2022. 1. 27. 22:54ㆍUnity3D/수업 내용
오늘은 위의 사진처럼 실행할 때마다 외부에서 가져온 데이터를,
오브젝트의 멤버로 할당하는 법을 실습해보겠다.
먼저, Project 내의 Resources 폴더에 갱신할 데이터 대상인 JSON파일을 저장해주어야 한다.
그리고 몬스터를 가장한 더미오브젝트 프리팹도 저 곳에 놔둔다.
그 다음, 아래와 같이 스크립트를 작성해준다.
먼저 핵심이 되는 DataManage 스크립트.
모노를 상속받지 않고 static이며 GetInstance()로만 static 인스턴스를 참조할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;
public class DataManage
{
static DataManage instance;
Dictionary<int, MonsterData> dictMonsterData;
Dictionary<int, GameObject> dictMonsterGameObjects;
DataManage()
{
this.dictMonsterData = new Dictionary<int, MonsterData>();
this.dictMonsterGameObjects = new Dictionary<int, GameObject>();
}
public static DataManage GetInstance()
{
if(DataManage.instance == null)
{
DataManage.instance = new DataManage();
}
return DataManage.instance;
}
public GameObject GetMonsterObjectByName(string name)
{
foreach(KeyValuePair<int, MonsterData> data in dictMonsterData)
{
if(data.Value.name == name)
{
return FindMonsterObjectByID(data.Value.id);
}
}
return null;
}
GameObject FindMonsterObjectByID(int id)
{
foreach(KeyValuePair<int, GameObject> obj in dictMonsterGameObjects)
{
if(obj.Key == id)
{
return obj.Value;
}
}
return null;
}
public void LoadMonsterData()
{
string path = "Monster_data";
string json = Resources.Load<TextAsset>(path).text;
this.dictMonsterData = JsonConvert.DeserializeObject<MonsterData[]>(json).ToDictionary(x => x.id);
LoadMonsterPrefabs();
}
void LoadMonsterPrefabs()
{
foreach(KeyValuePair<int, MonsterData> data in dictMonsterData)
{
GameObject go = Resources.Load<GameObject>(data.Value.name);
go.GetComponent<Monster>().InitMonsterStat(data.Value.id, data.Value.name, data.Value.hp);
dictMonsterGameObjects.Add(data.Key, go);
}
}
}
데이터 매니지 스크립트의 흐름은 이렇다.
1) 게임매니져에서 자신을 GetInstance()로 부르고, LoadMonsterData()를 호출받으면
Resources 폴더에서 Monster_data 텍스트에셋을 찾고 읽어들인다.
그 텍스트들은 MonsterData 매핑클래스 타입으로 역직렬화되어 배열이 되었다가
MonsterData의 id 속성을 Key로 삼아 미리 지정해둔 MonsterData 딕셔너리로 추가되어 들어간다.
2) 그 후 LoadMonsterPrefabs()을 호출하여 MonsterData딕셔너리를 반복문으로 순회시킨다.
반복문 안에서는 Resources 폴더에 있던 더미오브젝트 프리팹을
MonsterData의 name 속성을 이용해 가져온다.
오브젝트를 가져왔으면, 그 오브젝트에 미리 부착돼 있던 Monster 클래스의 InitMonsterStat()을 통해
Monster의 멤버값을 외부에서 가져온 데이터인 MonsterData 딕셔너리의 Value값과 동일하게 할당해준다.
간단하게,
외부 데이터를 읽어들이고
그 데이터로 딕셔너리를 만들고
그 딕셔너리로 몬스터의 멤버값을 할당해준다.
사실 dictMonsterGameObjects 딕셔너리는 없어도 된다.
게임매니져에서 몬스터를 만들 때마다 GetMonsterData(int id) 같은 메서드를 통해
몬스터를 생성하고 그때 그때 멤버값을 할당해줘도 충분하지만
그냥 DataManage에서 처음 딱 한 번만 사전에 다 담아버린 다음,
그때 그때 꺼내쓰기만 하고 싶었다.
이 아래는 나머지 스크립트.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
DataManage dm;
void Start()
{
dm = DataManage.GetInstance();
dm.LoadMonsterData();
GameObject go = Instantiate(dm.GetMonsterObjectByName("Slime"));
go.transform.position = new Vector3(0f, 2f, 0f);
GameObject go2 = Instantiate(dm.GetMonsterObjectByName("Rammus"));
go2.transform.position = new Vector3(3f, 2f, 0f);
}
}
public class MonsterData
{
public int id;
public string name;
public int hp;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster : MonoBehaviour
{
[HideInInspector] public int id;
public string monName;
public int hp;
public void InitMonsterStat(int id, string name, int hp)
{
this.id = id;
this.monName = name;
this.hp = hp;
}
void Start()
{
Debug.Log(this.id + "/" + this.monName + "/" + this.hp);
}
}
그리고, Monster의 멤버값 또한 public으로 선언해주어야
정상적으로 InitMonsterStat()을 통해 값을 할당받을 수 있다.
이유는 잘 모르겠다.
'Unity3D > 수업 내용' 카테고리의 다른 글
22.02.04 JSON 데이터를 UI에 바인딩하기 (0) | 2022.02.05 |
---|---|
22.02.03 Canvas와 UI 배우기 (0) | 2022.02.03 |
22.01.26 애니메이터 임팩트 타임에 따라 적에게 피해 입히기 (0) | 2022.01.26 |
22.01.26 유니티와 JSON 연동해 데이터 불러오고 저장하기 (0) | 2022.01.26 |
22.01.25 Simple RPG - 애니메이터, 파티클, JSON (0) | 2022.01.25 |