ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (14) Json으로 스테이지에 적 배치하기
    Galaxy Ball/2. 싱글플레이 - 스토리모드 2024. 5. 29. 15:28

    전 글에서 올바르게 스테이지를 찾아간뒤, 현재 스테이지의 인덱스값(chooseStage)까지

    인게임창에 전달하는것을 성공했으니 이번에는 그 스테이지의 인덱스값을 이용하여 적 유닛을 배치해보겠다

     

    적 배치 역시 Json을 사용할 예정이고, 예전에 한번 아주 간단하게 연습해본적이 있으나

    이번에는 실전이니 제대로 해보겠다

     

    우선 Json 파일을 만드는데 쓸 엑셀 파일부터 만들어주겠다

     

    이제 예전처럼 id, x, y만 달랑 적어놓고 단순하게 출력만 하지 않고 조금 더 구체적으로 작성하였다

     

    id는 당연히 스테이지를 나타내는것이고, enemies/0/type은 1번째 생성될 적 유닛의 종류,

    그 뒤에오는 x,y는 생성될 위치값이다. 

     

    이렇게 한 사이클이 돌고나면 배열값에 1이 더해져 이것을 반복하게 된다.

    한 스테이지에 둘 이상의 유닛이 배치될 경우라고 생각하면 되겠다

     

    그리고 enemies/2/type에 보면 빈칸(null)으로 있는것을 볼수 있는데 스테이지에 따라 하나의 유닛이 나올수도, 

    많게는 6~7개 이상의 유닛이 나올수도 있기에 저렇게 null값으로 비워두면 후에 작성할 스크립트에서 자연스럽게 넘어가도록 하겠다

     

    [
       {
          "id": 1,
          "enemies": [
             {"type": "Enemy1", "x": 1.3, "y": 1.3},
             {"type": "Enemy1", "x": -1.3, "y": -1.3},
             {"type": null, "x": 2, "y": 2}
          ]
       },
       {
          "id": 2,
          "enemies": [
             {"type": "Enemy2", "x": 1.3, "y": 1.3},
             {"type": "Enemy2", "x": -1.3, "y": -1.3},
             {"type": null, "x": 2, "y": 2}
          ]
       }
    ]

     

    위 엑셀 파일을 Json 형식으로 변환시킨것이다. 

     

    using System.Collections.Generic;
    using UnityEngine;
    using Newtonsoft.Json;
    
    public class EnemySpawnData
    {
        public string type;
        public float x;
        public float y;
    }
    
    public class EnemyData
    {
        public int id;
        public List<EnemySpawnData> enemies;
    }
    
    public class SpawnEnemy : MonoBehaviour
    {
        public GameObject[] Enemy;
        public TextAsset jsonFile;
    
        void Start()
        {
            if (jsonFile == null)
            {
                Debug.LogError("JSON file not set in the inspector.");
                return;
            }
    
            int stage = GlobalData.SelectedStage;
            string jsonData = jsonFile.text; // JSON 데이터를 TextAsset에서 가져옵니다.
            List<EnemyData> enemyDataList = JsonConvert.DeserializeObject<List<EnemyData>>(jsonData);
    
            if (enemyDataList == null)
            {
                Debug.LogError("Failed to deserialize JSON data.");
                return;
            }
    
            // 해당 stage의 데이터를 찾습니다.
            EnemyData data = enemyDataList.Find(d => d.id == stage);
            if (data != null)
            {
                if (data.enemies == null)
                {
                    Debug.LogError("No enemies data found for the selected stage.");
                    return;
                }
    
                foreach (var enemy in data.enemies)
                {
                    if (!string.IsNullOrEmpty(enemy.type))
                    {
                        InstantiateEnemy(enemy.type, enemy.x, enemy.y);
                    }
                }
            }
            else
            {
                Debug.LogError("No data found for the selected stage.");
            }
        }
    
        void InstantiateEnemy(string enemyType, float x, float y)
        {
            int index = GetEnemyIndex(enemyType);
            if (index >= 0 && index < Enemy.Length)
            {
                Instantiate(Enemy[index], new Vector3(x, y, 0), Quaternion.identity);
            }
        }
    
        int GetEnemyIndex(string enemyType)
        {
            switch (enemyType)
            {
                case "Enemy1": return 0;
                case "Enemy2": return 1;
                case "Enemy3": return 2;
                case "Enemy4": return 3;
                case "Enemy5": return 4;
                case "Enemy6": return 5;
                case "Enemy7": return 6;
                default: return -1;
            }
        }
    }

     

    그리고 예전에 임시로 만들어만 두었던 SpawnEnemy 스크립트를 대거 수정해주었다

    해당 코드는 인게임씬에 있는 빈 오브젝트 "EnemySpawn"에 부착되어있다

     

      public GameObject[] Enemy;
      public TextAsset jsonFile;


    가장 먼저 적 유닛의 타입을 정할 Enemy는 배열로 입력받고, jsonFile 역시 내가 직접 넣어주도록 하였다

     

            int stage = GlobalData.SelectedStage;
            string jsonData = jsonFile.text;
            List<EnemyData> enemyDataList = JsonConvert.DeserializeObject<List<EnemyData>>(jsonData);

     

    그리고 해당 스테이지 번호를 가져오고 입력받은 json 파일을 비직렬화해준다

     

     foreach (var enemy in data.enemies)
     {
         if (!string.IsNullOrEmpty(enemy.type))
         {
             InstantiateEnemy(enemy.type, enemy.x, enemy.y);
         }
     }

     

    중간중간에 에러를 잡기 위한 목적의 조건문, 로그들은 생략하겠다

    그리고 문제가 없다면 InstantiateEnemy 메서드를 실행하자

     

     void InstantiateEnemy(string enemyType, float x, float y)
     {
         int index = GetEnemyIndex(enemyType);
         if (index >= 0 && index < Enemy.Length)
         {
             Instantiate(Enemy[index], new Vector3(x, y, 0), Quaternion.identity);
         }
     }

     

    위 메서드는 말 그대로 적 유닛의 타입, x,y축 값을 받아와 적을 생성하는 메서드이다

     

    int GetEnemyIndex(string enemyType)
    {
        switch (enemyType)
        {
            case "Enemy1": return 0;
            case "Enemy2": return 1;
            case "Enemy3": return 2;
            case "Enemy4": return 3;
            case "Enemy5": return 4;
            case "Enemy6": return 5;
            case "Enemy7": return 6;
            default: return -1;
        }
    }

     

    그리고 마지막으로 쓰인 GetEnemyIndex 메서드는 인덱스 넘버에 따라 적 유닛의 종류가 결정되게 하는것인데

    솔직히 이것보다 좋은 방법이 있을것만 같지만 우선 내가 아는 지식의 한계에서는 이게 최선이다

     

     

    이제 Inspector창을 확인해보자. 내가 직접 적유닛타입 배열의 길이를 지정할수 있고 순서대로 적 유닛 프리팹을

    넣어주기만 하면 된다. JsonFile은 당연히 아까 작성한 Json 파일을 넣어주면 된다

     

     

     

    이제 결과를 한번 확인해보자. 

    1번 스테이지에는 1번유닛이 두개씩, 2번 스테이지에는 같은 위치에 2번 유닛이 생성되는것을 확인할 수 있고,

    이것에 이어 패배판정이 일어나면 넘어가는 Fail씬에서 다시하기를 누르면

    방금과 똑같은 씬으로 다시 전환되는것을 볼수 있다

     

    이제 기본적인 틀을 만드는데 성공했으니 스테이지 만드는것은 이제부터 스테이지 만들기는 

    무언가를 더 배우거나 시행착오를 거칠 필요없이 난이도 밸런스만 생각하면서 단순 작업에 들어가기만 하면 된다

     

    그러니 확실하게 Json 형식을 완성시키기전에 할수있는한 모든 아이디어들을 쥐어짜내서 마지막으로 유닛 추가를 한뒤

    중간보스와 최종보스까지 만들어보도록 하겠다

     

    그 다음은 유닛뿐만 아니라 고정구체, 배경 색깔까지

    직접 json으로 배치하고 수정하여 스테이지를 다양하게 만들어보도록 하겠다

Designed by Tistory.