본문 바로가기
KDT/유니티 기초

23/08/10 Test3 캐릭터 이동, 몬스터 제거 및 아이템 생성, 포탈 생성

by 잰쟁 2023. 8. 10.
728x90

Main

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

namespace Test3
{
    //씬에 있는 모든 객체들 관리(Hero,Monster,MonsterGenerator)하는 컴포넌트
    public class TestCreatePortalMain : MonoBehaviour
    {
        [SerializeField]
        private MonsterGenerator monsterGenerator;
        [SerializeField]
        private GameObject heroPrefab;
        [SerializeField]
        private GameObject portalPrefab;
        [SerializeField]
        private ItemGenerator itemGenerator;

        private HeroController heroController;
        private List<MonsterController> monsterList;

        // Start is called before the first frame update
        void Start()
        {
            //히어로 생성
            this.CreateHero();

            //몬스터 생성
            //컬렉션 사용전 반드시 초기화
            this.monsterList = new List<MonsterController>();  
            
            MonsterController turtle = this.monsterGenerator.Generate(GameEnums.eMonsterType.Turtle, new Vector3(-3, 0, 0));
            turtle.onDie = (rewardItemType) =>
            {
                Debug.Log("거북이 죽음");
                var pos = turtle.gameObject.transform. position;
                this.CreateItem(rewardItemType, pos);
                Destroy(turtle.gameObject);
            };
            MonsterController slime = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
            slime.onDie = (rewardItemType) =>
            {
                Debug.Log("슬라임 죽음");
                var pos = slime.gameObject.transform.position;
                this.CreateItem(rewardItemType, pos);
                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연습 클릭해서 선택 몬스터를 제거하자
            //화면을 클릭하면 Ray를 만든다
            if (Input.GetMouseButtonDown(0))
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                float maxDistance = 10f;
                //화면에 출력
                Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);
                //Ray사용하여 충돌체크
                RaycastHit hit;
                //몬스터와 충돌했다면
                if (Physics.Raycast(ray, out hit, maxDistance))
                {
                    //충돌 감지해서
                    Debug.LogFormat("hit.collider: {0}", hit.collider); 
                    MonsterController controller = hit.collider.gameObject.GetComponent<MonsterController>();
                        
                    //해당 몬스터를 제거
                    if (controller != null)
                    {
                         //리스트에서 제거
                         this.monsterList.Remove(controller);
                        Debug.LogFormat("this.monsterList.Count : {0}", this.monsterList.Count);
                        //몬스터 죽는 애니메이션 플레이
                         controller.Die();
                    }
                       
                    //남은 몬스터가 없다면 임의의 위치에 포털 생성
                    if (this.monsterList.Count <= 0)
                    {
                        this.CreatePortal();
                    }

                    //히어로 이동
                    this.heroController.Move(hit.point);


                }
            }
        }
        
        //히어로 생성 메서드
        private void CreateHero()
        {
            GameObject heroGo = Instantiate(this.heroPrefab);
            this.heroController = heroGo.GetComponent<HeroController>();
        }

        //포탈 생성 메서드
        private void CreatePortal()
        {
            GameObject portalGo = null;
           portalGo = Instantiate(this.portalPrefab);
            int x = Random.Range(-3, 3);
            int z = Random.Range(-3, 3);
            //위치 설정(랜덤)
           portalGo.transform.position = new Vector3(x, 0f, z);
        }

        //아이템 생성 메서드
        private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            this.itemGenerator.GenerateItem(itemType, position);
        }
    }
}

GameEnums

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

public class GameEnums
{
    //몬스터 타입
    public enum eMonsterType 
    { 
        Turtle, Slime
    }

    //아이템 타입
    public enum eItemType 
    { 
        Sword, Shield, Potion
    }
}

MonsterGenerator

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

        //몬스터 생성 메서드
        //"monsterType" : 생성하려고 하는 몬스터의 타입
        //"initPosition" : 생성된 몬스터의 초기 위치(월드좌표)s

        public MonsterController Generate(GameEnums.eMonsterType monsterType, Vector3 initPosition)
        {
            Debug.LogFormat("monsterType: {0}", monsterType);
            //몬스터 타입에 따라 어떤 프리팹으로 프리팹 복사본(인스턴스)를 생성할지 결정 해야함
            //Instantiate(프리팹)
            //몬스터 타입을 인덱스로 변경
            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)
            //{
            //    MonsterController controller = go.AddComponent<MonsterController>();
            //}            
            //위치를 설정
            go.transform.position = initPosition;

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

ItemGenerator

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

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

        private MonsterController monsterController;

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

        public void GenerateItem(GameEnums.eItemType itemType,Vector3 position)
        {
            Debug.LogFormat("itemType : {0}", itemType);
            
            //아이템 타입을 인덱스로 변경
            int index = (int)itemType;
            Debug.LogFormat("ItemIndex : {0}", index);
            //아이템 배열에서 인덱스로 아이템(프리팹)을 가져옴
            GameObject item = this.itemList[index];
            Debug.LogFormat("item : {0}", index);
            //아이템 인스턴스를 생성
            GameObject itemGo = Instantiate(item);
            itemGo.transform.position = position;
            //컨트롤러 가져오기
            var controller = itemGo.GetComponent<ItemController>();
            
        }
    }
}

HeroController

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

namespace Test3 
{

    public class HeroController : MonoBehaviour
    {
        private MonsterController target;
        private Vector3 targetPosition;
        private Animator anim;
        //public System.Action onMoveComplete;

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

        //이동 메서드
        public void Move(Vector3 targetPosition)
        {
            //이동할 목표지점을 저장 
            this.targetPosition = targetPosition;          
            //이동
            this.anim.SetInteger("State", 1);
            //코루틴 실행
            this.StartCoroutine(this.CoMove());
        }

        //코루틴 이동
        private IEnumerator CoMove()
        {
            //while 동안 실행
            while (true)
            {
                //방향을 바라봄
                this.transform.LookAt(this.targetPosition);
                //바라봤으니까 정면으로 이동(이동로직)
                this.transform.Translate(Vector3.forward * 2f * Time.deltaTime);
                //목표지점과 나와의 거리 재기
                float distance = Vector3.Distance(this.transform.position, this.targetPosition);
                //타겟이 있는가?              
                if(distance <= 0.1f)
                {
                    //도착
                    break;
                }              
                yield return null; //다음 프레임 시작
            }
            Debug.Log("<color=yellow>도착!</color>");
            this.anim.SetInteger("State", 0);
            //대리자를 호출
            //this.onMoveComplete();
        }           
    }
}

MonsterController

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

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

        [SerializeField]
        private GameEnums.eItemType rewardItemType;

        public System.Action<GameEnums.eItemType> onDie;  //대리자 변수 선언
  
        public void Awake()
        {
            this.anim = this.GetComponent<Animator>();
        }
        
       public void Die()
        {
            //코루틴 호출
            StartCoroutine(this.coDie());
        }

        //죽고 리워드 아이템 생성 코루틴
        private IEnumerator coDie()
        {
            this.anim.SetInteger("State", 3);
            yield return new WaitForSeconds(2.0f);
            this.onDie(this.rewardItemType);  //대리자 호출
        }
    }
}

ItemController

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

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

        public GameEnums.eItemType ItemType
        {
            get { return this.itemType; }
        }
    }
}

 

 

'KDT > 유니티 기초' 카테고리의 다른 글

23/08/11 할거  (0) 2023.08.11
23/08/10 내용 복습  (0) 2023.08.10
23/08/09 SimpleRPG (+ 이펙트 효과)  (0) 2023.08.09
23/08/09 SimpleRPG 몬스터 공격 및 데미지 받기  (0) 2023.08.09
23/08/08 복습 - 내용정리  (0) 2023.08.08