공부중

[Unity]동일한 구조(?)의 코드를 생성해야 하는 경우 본문

Programing/Unity3D

[Unity]동일한 구조(?)의 코드를 생성해야 하는 경우

곤란 2020. 4. 7. 23:44
반응형

음 뭐라고 제목을 정할까 하다가 실제로 저런 문제를 해결하려고 구현한것이라서 일단 저렇게 써봤다.

문제의 상황은 아래와 같다.

Skill 이라는 클래스가 있고 Skill의 자식클래스로 각각의 스킬 구현을 할 예정이다.

// Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PokemonDefine;


public abstract class Skill : MonoBehaviour
{
    protected PokemonSkillInfoData skillInfo;

    public void Init(string skillName)
    {
        this.skillInfo = PokemonDataManager.Instance.GetPokemonSkillData(skillName);
    }

    public virtual void DoSkill() { }

    public PokemonSkillInfoData GetSkillInfo()
    {
        return skillInfo;
    }

}

 이런 스킬 클래스가 있고

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

public class ########## : Skill
{
    // protected PokemonSkillInfoData skillInfo;

    // public void Init(string skillName);

    public override void DoSkill()
    {
        base.DoSkill();

        Debug.Log(this.skillInfo.name);

    }


}

이런 모양의 자식 클래스들을 생성해줄것이다.

위의 코드에서 ##########에 클래스 이름을 스킬이름으로 넣어줄 생각이다.

 

스킬은 어떻게 구현할지 다르고 나머지 공통 부분은 Skill클래스에서 구현할 예정이므로 일단 저렇게 잡아놓았다.

 

문제는 만들어야할 파일이 한두개가 아니고 총 167개의 파일을 단순 노동으로 생성해야한다.

이것을 템플릿파일 한개를 만들어두고 이 탬플릿에서 변경할 내용을 정해서 파일을 생성해줄 예정이다.

구현한 코드는 아래와 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using PokemonDefine;

public class CreateSkillClass
{
    // 스킬 클래스 관련 경로와 파일명
    public static string skillClassFileDirectory = "Assets/Scripts/Game/Skill/Skills";
    public static string skillClassTemplateFilePath = skillClassFileDirectory + "/Template.txt";
    public static string T = "##########";
    public static string templateString = "";

    // 스킬파일에대한 경로와 파일명
    public static string skillInfoFilePath = "Assets/Resources/Data/PokemonInfo/skillInfo_min.json";

    public static PokemonSkillInfoData[] skillInfo;

    [MenuItem("Assets/Create SkillClassFile")]
    static void CreateSkillClassFiles()
    {
        Debug.Log("= 스킬 클래스 파일 생성 시작 =");

        // 디렉토리가 존재하지 않는다면 생성한다.
        if (false == Directory.Exists(skillClassFileDirectory))
        {
            Debug.Log("디렉토리가 존재하지 않으므로 생성합니다.");
            Directory.CreateDirectory(skillClassFileDirectory);
            Debug.Log("디렉토리가 생성 완료.");
        }

        // 스킬 정보 데이터 로드
        if (true == File.Exists(skillInfoFilePath))
        {
            Debug.Log("스킬정보 데이터 파일 확인");

            Debug.Log("스킬 정보 데이터 파일 읽기 시작");
            string readSkillInfo = File.ReadAllText(skillInfoFilePath);
            Debug.Log("스킬 정보 데이터 파일 읽기 완료");

            Debug.Log("스킬 정보 데이터 Json 변환 시작");
            PokemonSkillInfoDataList loadedData = JsonUtility.FromJson<PokemonSkillInfoDataList>(readSkillInfo);
            if (null == loadedData.pokemonSkillInfoData)
            {
                Debug.LogError("Json 변환 실패");
                return;
            }

            skillInfo = loadedData.pokemonSkillInfoData;
            Debug.Log("스킬 정보 데이터 Json 변환 완료");
            Debug.Log("스킬 갯수 : " + skillInfo.Length);
        }
        else
        {
            Debug.LogError("스킬정보 데이터 파일이 존재하지 않습니다. 경로를 확인해 주세요");
            return;
        }

        // 템플릿 파일 로드
        if (true == File.Exists(skillClassTemplateFilePath))
        {
            Debug.Log("클래스 템플릿 파일 확인");

            Debug.Log("클래스 템플릿 파일 읽기 시작");
            templateString = File.ReadAllText(skillClassTemplateFilePath);

            if (0 == templateString.Length)
            {
                Debug.LogError("템플릿 파일 내용이 비어있습니다.");
                return;
            }
            Debug.Log("클래스 템플릿 파일 읽기 완료");

            Debug.Log("스킬 클래스 생성 시작!");

            for (int i = 0; i < skillInfo.Length; i++)
            {
                string temp = templateString;
                temp = temp.Replace(T, skillInfo[i].enName);


                string newSkillFilePath = skillClassFileDirectory + "/" + skillInfo[i].enName + ".cs";

                File.WriteAllText(newSkillFilePath, temp);
                Debug.Log(newSkillFilePath + " 생성 성공");
            }

            Debug.Log("모든 스킬 클래스 생성 완료");
        }
        else
        {
            Debug.LogError("클래스 템플릿 파일이 존재하지 않습니다. 경로를 확인해 주세요");
            return;
        }
    }
}

모든 코드는 위와 같으며 기능을 간단히 정리해보자면

  • 먼저 skillInfo_min.json에 저장된 모든 스킬 정보들을 읽어와 스킬 정보를 수집한다.
  • 클래스 템플릿 파일을 읽어온다.
  • 읽어온 템플릿파일에서 변환할 부분만 변환작업을 거친뒤 저장해준다.

부분부분 코드를 보면 아래와 같다.

    // 스킬 클래스 관련 경로와 파일명
    public static string skillClassFileDirectory = "Assets/Scripts/Game/Skill/Skills";
    public static string skillClassTemplateFilePath = skillClassFileDirectory + "/Template.txt";
    public static string T = "##########";
    public static string templateString = "";

    // 스킬파일에대한 경로와 파일명
    public static string skillInfoFilePath = "Assets/Resources/Data/PokemonInfo/skillInfo_min.json";

    public static PokemonSkillInfoData[] skillInfo;

각각의 경로들과 템플릿에서 변환시킬 부분은 어떤것인지를 저장한것이다.

skillInfo_min.json에서 읽어온 스킬정보를 저장할 배열도 만들어놓았다.

 

    [MenuItem("Assets/Create SkillClassFile")]
    static void CreateSkillClassFiles()
    {
        Debug.Log("= 스킬 클래스 파일 생성 시작 =");

        // 디렉토리가 존재하지 않는다면 생성한다.
        if (false == Directory.Exists(skillClassFileDirectory))
        {
            Debug.Log("디렉토리가 존재하지 않으므로 생성합니다.");
            Directory.CreateDirectory(skillClassFileDirectory);
            Debug.Log("디렉토리가 생성 완료.");
        }
        
        ......

[MenuItem( ... )]을 통해서 유니티 메뉴에 등록을 해주고

만일 지정한 경로가 없다면 폴더를 생성해주는 코드이다.

[MenuItem( ... )]을 사용하면 이렇게 지정한 메뉴경로에 생성이 된다.

        ....
        
        // 스킬 정보 데이터 로드
        if (true == File.Exists(skillInfoFilePath))
        {
            Debug.Log("스킬정보 데이터 파일 확인");

            Debug.Log("스킬 정보 데이터 파일 읽기 시작");
            string readSkillInfo = File.ReadAllText(skillInfoFilePath);
            Debug.Log("스킬 정보 데이터 파일 읽기 완료");

            Debug.Log("스킬 정보 데이터 Json 변환 시작");
            PokemonSkillInfoDataList loadedData = JsonUtility.FromJson<PokemonSkillInfoDataList>(readSkillInfo);
            if (null == loadedData.pokemonSkillInfoData)
            {
                Debug.LogError("Json 변환 실패");
                return;
            }

            skillInfo = loadedData.pokemonSkillInfoData;
            Debug.Log("스킬 정보 데이터 Json 변환 완료");
            Debug.Log("스킬 갯수 : " + skillInfo.Length);
        }
        else
        {
            Debug.LogError("스킬정보 데이터 파일이 존재하지 않습니다. 경로를 확인해 주세요");
            return;
        }

	....

스킬정보를 로드하는 부분인데 특별히 구현한것은 없고 JsonUtility를 통해서 읽어온 파일의 string을 json으로 적절히 변환해서 배열에 저장하는 내용이다.

 

		....

		// 템플릿 파일 로드
        if (true == File.Exists(skillClassTemplateFilePath))
        {
            Debug.Log("클래스 템플릿 파일 확인");

            Debug.Log("클래스 템플릿 파일 읽기 시작");
            templateString = File.ReadAllText(skillClassTemplateFilePath);

            if (0 == templateString.Length)
            {
                Debug.LogError("템플릿 파일 내용이 비어있습니다.");
                return;
            }
            Debug.Log("클래스 템플릿 파일 읽기 완료");

            Debug.Log("스킬 클래스 생성 시작!");

            for (int i = 0; i < skillInfo.Length; i++)
            {
                string temp = templateString;
                temp = temp.Replace(T, skillInfo[i].enName);


                string newSkillFilePath = skillClassFileDirectory + "/" + skillInfo[i].enName + ".cs";

                File.WriteAllText(newSkillFilePath, temp);
                Debug.Log(newSkillFilePath + " 생성 성공");
            }

            Debug.Log("모든 스킬 클래스 생성 완료");
        }
        else
        {
            Debug.LogError("클래스 템플릿 파일이 존재하지 않습니다. 경로를 확인해 주세요");
            return;
        }

위에서 적어놓은 템플릿 파일 내용을 보면 ########## 이 부분이 변경할 내용이고 이 문자열은 string T에 저장되어있다.

File을 통해서 템플릿파일을 읽고 Replace를 통해서 #########을 위에서 읽어온 json파일의 내용중 스킬이름으로 변경하고 스킬명으로 .cs파일을 생성한다.

 

이제 컴파일후 메뉴에서 실행해보면

Console창에 이와같은 로그를 찍고 완료하게 된다.

 

실제로 .cs 파일을 생성한 모습이다.

반응형