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 float turnSpeed = 10.0f;
        private void Start()
        {
            targetPosition = transform.position;
            heroAnimator = GetComponent<Animator>();
        }

        private void Update()
        {
            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);
                heroAnimator.SetInteger("state", 1);
            }
            else
            {
                heroAnimator.SetInteger("state", 0); 
            }

        }

        public void SetTargetPosition(Vector3 position)
        {
            targetPosition = position;
        }

        public void CollectItem(ItemController item)
        {
            EquipItem(item);
            onItemCollected?.Invoke(item);
        }

        private 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:
                    // 체력 회복 로직 or 다른 액션
                    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 System.Collections.Generic;
using UnityEngine;

namespace Test_Portal
{
    public class ItemController : MonoBehaviour
    {
        public string itemName;
        public GameEnums.eItemType itemType;
        private void OnTriggerEnter(Collider other)
        {
            if (other.CompareTag("Hero"))
            {
                HeroController hero = other.GetComponent<HeroController>();
                if (hero != null)
                {
                    hero.CollectItem(this);
                }
            }
        }
    }
}
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;

        private Transform monsterTarget;

 


        [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));

            hero = this.heroGenerator.Generate(heroPrefab, new Vector3(3, 0, 3));


            //만들어진 개체들을 그룹화 관리 
            //배열, 컬렉션 
            //동적 배열 
            this.monsterList.Add(turtle);
            this.monsterList.Add(slime);

            Debug.LogFormat("this.monsterList.Count: {0}", this.monsterList.Count);
            //리스트의 요소를 출력 
            foreach (MonsterController monster in this.monsterList)
            {
                Debug.LogFormat("monster: {0}", monster);
                monster.OnMonsterDied += (position, itemType) => HandleMonsterDied(position, itemType);
            }

        }


        private void Update()
        {
            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)
                    {
                        monsterHit.Die(); // 몬스터 죽음 메서드 호출
                       
                        monsterList.Remove(monsterHit);
                        //Destroy(monsterHit.gameObject,2.5f);

                        if (this.monsterList.Count == 0)
                        {
                            this.potalObject.SetActive(true);
                        }
                    }
                    // 아이템이 클릭된 경우
                    else if (itemHit != null)
                    {
                        // 히어로를 해당 아이템 위치로 이동
                        HeroController hero = FindObjectOfType<HeroController>();
                        if (hero != null)
                        {
                            hero.SetTargetPosition(itemHit.transform.position);
                        }
                    }
                    //바닥이나 기타 오브젝트가 클릭된 경우
                    else
                    {
                        // 히어로를 클릭한 위치로 이동
                        HeroController hero = FindObjectOfType<HeroController>();
                        if (hero != null)
                        {
                            Vector3 targetPos = hit.point;
                            targetPos.y = hero.transform.position.y; // 현재 히어로의 Y축 값을 유지
                            hero.SetTargetPosition(targetPos);
                        }
                    }
                }
            }
        }

        
        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);
        }

        public void GenerateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            itemGenerator.Generate(itemType, position);
        }
    }
}
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 UnityEngine;

namespace Test_Portal
{
    public class ItemGenerator : MonoBehaviour
    {
        [SerializeField]
        private List<GameObject> itemPrefabs;    // 아이템 프리팹들의 리스트

        // Start is called before the first frame update
        void Start()
        {
            for (int i = 0; i < this.itemPrefabs.Count; i++)
            {
                GameObject prefab = this.itemPrefabs[i];
                Debug.LogFormat("index: {0}, prefab: {1}", i, prefab);
            }
        }

        /// <summary>
        /// 아이템 생성
        /// </summary>
        /// <param name="itemType">생성하려는 아이템의 타입</param>
        /// <param name="initPosition">생성된 아이템의 초기 월드좌표</param>
        public ItemController Generate(GameEnums.eItemType itemType, Vector3 initPosition)
        {
            Debug.LogFormat("itemType: {0}", itemType);
            int index = (int)itemType;
            Debug.LogFormat("index: {0}", index);
            GameObject prefab = this.itemPrefabs[index];
            Debug.LogFormat("prefab: {0}", index);
            GameObject go = Instantiate(prefab);
            go.transform.position = initPosition;

            ItemController itemController = go.GetComponent<ItemController>();
            itemController.itemType = itemType;   // itemType 설정

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

namespace Test_Portal
{
    public class MonsterGenerator : MonoBehaviour
    {
      

        [SerializeField]
        private List<GameObject> prefabList;    //동적 배열 (컬렉션 사용전 반드시 인스턴스화)

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

            for (int i = 0; i < this.prefabList.Count; i++)
            {
                GameObject prefab = this.prefabList[i];
                Debug.LogFormat("index: {0}, prefab: {1}", i, prefab);
            }
        }

        /// <summary>
        /// 몬스터 생성 
        /// </summary>
        /// <param name="monsterType">생성 하려고 하는 몬스터의 타입</param>
        /// <param name="initPosition">생성된 몬스터의 초기 월드좌표</param>
        public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
        {
            Debug.LogFormat("monsterType: {0}", monsterType);
            //몬스터 타입에 따라 어떤 프리팹으로 프리팹 복사본(인스턴스)를 생성할지 결정 해야 함 
            //몬스터 타입을 인덱스로 변경 
            int index = (int)monsterType;
            Debug.LogFormat("index: {0}", index);
            //프리팹 배열에서 인덱스로 프리팹 가져옴
            GameObject prefab = this.prefabList[index];
            Debug.LogFormat("prefab: {0}", index);
            //프리팹 인스턴스를 생성 
            GameObject go = Instantiate(prefab);    //위치를 결정 하지 않은 상태이기때문 (프리팹의 설정된 위치에 생성됨)
            //위치를 설정
            go.transform.position = initPosition;

            return go.GetComponent<MonsterController>();
        }
    }

}
using System.Collections;
using UnityEngine;

namespace Test_Portal
{
    public class MonsterController : MonoBehaviour
    {
        // Delegate 및 Event 수정
        public delegate void MonsterDied(Vector3 position, GameEnums.eItemType itemType);
        public event MonsterDied OnMonsterDied;

        public GameEnums.eItemType dropItemType;
        private Animator anim;

        private void Start()
        {
            anim = GetComponent<Animator>();
        }

        public void Die()
        {
            anim.SetInteger("state", 3);
            StartCoroutine(DieCoroutine());
        }

        IEnumerator DieCoroutine()
        {
            yield return new WaitForSeconds(2.5f); // 2.5초 기다림 (애니메이션 재생 시간)

            OnMonsterDied?.Invoke(transform.position, dropItemType); // 이벤트 발생

            Destroy(this.gameObject); // 몬스터 파괴
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using Test_Portal;
using UnityEngine;



namespace Test_Portal
{
    public class HeroGenerator : MonoBehaviour
{
   
    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)
    {
       
        heroPrefab = Instantiate(prefab);
        heroPrefab.transform.position = initPosition;
        return heroPrefab.GetComponent<HeroController>();
    }
    }
}

반응형

+ Recent posts