Unity2D

Unity) [유니티 2D] 데이터 테이블을 연동하여 다양한 몬스터 생성하기

HSH12345 2023. 5. 6. 03:12
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MonsterGenerator : MonoBehaviour
{
    public GameObject player;
    public GameObject[] generatePoint;
    public List<GameObject> portalPintArr; // 포탈 리스트
    private List<GameObject> monsterPrefabList;

    [System.NonSerialized]
    public Queue<GameObject> monsterPool;
    private int numberOfMonsters;
    public float generateInterval = 5f;
    private int maxCnt = 12;
    private int difficultIdx;
    private int startDifficultyIdx;

    private int mostFarSpawnPoint;
    private int secondFarSpawnPoint;

    private bool isAwaked;
    public bool isFinished;
    Coroutine generateRoutine;
    List<int> monsterIDList;

    private bool test;

    public void Init()
    {
        this.player = GameObject.FindGameObjectWithTag("Player");
        this.monsterPrefabList = new List<GameObject>();
        this.monsterPool = new Queue<GameObject>();
        this.startDifficultyIdx = SetDifficultyID(14000); //인자 -> 룸id
        this.monsterIDList = DataManager.Instance.GetMonsetIDList(this.SetGroupID(4, "meleeRangedExplosive")); //인자로 스테이지와 몬스터 타입

        for (int i = 0; i < monsterIDList.Count; i++)
        {
            int monsterID = monsterIDList[i];
            var prefabName = string.Format("Prefabs/Monsters/{0}", DataManager.Instance.GetMonsterData(monsterID).prefabPath);            
            this.monsterPrefabList.Add(Resources.Load<GameObject>(prefabName));
        }

        this.generateRoutine = StartCoroutine(this.GenerateMonstersRoutine());
        // Init Update 돕니다.
        this.isAwaked = true;

        //ChestTest         
        if (this.test == false)
        {
            EventDispatcher.Instance.Dispatch<Transform, bool>(EventDispatcher.EventName.ChestItemGeneratorMakeChest,
            this.transform);
            this.test = true;
        }

    }

    void Update()
    {
        if (this.isAwaked)
        {
            this.mostFarSpawnPoint = 0;
            this.secondFarSpawnPoint = 0;
            float maxDist = 0;
            float secondMaxDist = 0;

            for (int i = 0; i < this.generatePoint.Length; i++)
            {
                float distance = Vector2.Distance(this.player.transform.position, this.generatePoint[i].transform.position);
                if (distance > maxDist)
                {
                    secondMaxDist = maxDist;
                    this.secondFarSpawnPoint = this.mostFarSpawnPoint;

                    maxDist = distance;
                    this.mostFarSpawnPoint = i;
                }
                else if (distance > secondMaxDist)
                {
                    secondMaxDist = distance;
                    this.secondFarSpawnPoint = i;
                }
            }

            if (AllMonstersInactive())
            {
                if (this.generateRoutine != null) StopCoroutine(this.generateRoutine);
                this.generateRoutine = StartCoroutine(this.GenerateMonstersRoutine());

                if (this.maxCnt <= 0 && !this.isFinished)
                {
                    this.RoomClearInitializing();
                }
            }
        }

    }

    private void RoomClearInitializing()
    {
        this.portalPintArr.ForEach((x) => x.SetActive(true));
        InfoManager.instance.ChangeDungeonStepInfo();
        this.isFinished = true;
        EventDispatcher.Instance.Dispatch<Transform>(EventDispatcher.EventName.UIPortalArrowControllerInitializingArrows,
            this.transform);
        EventDispatcher.Instance.Dispatch<Transform, bool>(EventDispatcher.EventName.ChestItemGeneratorMakeChest,
            this.transform);
    }

    private bool AllMonstersInactive()
    {
        GameObject[] monsters = GameObject.FindGameObjectsWithTag("Monster");
        foreach (GameObject monster in monsters)
        {
            if (monster.activeSelf)
            {
                return false;
            }
        }
        return true;
    }

    IEnumerator GenerateMonstersRoutine()
    {
        while (this.maxCnt >= 0)
        {            
            var difficulty = DataManager.Instance.GetDifficultyData(this.difficultIdx + this.startDifficultyIdx);
            this.numberOfMonsters = difficulty.monsterAmount;
            this.maxCnt--;

            for (int i = 0; i < this.numberOfMonsters; i++)
            {
                int monsterIdx = i % this.monsterIDList.Count;
                GameObject monsterGo;

                if (this.monsterPool.Count > 0)
                {
                    monsterGo = this.monsterPool.Dequeue();
                    if (monsterGo.activeSelf) monsterGo = Instantiate(this.monsterPrefabList[monsterIdx]);
                    monsterGo.SetActive(true);
                }
                else
                {
                    monsterGo = Instantiate(this.monsterPrefabList[monsterIdx]);
                }

                monsterGo.GetComponent<Monster>().Init(this, difficulty.monsterHP, difficulty.monsterDefense);


                int spawnPoint = Random.Range(0, 2) == 0 ? this.mostFarSpawnPoint : this.secondFarSpawnPoint;
                monsterGo.transform.position = this.generatePoint[spawnPoint].transform.position;
            }
            this.difficultIdx++;
            yield return new WaitForSeconds(this.generateInterval);
        }
    }

    private int SetDifficultyID(int roomId)
    {
        int id = 13000;

        if (roomId >= 14000 && roomId <= 14035)
        {
            id += (roomId - 14000) * 12;
        }

        return id;
    }

    private int SetGroupID(int stageNum, string monsterType)
    {
        int id = 15000 + (stageNum - 1) * 6;

        switch (monsterType)
        {
            case "melee":
                break;
            case "ranged":
                id += 1;
                break;
            case "meleeRanged":
                id += 2;
                break;
            case "meleeExplosive":
                id += 3;
                break;
            case "rangedExplosive":
                id += 4;
                break;
            case "meleeRangedExplosive":
                id += 5;
                break;
        }

        return id;
    }
}
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public partial class DataManager 
{
    public static readonly DataManager Instance = new DataManager();    

    private DataManager() { }

    public Dictionary<int,TestData> dicTestDatas;
    
    public void LoadAllDatas()
    {
        this.LoadMonsterData();
        this.LoadMonsterGroupData();
        this.LoadDifficultyData();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;

public partial class DataManager
{
    public Dictionary<int, MonsterData> dicMonsterData;
    public Dictionary<int, MonsterGroupData> dicMonsterGroupData;
    public Dictionary<int, DifficultyData> dicDifficultyData;

    public void LoadMonsterData()
    {
        var asset = Resources.Load<TextAsset>("Data/monster_data");
        if (asset != null)
        {
            var json = asset.text;
            MonsterData[] arr = JsonConvert.DeserializeObject<MonsterData[]>(json);
            this.dicMonsterData = arr.ToDictionary(x => x.id);
            Debug.Log("MonsterDataLoadComplete");
        }
        else Debug.LogError("Data/monster_data not found.");
    }

    public List<MonsterData> GetMonsterDatas()
    {
        return this.dicMonsterData.Values.ToList();
    }

    public MonsterData GetMonsterData(int id)
    {
        return this.dicMonsterData[id];
    }

    public void LoadMonsterGroupData()
    {
        var asset = Resources.Load<TextAsset>("Data/monster_group_data");
        if (asset != null)
        {
            var json = asset.text;
            MonsterGroupData[] arr = JsonConvert.DeserializeObject<MonsterGroupData[]>(json);
            this.dicMonsterGroupData = arr.ToDictionary(x => x.id);
            Debug.Log("MonsterGroupDataLoadComplete");
        }
        else Debug.LogError("Data/monster_group_data not found.");
    }

    public List<int> GetMonsetIDList(int id)
    {
        List<int> listMonsterID = new List<int>();
        var data = dicMonsterGroupData[id];

        if (data.monsterId1 >= 15000) listMonsterID.Add(data.monsterId1);
        if (data.monsterId2 >= 15000) listMonsterID.Add(data.monsterId2);
        if (data.monsterId3 >= 15000) listMonsterID.Add(data.monsterId3);
        if (data.monsterId4 >= 15000) listMonsterID.Add(data.monsterId4);
        if (data.monsterId5 >= 15000) listMonsterID.Add(data.monsterId5);
        if (data.monsterId6 >= 15000) listMonsterID.Add(data.monsterId6);
        if (data.monsterId7 >= 15000) listMonsterID.Add(data.monsterId7);

        return listMonsterID;
    }

    public void LoadDifficultyData()
    {
        var asset = Resources.Load<TextAsset>("Data/difficulty_data");
        if (asset != null)
        {
            var json = asset.text;
            DifficultyData[] arr = JsonConvert.DeserializeObject<DifficultyData[]>(json);
            this.dicDifficultyData = arr.ToDictionary(x => x.id);
            Debug.Log("DifficultyDataLoadComplete");
        }
        else Debug.LogError("Data/difficulty_data not found.");
    }

    public DifficultyData GetDifficultyData(int id)
    {
        return this.dicDifficultyData[id];
    }
}

 

 json 파일 형식의 데이터테이블을 작성하고 해당 테이블을 참조하여 생성할 몬스터의 종류와 몬스터 능력치를 설정합니다.