유니티 기초

몬스터 2초 후 삭제, 아이템 드랍, 아이템 씬에서 제거 후 아이템 로그 출력

다모아 2023. 8. 10. 18:01

https://m.blog.naver.com/gold_metal/220526236275

 

[유니티 기초] 17. 아이템 줍고 장착하기

안녕하세요. 골드메탈입니다. 오늘은 액션 RPG에서는 없어선 안될 아이템을 줍고 장착하는 기능을 ...

blog.naver.com

 

ItemGenerator

using Real;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Test3
{
    public class ItemGenerator : MonoBehaviour
    {

        [SerializeField]
        private List<GameObject> prefabList;

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

        }

        public void Generate(GameEnums.eItemType itemType, Vector3 position)
        {
            //인덱스화
            int index = (int)itemType;
            //프리팹 선택
            GameObject prefab = prefabList[index];
            //인스턴스화
            GameObject go = Instantiate(prefab);
            //위치지정
            go.transform.position = position;

        }
    }
}

 

MonsterGenerator

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

namespace Test3
{
    public class MonsterGenerator : MonoBehaviour
    {
        //[SerializeField] private GameObject turtlePrefab;
        //[SerializeField] private GameObject slimePrefab;
        [SerializeField]
        private List<GameObject> prefabList; //동적배열 (컬렉션 사용전 반드시 인스턴스화)

        // Start is called before the first frame update
        void Start()
        {
            //int index = 0;
            //foreach(GameObject prefab in this.prefabList)
            //{
            //    Debug.LogFormat("index: {0}, prefab: {1}",index++, prefab);
            //}

            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">생성된 몬스터의 World Position 초기월드좌표</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); //위치를 결정하지 않은 상태이기 때문 (프리팹의 설정된 위치에 생성됨)

            //if(go.GetComponent<MonsterController>() != null)
            //{
            //    //부착되어 있다면 컴포넌트를 제거
            //    Destroy(go.GetComponent<MonsterController>());
            //}

            ////게임오브젝트에 MonsterController가 부착되어 있지 않다면
            //if(go.GetComponent<MonsterController>() == null)
            //{

            //}
            //동적으로 컴포넌트를 부착할 수 있음
            //MonsterController controller = go.AddComponent<MonsterController>();
            //위치를 설정
            go.transform.position = initPosition;

            return go.GetComponent<MonsterController>();
            //if(monsterType == GameEnums.eMonsterType.Turtle)
            //{
            //    Instantiate(this.turtlePrefab) ;
            //}
            //else if(monsterType == GameEnums.eMonsterType.Slime)
            //{
            //    Instantiate(this.slimePrefab);
            //}

            //switch (monsterType)
            //{
            //    case GameEnums.eMonsterType.Turtle:
            //        Instantiate(this.turtlePrefab);
            //        break;

            //    case GameEnums.eMonsterType.Slime:
            //        Instantiate(this.slimePrefab);
            //        break;
            //}


        }
    }
}

 

메인

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

namespace Test3
{
    //씬의 모든 객체들을 관리
    public class Test_CreatePortalMain : MonoBehaviour
    {
        [SerializeField]
        private HeroController heroController;
        [SerializeField]
        private MonsterGenerator monsterGenerator;
        [SerializeField]
        private ItemGenerator itemGenerator;

        [SerializeField]
        private GameObject portal;

        private List<MonsterController> monsterList;

        // Start is called before the first frame update
        void Start()
        {
            //컬렉션 사용전 반드시 초기화
            this.monsterList = new List<MonsterController>();
            MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
            turtle.onDie = (rewardItemType) => {
                Debug.Log("죽음");
                this.CreateItem(rewardItemType, turtle.transform.position);
                Destroy(turtle.gameObject);
            };
            MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
            slime.onDie = (rewardItemType) => {
                Debug.Log("죽음");
                this.CreateItem(rewardItemType, slime.transform.position);
                Destroy(slime.gameObject);
            };

            //만들어진 개체들을 그룹화 관리
            //배열, 컬렉션
            //동적 배열
            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);
            }
        }

        // Update is called once per frame
        void Update()
        {
            //Test
            //Ray연습할겸 클릭해서 선택 몬스터를 제거하자
            if(Input.GetMouseButtonDown(0))
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);

                RaycastHit hit;

                if(Physics.Raycast(ray, out hit, 100f))
                {
                    //if(hit.collider.tag == "Monster")
                    //{
                    //    int i = 0;
                    //    Debug.LogFormat("hit.collider.tag: {0}", hit.collider.tag);
                    //    Destroy(hit.collider.gameObject);
                    //    this.monsterList.Remove(monsterList[i++]);
                    //    Debug.LogFormat("남은 몬스터의 수: {0}", monsterList.Count);
                    //    if(monsterList.Count == 0)
                    //    {
                    //        this.CreatePortal();
                    //    }
                    //}
                    MonsterController controller = hit.collider.gameObject.GetComponent<MonsterController>();
                    if(controller != null)
                    {
                        this.monsterList.Remove(controller);
                        //Destroy(controller.gameObject);
                        //this.CreateItem(GameEnums.eItemType.Sword, controller.transform.position);
                        //몬스터 죽는 애니메이션 플레이
                        controller.Die();
                        //this.CreateItem(GameEnums.eItemType.Sword, controller.gameObject.transform.position);
                        
                        Debug.LogFormat("남은 몬스터의 수: {0}", monsterList.Count);
                        if(monsterList.Count <= 0)
                        {
                            this.CreatePortal();
                        }
                    }
                }
            }
        }
        private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            this.itemGenerator.Generate(itemType, position);
        }

        private void CreatePortal()
        {
            this.StartCoroutine(this.CoCreatePortal());
        }

        private IEnumerator CoCreatePortal()
        {
            yield return new WaitForSeconds(2.0f);
            float randX = Random.Range(-3f, 3f);
            float randZ = Random.Range(-3f, 3f);
            this.portal.transform.position = new Vector3(randX, 0f, randZ);
            this.portal.SetActive(true);
        }
    }
}

 

HeroController

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

namespace Test3
{
    public class HeroController : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {

        }
        private void OnTriggerEnter(Collider other)
        {
            var item = other.gameObject.GetComponent<ItemController>();

            if (other.tag == "Sword")
            {
                Debug.Log("칼을 획득했습니다.");
                Destroy(other.gameObject);
                Debug.LogFormat("itemType: {0}", item.ItemType);
                this.EquipItem(item.ItemType);
            }
            else if (other.tag == "Shield")
            {
                Debug.Log("방패를 획득했습니다.");
                Destroy(other.gameObject);
                Debug.LogFormat("itemType: {0}", item.ItemType);
            }
            else if (other.tag == "Potion")
            {
                Debug.Log("포션을 획득했습니다.");
            }
        }

        private void EquipItem(GameEnums.eItemType itemType)
        {
            GameObject playerEquip = GameObject.FindGameObjectWithTag("EquipSword");
            this.transform.SetParent(playerEquip.transform);
        }
    }
}

 

MonsterController

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

namespace Test3
{
    public class MonsterController : MonoBehaviour
    {
        private Animator anim;

        public GameEnums.eItemType rewardItemType;

        public System.Action<GameEnums.eItemType> onDie;
        // Start is called before the first frame update
        void Start()
        {
            this.anim = this.GetComponent<Animator>();
        }

        public void Die()
        {
            this.StartCoroutine(this.CoDie());
        }

        private IEnumerator CoDie()
        {
            this.anim.SetInteger("State", 3);
            yield return new WaitForSeconds(2.0f);
            this.onDie(rewardItemType);
        }
    }
}

 

ItemController

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

namespace Test3
{
    public class ItemController : MonoBehaviour
    {
        [SerializeField]
        private GameEnums.eItemType itemType;

        public GameEnums.eItemType ItemType
        {
            get
            {
                return this.itemType;
            }
        }
        // Start is called before the first frame update
        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {

        }
    }
}

 

GameEnums

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

public class GameEnums
{
    public enum eItemType
    {
        Sword, Shield, Potion
    }
    public enum eMonsterType
    {
        Turtle, Slime
    }



}