K-digital traning/유니티 기초

몬스터 처지 후 아이템 드롭 + 장착

내꺼블로그 2023. 8. 10. 18:17

1.GameEnums.cs

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

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

    public enum eItemType
    {
        Sword, Shield, HealthPotion
    }

    public enum eHeroState
    {
        Idle, Run, Attack
    }

    public enum eMonsterState
    {
        Idle, Die=3
    }
}

 

 

 

2.ItemGenerator.cs

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

namespace Test3
{
    public class ItemGenerator : MonoBehaviour
    {
        [SerializeField]
        private List<GameObject> itemPrefabs;

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

        }

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

        }

        public ItemController GenerateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            GameObject prefab = itemPrefabs[(int)itemType];
            GameObject item = Instantiate(prefab);
            item.transform.position = position;
            return item.GetComponent<ItemController>();
        }
    }
}

 

 

 

 

3.ItemController.cs

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 itemType; } }
        //// Start is called before the first frame update
        //void Start()
        //{

        //}

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

        //}
    }
}

 

 

 

 

4.MonsterGenerator.cs

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace Test3
{
    public class MonsterGenerator : MonoBehaviour
    {
        //[SerializeField]
        //private GameObject TurtlePrefpb;
        //[SerializeField]
        //private GameObject SlimPrefab;

        [SerializeField]
        private List<GameObject> prefabList;
        // Start is called before the first frame update
        //void Start()
        //{
         
        //}

        /// <summary>
        /// 몬스터 생성
        /// </summary>
        /// <param name="monsterType">생성 하려고 하는 몬스터의 타입</param>
        /// <param name="initPosition">생성된 몬스터의 초기 월드좌표param>
        public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
        {
            Debug.LogFormat("monster: {0}", monsterType);
            //몬스터 타입에 따라 어떤 프리팹으로 복사본(인스턴스)를 생성할지 결정 해야 함

            int index = (int)monsterType;

            GameObject prefab = this.prefabList[index];

            Debug.LogFormat("prefab: {0}", index);
            GameObject go = Instantiate(prefab);        //위치를 결정 하지 않은 상태이기때문(프리팹에 설정된 위치에 생성됨)
            go.transform.position = initPosition;

            return go.GetComponent<MonsterController>();

            ////게임오브젝트에 MonsterController가 이미 부착되어 있다면
            //if (go.GetComponent<MonsterController>() != null)
            //{
            //    Destroy(go.GetComponent<MonsterController>());
            //}
            //go.AddComponent<MonsterController>();

            ////게임오브젝트에 MonsterController가 부착 되어 있지 않다면
            //if (go.GetComponent<MonsterController>() == null)
            //{
            //    //동적으로 컴포넌트를 부착 할 수 있음.
            //    MonsterController controller = go.AddComponent<MonsterController>();
            //}
        }
    }
}

 

 

 

 

5.MonsterController.cs

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

namespace Test3
{
    public class MonsterController : MonoBehaviour
    {
        [SerializeField]
        private GameEnums.eItemType itemType;
        private Animator anim;
        public System.Action<GameEnums.eItemType> onDie;
        private GameEnums.eMonsterState monsterState;
        // Start is called before the first frame update
        void Awake()
        {
            anim=this.GetComponent<Animator>();
        }

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

        //}

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

        private IEnumerator CoDie()
        {
            this.monsterState = GameEnums.eMonsterState.Die;
            this.anim.SetInteger("State", (int)this.monsterState);
            Debug.LogFormat("monster state: {0}", this.monsterState);
            AnimatorStateInfo animatorStateInfo = this.anim.GetCurrentAnimatorStateInfo(0);
            yield return new WaitForSeconds(animatorStateInfo.length);
            onDie(this.itemType);
            yield return null;
        }
    }
}

 

 

6.HeroController.cs

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

namespace Test3
{
    public class HeroController : MonoBehaviour
    {
        private Vector3 targetPosition;
        private Coroutine moveRoutine;
        private Animator anim;
        GameEnums.eHeroState state;
        public System.Action<ItemController> onGetItem;

        private ItemController leftHandItemController;
        private ItemController rightHandItemController;

        // Start is called before the first frame update
        void Start()
        {
            anim = this.GetComponent<Animator>();
        }

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

        //}

        public void Move(Vector3 targetPosition)
        {
            this.targetPosition = targetPosition;
            this.transform.LookAt(this.targetPosition);
            this.PlayAnimation(GameEnums.eHeroState.Run);
        }

        private void PlayAnimation(GameEnums.eHeroState state)
        {
            this.state = state;
            this.anim.SetInteger("State", (int)this.state);
            switch (this.state)
            {
                case GameEnums.eHeroState.Run:
                    if (moveRoutine != null)
                        StopCoroutine(moveRoutine);
                    moveRoutine = StartCoroutine(CoMove());
                    break;
            }
        }

        private IEnumerator CoMove()
        {
            while (true)
            {
                this.transform.Translate(Vector3.forward * Time.deltaTime);
                float distance = Vector3.Distance(this.targetPosition, this.transform.position);
                if (distance < 0.1f)
                {
                    break;
                }
                yield return null;
            }
            moveRoutine = null;
            this.PlayAnimation(GameEnums.eHeroState.Idle);
        }

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Item")
            {
                if(moveRoutine!=null)
                    StopCoroutine(moveRoutine);
                Debug.LogFormat("moveroutine: {0}", this.moveRoutine);
                PlayAnimation(GameEnums.eHeroState.Idle);
                ItemController item = other.GetComponent<ItemController>();
                onGetItem(item);
            }
        }

        public void SetItem(GameObject item)
        {
            ItemController itemController = item.GetComponent<ItemController>();
            GameEnums.eItemType itemType = itemController.ItemType;
            switch (itemType)
            {
                case GameEnums.eItemType.Sword:
                    GameObject preSwordGo = GameObject.Find("SwordPolyart");
                    preSwordGo.transform.SetParent(null);
                    preSwordGo.transform.position = this.transform.position;
                    preSwordGo.transform.Translate(0.5f, 0, 0.5f);
                    GameObject swordGo = GameObject.Find("Weapon");
                    Debug.LogFormat("swordGo: {0}", swordGo);
                    item.transform.position = swordGo.transform.position;
                    item.transform.SetParent(swordGo.transform);
                    break;
                case GameEnums.eItemType.Shield:
                    GameObject preShieldGo = GameObject.Find("ShieldPolyart");
                    preShieldGo.transform.SetParent(null);
                    preShieldGo.transform.position = this.transform.position;
                    preShieldGo.transform.Translate(0.5f, 0, 0.5f);
                    GameObject shieldGo = GameObject.Find("Shield");
                    Debug.LogFormat("shieldGo: {0}", shieldGo);
                    item.transform.position = shieldGo.transform.position;
                    item.transform.SetParent(shieldGo.transform);
                    break;
                case GameEnums.eItemType.HealthPotion:
                    break;
            }
        }
    }
}

 

 

 

 

7.Test_CreatePortalMain.cs

using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;

namespace Test3
{
    //씬의 모든 객체들을 관리하는 클래스 (컴포넌트)
    public class Test_CreatePortalMain : MonoBehaviour
    {
        [SerializeField]
        private MonsterGenerator monsterGenerator;

        [SerializeField]
        private GameObject portalPrefab;

        [SerializeField]
        private ItemGenerator itemGenerator;

        private List<MonsterController> monsterList;
        private List<ItemController> itemList;

        [SerializeField]
        private GameObject heroPrefab;

        private HeroController heroController;

        //private GameObject hero;
        // Start is called before the first frame update
        void Start()
        {
            //컬렉션 사용전 반드시 초기화
            this.monsterList = new List<MonsterController>();
            this.itemList = new List<ItemController>();
            MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
            //turtle.onDie = (item) =>
            //{
            //    ItemController itemController = this.CreateItem(item, turtle.transform.position);
            //    itemList.Add(itemController);
            //    Destroy(turtle.gameObject);
            //    monsterList.Remove(turtle);
            //    Debug.LogFormat("count: {0}", monsterList.Count);
            //    if (monsterList.Count == 0)
            //    {
            //        this.CompleteAttackMonster();
            //    }
            //};
            MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
            //slime.onDie = (item) =>
            //{
            //    ItemController itemController = this.CreateItem(item, slime.transform.position);
            //    itemList.Add(itemController);
            //    Destroy(slime.gameObject);
            //    monsterList.Remove(slime);
            //    Debug.LogFormat("count: {0}", monsterList.Count);
            //    if (monsterList.Count == 0)
            //    {
            //        this.CompleteAttackMonster();
            //    }
            //};

            //만들어진 개체들을 그룹화 관리
            monsterList.Add(turtle);
            monsterList.Add(slime);
            Debug.LogFormat("this.monsterList.Count: {0}", this.monsterList.Count);
            foreach (MonsterController monster in this.monsterList)
            {
                Debug.LogFormat("monster: {0}", monster);
            }

            //몬스터 대리자
            for(int i=0;i<monsterList.Count;i++)
            {
                MonsterController temp = monsterList[i];
                temp.onDie = (item) =>
                {
                    ItemController itemController = this.CreateItem(item, temp.transform.position);
                    itemList.Add(itemController);
                    Destroy(temp.gameObject);
                    monsterList.Remove(temp);
                    Debug.LogFormat("count: {0}", monsterList.Count);
                    if (monsterList.Count == 0)
                    {
                        this.CompleteAttackMonster();
                    }
                };
            }
            
        }

        // Update is called once per frame
        void Update()
        {
            //Test
            //Ray연습할겸 클릭해서 선택 몬스터를 제거하자
            //화면을 클릭하면 Ray를 만든다
            //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))
                {
                    Debug.LogFormat("collider: {0}", hit.collider.tag);
                    if (hit.collider.tag == "Monster")
                    {
                        hit.collider.GetComponent<MonsterController>().Die();
                    }
                    else
                    {
                        if(monsterList.Count == 0)
                        {
                            float x = hit.point.x;
                            float z = hit.point.z;
                            Vector3 targetPosition = new Vector3(x, 0, z);
                            this.heroController.Move(targetPosition);

                        }
                    }
                }
            }
        }

        IEnumerator CoCreatePortal()
        {
            yield return new WaitForSeconds(0.3f);
            GameObject portal = Instantiate(portalPrefab);

            float x = Random.Range(-3.7f, 3.7f);
            float z = Random.Range(-3.7f, 3.7f);
            portal.transform.position = new Vector3(x, 0, z);
        }

        IEnumerator CoCreateHero()
        {
            yield return new WaitForSeconds(0.3f);
            GameObject hero = Instantiate(heroPrefab);
            float x = Random.Range(-3.7f, 3.7f);
            float z = Random.Range(-3.7f, 3.7f);
            hero.transform.position = new Vector3(x, 0, z);
            heroController=hero.GetComponent<HeroController>();
            heroController.onGetItem = (item) =>
            {
                Debug.LogFormat("{0}을 획득하였습니다.", item.ItemType);
                itemList.Remove(item);
                //Destroy(item.gameObject);
                heroController.SetItem(item.gameObject);
            };
        }

        private ItemController CreateItem(GameEnums.eItemType item, Vector3 position)
        {
            return this.itemGenerator.GenerateItem(item, position);
        }

        private void CompleteAttackMonster()
        {
            StartCoroutine(CoCreatePortal());
            StartCoroutine(CoCreateHero());
        }
    }
}

 

 

 

 

 

 

 

 

 

추가할 예정임다,,,,

'K-digital traning > 유니티 기초' 카테고리의 다른 글

[주말과제]SimpleRPG  (1) 2023.08.14
[주말과제] 이동 및 몬스터 공격  (0) 2023.08.07
애니메이션 전환 연습  (0) 2023.08.03
캐릭터 이동(달리기) 애니메이션  (0) 2023.08.03
ClimbCloud  (0) 2023.08.02