EasyCastleUNITY

간단 RPG Test 3-1 본문

유니티 기초

간단 RPG Test 3-1

EasyCastleT 2023. 8. 10. 12:56

씬 정보

레이를 통해 몬스터를 선택하면, 몬스터가 사라지고 해당 위치에 드롭아이템이 생성된다.

모든 몬스터가 사라지면 다음 씬으로 넘어갈 수 있는 포탈을 생성한다. (랜덤한 위치)

GameEnums -> 게임에서 필요한 정보 타입

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

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

        public enum eItemType
        {
            Shield, Sword, Potion
        }
    }
}

MonsterGenerator -> 몬스터를 동적생성

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
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()
        {
            foreach(GameObject prefab in prefabList)
            {
                Debug.LogFormat("Monster prefab : {0}", prefab.name);
            }
        }

        /// <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("Monsterprefab: {0}", this.prefabList[index].name);
            //프리팹 인스턴스를 생성
            GameObject go =Instantiate(prefab);
            //MonsterController가 부착되어 있지 않다면 
            //if (go.GetComponent<MonsterController>() == null)
            //{
            //    //동적으로 컴포넌트를 부착 할수 있음
            //    MonsterController controller = go.AddComponent<MonsterController>();
            //}
            //위치 설정
            go.transform.position = initPosition;

            return go.GetComponent<MonsterController>();


        }
    }
}

Monster Generator 인스펙터

ItemGenerator -> 드롭 아이템을 동적 생성

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()
        {
            foreach(GameObject prefab in prefabList)
            {
                Debug.LogFormat("Item prefab :{0}",prefab.name);
            }
        }
        /// <summary>
        /// 아이템 생성
        /// </summary>
        /// <param name="itemType">생성하려고 하는 아이템의 타입</param>
        /// <param name="initPosition">생성한 아이템의 초기 월드 좌표</param>
        /// <returns></returns>
        public GameObject Generate(GameEnums.eItemType itemType,Vector3 initPosition)
        {
            Debug.LogFormat("itemType :{0}", itemType);

            int index = (int)itemType;

            Debug.LogFormat("index: {0}", index);
            GameObject prefab = this.prefabList[index];
            Debug.LogFormat("Item prefab: {0}", this.prefabList[index].name);
            //프리팹 인스턴스 생성
            GameObject go =Instantiate(prefab);
            go.transform.position = initPosition;

            return go;

        }

    }
}

ItemGenerator 인스펙터

Test3_CreatePortalMain-> 전체적으로 모든 것을 통괄 (몬스터, 아이템, 영웅 등)

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

namespace Test3
{
    //씬의 모든 객체들을 관리하는 클래스 (컴포넌트)
    public class Test3_CreatePortalMain : MonoBehaviour
    {
        [SerializeField]
        private MonsterGenerator monsterGenerator;
        [SerializeField]
        private ItemGenerator itemGenerator;
        [SerializeField]
        private GameObject portalPrefab;
        [SerializeField]
        private GameObject portalFxPrefab;
        private bool isNotCreate = true;

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

        RaycastHit hit;

        // Start is called before the first frame update
        void Start()
        {
            //컬렉션 사용전 반드시 초기화
            this.monsterList = new List<MonsterController>();
            this.itemList = new List<GameObject>();
            //몬스터 동적 생성
            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));
            //만들어진 객체들을 그룹화 관리 
            //동적 배열 
            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.name);
            }
        }
        private void CreatePortal()
        {
            if (this.monsterList.Count <= 0 && this.isNotCreate == true)
            {
                Debug.Log("<color=lime>포탈이 생성됩니다!</color>");
                GameObject portalGo = Instantiate(portalPrefab);
                int posX = Random.Range(-4, 5);
                int posZ = Random.Range(-4, 5);
                portalGo.transform.position = new Vector3(posX, 0, posZ);
                GameObject portalFx = Instantiate(portalFxPrefab);
                portalFx.transform.position = portalGo.transform.position;
                this.isNotCreate = false;
            }
        }
        private void MonsterDestory()
        {
            //몬스터 제거
            Destroy(hit.collider.gameObject);
            this.monsterList.Remove
                (hit.collider.gameObject.GetComponent<MonsterController>());
            //남은 수 확인
            Debug.LogFormat("<color=yellow>몬스터 남은 수: {0}</color>",
                this.monsterList.Count);
        }
        private void CreateDropItem()
        {
            //드롭 아이템 생성
            int randomIndex = Random.Range(0, 3); //0~2
            GameEnums.eItemType eItemIndex = (GameEnums.eItemType)randomIndex;
            Vector3 itemPos = new Vector3(hit.collider.gameObject.transform.position.x,
                hit.collider.gameObject.transform.position.y + 1.0f,
                hit.collider.gameObject.transform.position.z);
            GameObject dropItem = this.itemGenerator.Generate(eItemIndex, itemPos);
            this.itemList.Add(dropItem);
            Debug.LogFormat("<color=yellow>드롭 아이템 {0} 생성</color>", dropItem.name);
        }
        // Update is called once per frame
        void Update()
        {
            //Test
            //Ray연습 겹 클릭해서 선택 몬스터 제거
            if(Input.GetMouseButtonDown(0))
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                float maxDistance = 1000f;
                Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);
                
                if(Physics.Raycast(ray, out hit , maxDistance))
                {
                    Debug.LogFormat("<color=red>{0}</color>",hit.collider.tag);
                    if(hit.collider.tag == "Monster")
                    {
                        this.MonsterDestory();
                        this.CreateDropItem();
                    }
                }
            }
            this.CreatePortal();
        }
    }
}

메인 인스펙터
실행결과