using System.Collections;
using UnityEngine;

public class BossController : MonoBehaviour
{
    public float detectionRange = 3f;
    public float attackRange = 2f;
    public float moveSpeed = 1f;

    private GameObject Hero;
    private int state = 0;
    private Animator animator;  // 애니메이터 컴포넌트 참조 추가

    private void Start()
    {
        animator = GetComponent<Animator>();  // 애니메이터 컴포넌트 초기화
        StartCoroutine(LateStart());
    }

    IEnumerator LateStart()
    {
        yield return new WaitForSeconds(0.1f);
        Hero = GameObject.FindGameObjectWithTag("Hero");
    }

    private void Update()
    {
        if (Hero == null)
        {
            Hero = GameObject.FindGameObjectWithTag("Hero");
            if (Hero == null)
            {
                Debug.LogError("Hero not found in the scene.");
                return;
            }
            else
            {
                Debug.Log("Hero found.");
            }
        }

        switch (state)
        {
            case 0:
                Idle();
                break;
            case 1:
                Chase();
                break;
            case 2:
                Attack();
                break;
        }

        animator.SetInteger("state", state);  // 애니메이터에 상태값 전달
    }

    void Idle()
    {
        float distance = Vector3.Distance(transform.position, Hero.transform.position);
        if (distance <= detectionRange)
            state = 1;
    }

    void Chase()
    {
        float distance = Vector3.Distance(transform.position, Hero.transform.position);

        if (distance <= attackRange)
        {
            state = 2;
            return;
        }

        Vector3 moveDirection = (Hero.transform.position - transform.position).normalized;

        // 플레이어와의 거리와 다음 프레임에서의 이동 거리를 비교
        float nextStepDistance = moveSpeed * Time.deltaTime;
        if (distance > nextStepDistance)  // 만약 이동 거리가 플레이어와의 거리보다 짧으면 이동
        {
            transform.position += moveDirection * nextStepDistance;
        }
        else  // 그렇지 않다면, 플레이어 바로 앞에서 멈춤
        {
            transform.position = transform.position + moveDirection * distance;
        }
    }

    void Attack()
    {
        float distance = Vector3.Distance(transform.position, Hero.transform.position);
        if (distance > attackRange)
            state = 1;
            return;
    }

    public void SetHero(GameObject newHero)
    {
        Hero = newHero;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace BossScene
{
    public class BossGenerator : MonoBehaviour
    {
        private GameObject bossPrefab;    //hero 프리팹

        // Start is called before the first frame update
        void Start()
        {

        }


        public BossController Generate(GameObject prefab, Vector3 initPosition)
        {

            bossPrefab = Instantiate(prefab);
            bossPrefab.transform.position = initPosition;
            return bossPrefab.GetComponent<BossController>();
        }
    }










}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Test_Portal
{
    // 히어로의 움직임과 행동을 제어하는 클래스
    public class HeroController : MonoBehaviour
    {
        public float moveSpeed = 5.0f;          // 히어로의 움직임 속도
        private Vector3 targetPosition;         // 히어로의 이동 대상 위치
        public static event Action<ItemController> onItemCollected;  // 아이템 수집 시 발생하는 이벤트
        private Animator heroAnimator;          // 히어로의 애니메이터 컴포넌트
        private bool isInAttackAnimation = false;
        private float turnSpeed = 10.0f;        // 회전 속도
        public GameObject hitParticlePrefab;
        // 공격 대상이 되는 몬스터
        private MonsterController attackTarget = null;
        public float attackRange = 2f;        // 공격 가능한 거리

        private void Start()
        {
            targetPosition = transform.position;     // 시작 위치 초기화
            heroAnimator = GetComponent<Animator>(); // 애니메이터 컴포넌트 초기화
            StartCoroutine(HeroMovementUpdate());
        }
        private IEnumerator HeroMovementUpdate()
        {
            while (true)
            {
                if (attackTarget != null)
                {
                    float distance = Vector3.Distance(transform.position, attackTarget.transform.position);
                    if (distance <= attackRange)
                    {
                        if (!isInAttackAnimation) // 이미 공격 중이 아니라면 공격을 시작합니다.
                        {
                            isInAttackAnimation = true;
                            heroAnimator.SetInteger("state", 2);
                            yield return new WaitForSeconds(0.5f); // 공격 애니메이션 지속 시간
                            isInAttackAnimation = false;
                            continue;
                        }
                    }
                }


                // 움직임 로직 (공격 애니메이션 중에도 실행되도록 변경)
                if (Vector3.Distance(transform.position, targetPosition) > 0.1f)
                {
                    Quaternion targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
                    transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
                    transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);

                    // 움직이는 중이며 공격 애니메이션 중이 아닐 때만 움직임 애니메이션을 플레이
                    if (!isInAttackAnimation)
                    {
                        heroAnimator.SetInteger("state", 1);
                    }
                }
                else
                {
                    if (!isInAttackAnimation)
                    {
                        heroAnimator.SetInteger("state", 0);
                    }
                }

                yield return null;  // Yield every frame
            }
        }

        public void TriggerAttack()
        {
            if (attackTarget)
            {
                // 파티클 생성
                GameObject hitParticle = Instantiate(hitParticlePrefab, attackTarget.transform.position, Quaternion.identity);
                Destroy(hitParticle, 3f);  // 파티클 애니메이션 끝나면 3초 후에 파괴 (3초는 예시로 설정한 값이며 필요에 따라 조절)

                attackTarget.Die();
                isInAttackAnimation = false;
                attackTarget = null; // 공격 대상 초기화
                targetPosition = transform.position;
            }
        }

        // 공격 대상을 설정하는 메서드
        public void SetAttackTarget(MonsterController monster)
        {
            attackTarget = monster;

            Vector3 directionToMonster = (monster.transform.position - transform.position).normalized;
            Vector3 attackPosition = monster.transform.position - directionToMonster * (attackRange * 0.9f);
            SetTargetPosition(attackPosition);
        }

        // 히어로의 이동 대상 위치 설정
        public void SetTargetPosition(Vector3 position)
        {
            targetPosition = position;
        }

        // 아이템을 수집하는 메서드
        public void CollectItem(ItemController item)
        {
            EquipItem(item);
            onItemCollected?.Invoke(item);
        }

        // 아이템을 장착하는 메서드
        public void EquipItem(ItemController item)
        {
            GameEnums.eItemType itemType = item.itemType;
            switch (itemType)
            {
                case GameEnums.eItemType.Sword:
                    EquipToSlot(item.gameObject, "Weapon");
                    break;
                case GameEnums.eItemType.Shield:
                    EquipToSlot(item.gameObject, "Shield");
                    break;
                case GameEnums.eItemType.Potion:
                    // 추가적인 로직(체력 회복 등)을 여기에 구현
                    break;
            }
        }

        // 특정 슬롯에 아이템을 장착하는 메서드
        private void EquipToSlot(GameObject item, string slotName)
        {
            Transform slotTransform = FindChildWithName(this.transform, slotName);

            if (slotTransform == null)
            {
                Debug.LogError("Cannot find slot with name: " + slotName);
                return;
            }

            foreach (Transform child in slotTransform)
            {
                Destroy(child.gameObject);  // 이전에 장착되어 있던 아이템 제거
            }

            Destroy(item.GetComponent<BoxCollider>());

            item.transform.SetParent(slotTransform); // 아이템을 해당 슬롯에 부착
            item.transform.localPosition = Vector3.zero;
            item.transform.localRotation = Quaternion.identity;
        }

        // 이름을 기반으로 자식 오브젝트를 찾는 메서드
        private Transform FindChildWithName(Transform parent, string name)
        {
            foreach (Transform child in parent)
            {
                if (child.name == name)
                {
                    return child;
                }

                Transform found = FindChildWithName(child, name);
                if (found != null)
                {
                    return found;
                }
            }
            return null;
        }



    }
}
using System.Collections;
using UnityEngine;

namespace Test_Portal
{
    // 몬스터를 제어하는 클래스
    public class MonsterController : MonoBehaviour
    {
        // 몬스터가 죽었을 때 호출될 이벤트와 대리자(delegate) 선언
        public delegate void MonsterDied(Vector3 position, GameEnums.eItemType itemType);
        public event MonsterDied OnMonsterDied;

        // 죽는 애니메이션 시간
        private float deathAnimationTime = 2f;

        // 몬스터가 드롭할 아이템의 종류
        public GameEnums.eItemType dropItemType;

        // 애니메이션 컨트롤러
        private Animator anim;

        private void Start()
        {
            // 시작할 때 애니메이터 컴포넌트를 가져옵니다.
            anim = GetComponent<Animator>();
        }

        // 몬스터가 죽을 때 호출될 함수
        public void Die()
        {
            anim.SetInteger("state", 3);
            StartCoroutine(DieCoroutine());
        }

        // 죽는 애니메이션 후 몬스터를 파괴하는 코루틴
        private IEnumerator DestroyAfterAnimation()
        {
            yield return new WaitForSeconds(deathAnimationTime);
            Destroy(this.gameObject);
        }

        // 몬스터가 죽을 때 이벤트를 호출하고 몬스터를 파괴하는 코루틴
        IEnumerator DieCoroutine()
        {
            yield return new WaitForSeconds(deathAnimationTime);

            OnMonsterDied?.Invoke(transform.position, dropItemType);
            Destroy(this.gameObject);
            yield return null;
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

namespace Test_Portal
{
    
    public class PortalController : MonoBehaviour
    {
        private FadeOutEffect fadeOut;
        public string nextSceneName;
        public Image fadeOutImage;

        private void Start()
        {
            fadeOut = FindObjectOfType<FadeOutEffect>();
        }

        private void OnTriggerEnter(Collider other)
        {
            if (other.CompareTag("Hero"))
            {
                StartCoroutine(fadeOut.FadeOutRoutine(fadeOutImage));
                GameManager.SetPlayer(other.gameObject);
                SceneManager.LoadScene(nextSceneName);
            }
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Test_Portal
{
    public class GameEnums
    {
        public enum eMonsterType
        {
            Turtle, Slime
        }

        public enum eItemType
        {
            Potion,Sword,Shield
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using Test_Portal;
using UnityEngine;
using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;

namespace Test_Portal
{
    // 씬의 모든 객체들을 관리하는 클래스(컴포넌트)
    public class Test_CreatePortalMain : MonoBehaviour
    {
        // 변수 선언 영역
        [SerializeField]
        private MonsterGenerator monsterGenerator; // 몬스터 생성 클래스
        [SerializeField] private GameObject heroPrefab; // 히어로 프리팹

        [SerializeField] private HeroGenerator heroGenerator; // 히어로 생성 클래스
        [SerializeField] private HeroController hero; // 히어로 컨트롤러

        [SerializeField]
        private ItemGenerator itemGenerator; // 아이템 생성 클래스

        private Camera camera; // 메인 카메라
        private List<MonsterController> monsterList; // 현재 씬에 있는 몬스터 리스트
        public GameObject potalObject; // 포탈 오브젝트

        [SerializeField]
        private Text txtMonsterCount; // 화면에 보여지는 몬스터 카운트

        [SerializeField]
        private Text txtGetItem; // 아이템 획득 시 화면에 보여지는 텍스트

        private void Awake()
        {
            camera = Camera.main; // 카메라 초기화
            hero = FindObjectOfType<HeroController>(); // 히어로 컨트롤러 찾기
            HeroController.onItemCollected += HandleItemCollected; // 아이템 획득 이벤트 바인딩
        }

        void Start()
        {
            // 초기 몬스터와 히어로 생성 로직
            this.monsterList = new List<MonsterController>();

            // 몬스터 생성
            MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
            MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));

            // 히어로 생성
            if (!hero)
            {
                hero = this.heroGenerator.Generate(heroPrefab, new Vector3(3, 0, 3));
            }

            // 생성된 몬스터를 리스트에 추가
            this.monsterList.Add(turtle);
            this.monsterList.Add(slime);

            // 이벤트 바인딩
            foreach (MonsterController monster in this.monsterList)
            {
                monster.OnMonsterDied += HandleMonsterDied; // 바인딩 부분 수정
            }
        }

        private void Update()
        {
            // UI 업데이트 및 마우스 입력 처리
            this.UpdateScoreUI();

            if (Input.GetMouseButtonUp(1)) // 마우스 오른쪽 클릭 검사
            {
                RaycastHit hit;
                // 마우스 위치에서 레이캐스트 발사
                if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit))
                {
                    MonsterController monsterHit = hit.collider.GetComponent<MonsterController>();
                    ItemController itemHit = hit.collider.GetComponent<ItemController>();

                    // 몬스터 클릭 시 처리
                    if (monsterHit != null)
                    {
                        hero.SetAttackTarget(monsterHit);
                        if (this.monsterList.Count == 0)
                        {
                            this.potalObject.SetActive(true);
                        }
                    }
                    // 아이템 클릭 시 처리
                    else if (itemHit != null)
                    {
                        hero.SetTargetPosition(itemHit.transform.position);
                    }
                    // 그 외 영역 클릭 시 처리
                    else
                    {
                        Vector3 targetPos = hit.point;
                        targetPos.y = hero.transform.position.y; // Y축 값 유지
                        hero.SetTargetPosition(targetPos);
                    }
                }
            }
        }

        // 몬스터 카운트 UI 업데이트
        public void UpdateScoreUI()
        {
            this.txtMonsterCount.text = string.Format("남은 몬스터 수: {0}", this.monsterList.Count);
        }

        // 아이템 획득 시 텍스트 출력 후 일정 시간 후 숨기기
        private IEnumerator DeactivateTextAfterSeconds(float seconds)
        {
            yield return new WaitForSeconds(seconds);
            txtGetItem.gameObject.SetActive(false);
        }

        // 아이템 획득 이벤트 핸들러
        private void HandleItemCollected(ItemController item)
        {
            txtGetItem.text = "획득한 아이템: " + item.itemName;
            txtGetItem.gameObject.SetActive(true);
            StartCoroutine(DeactivateTextAfterSeconds(5));
        }

        // 몬스터 사망 이벤트 핸들러
        void HandleMonsterDied(Vector3 position, GameEnums.eItemType itemType)
        {
            GenerateItem(itemType, position);

            // 몬스터 리스트에서 제거
            MonsterController monster = monsterList.Find(m => m.transform.position == position);
            if (monster != null)
            {
                monsterList.Remove(monster);
            }

            UpdateScoreUI();

            // 포탈 활성화 조건
            if (monsterList.Count == 0)
            {
                potalObject.SetActive(true);
            }
        }

        // 아이템 생성 함수
        public void GenerateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            itemGenerator.Generate(itemType, position);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using Test_Portal;
using UnityEngine;



namespace Test_Portal
{
    public class HeroGenerator : MonoBehaviour
    {
        private Vector3 savedPosition = Vector3.zero;
        private GameObject heroPrefab;    //hero 프리팹

        // Start is called before the first frame update
        void Start()
        {
            //Debug.Log(heroPrefab.gameObject.name + "생성!");
        }
        /// <summary>
        /// 히어로 생성 
        /// </summary>
        /// <param name="initPosition">생성된 몬스터의 초기 월드좌표</param>


        public HeroController Generate(GameObject prefab, Vector3 initPosition)
        {
            GameObject heroInstance = Instantiate(prefab);
            heroInstance.transform.position = initPosition;
            return heroInstance.GetComponent<HeroController>();
        }
    }
}

 

반응형

+ Recent posts