2022. 1. 26. 12:44ㆍUnity3D/수업 내용
데이터 불러오기
Resources 폴더에 json파일을 갖다놓고 그 데이터를 유니티 런타임에서 불러오도록 한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
public class MonsterData
{
public int id;
public int hp;
}
public class useJson : MonoBehaviour
{
public static useJson instance;
public GameInfo gi;
private Dictionary<int, MonsterData> dictMonsterData = new Dictionary<int, MonsterData>();
void Awake() //Start로 하면 이 데이터를 참조하는 다른 스크립트에서 에러 남
{
instance = this;
TextAsset data = Resources.Load<TextAsset>("monster_data");
string json = data.text;
dictMonsterData = JsonConvert.DeserializeObject<MonsterData[]>(json).ToDictionary(x => x.id);
gi.InitMonsterInfo();
}
public MonsterData GetMonsterData(int i)
{
return dictMonsterData[i];
}
}
Resources.Load문장이 Resources 폴더에서 json파일을 불러오는 코드이다.
주의할 점이 저 불러오는 코드가 위치한 이벤트 함수는 Start()가 아니라 Awake()이어야 한다.
이유는 다른 스크립트에서도 이 useJson 스크립트가 불러온 데이터를 참조할 것인데,
그 다른 스크립트가 참조하는 코드가 위치한 이벤트 함수도 Start()라서
불러오는 것과 참조하는 것이 동시에 일어나서 에러가 나기 때문이다.
그래서 유니티 이벤트 함수의 생명 주기를 보면 알 수 있듯이
Awake()가 Start()보다 먼저 실행이 되므로 Start() 대신 Awake()를 쓴다.
참고로 유니티 Project 창 내의 Resources 폴더에 있는 것은 모두 File이자 Asset이다.
JSON파일도 TextAsset으로 분류되기 때문에 불러오는 타입도 TextAsset타입으로 캐스팅했다.
그 후 텍스트에셋의 문자열 데이터를 역직렬화하고 미리 만들어둔 딕셔너리에 데이터를 담았다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster
{
public int id;
public int hp;
public Monster(int id, int hp)
{
this.id = id;
this.hp = hp;
}
}
public class GameInfo
{
public Monster monsterInfo;
public void InitMonsterInfo()
{
int id = useJson.instance.GetMonsterData(0).id;
int hp = useJson.instance.GetMonsterData(0).hp;
monsterInfo = new Monster(id, hp);
}
}
그리고 useJson클래스에서 InitMonsterInfo() 메서드를 호출하여
GameInfo를 초기화시켜 useJson 클래스가 갖고 있게 한다.
그 결과 useJson 클래스는
속성이 할당된 Monster객체를 참조하는 변수 monsterInfo를 갖고 있는
GameInfo 를 갖고 있게 된다.
그러면 이 GameInfo를 파일로 저장해보자.
데이터 저장하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
public class MonsterData
{
public int id;
public int hp;
}
public class useJson : MonoBehaviour
{
public static useJson instance;
public GameInfo gi;
private Dictionary<int, MonsterData> dictMonsterData = new Dictionary<int, MonsterData>();
void Awake()
{
instance = this;
TextAsset data = Resources.Load<TextAsset>("monster_data");
string json = data.text;
Debug.Log(json);
dictMonsterData = JsonConvert.DeserializeObject<MonsterData[]>(json).ToDictionary(x => x.id);
Debug.Log(dictMonsterData[0].hp);
gi.InitMonsterInfo();
}
public void SaveData()
{
Debug.Log("데이터를 저장했습니다.");
string saveJson = JsonConvert.SerializeObject(this.gi);
File.WriteAllText("Assets/Resources/monster_data3.json", saveJson);
}
public MonsterData GetMonsterData(int i)
{
return dictMonsterData[i];
}
}
SaveData() 에서 Resources 폴더에 JSON파일을 저장한다.
이때는 File.WriteAllText를 써서 이름 뒤에 "3"만 붙여 저장했다.
잘 저장 된 것이 확인 됐으면 그 저장한 GameInfo의 JSON파일을 불러와보자.
저장한 GameInfo 객체의 데이터 불러오기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
public class MonsterData
{
public int id;
public int hp;
}
public class useJson : MonoBehaviour
{
public static useJson instance;
public GameInfo gi;
private Dictionary<int, MonsterData> dictMonsterData = new Dictionary<int, MonsterData>();
void Awake()
{
instance = this;
TextAsset data2 = Resources.Load<TextAsset>("monster_data3");
string json2 = data2.text;
gi = new GameInfo();
gi = JsonConvert.DeserializeObject<GameInfo>(json2);
}
public void SaveData()
{
Debug.Log("데이터를 저장했습니다.");
string saveJson = JsonConvert.SerializeObject(this.gi);
File.WriteAllText("Assets/Resources/monster_data3.json", saveJson);
}
public MonsterData GetMonsterData(int i)
{
return dictMonsterData[i];
}
}
딕셔너리에 데이터를 넣는 사전작업은 건너뛰고 저장한 GameInfo객체의 데이터를
잘 불러오는지만 확인하기 위해 Awake()에서 코드를 바꿨다.
불러온 GameInfo 객체를 다른 스크립트에서 참조해보고 정상적으로 불러왔는지 확인해보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MainSCR : MonoBehaviour
{
[SerializeField] private Button saveBtn;
private GameObject[] enemies;
void Start()
{
enemies = GameObject.FindGameObjectsWithTag("Enemy");
saveBtn.onClick.AddListener(LetDataSaved);
EnemiesInit();
}
void LetDataSaved()
{
useJson.instance.SaveData();
}
void EnemiesInit()
{
foreach(GameObject em in enemies)
{
Monster monsterInfo = useJson.instance.gi.monsterInfo;
em.GetComponent<EnemyControl>().LoadStatData(monsterInfo.id, monsterInfo.hp);
}
}
}
메인 스크립트에서 EnemiesInit()을 통해 게임씬에 있는 모든 enemy오브젝트들에게
불러온 GameInfo객체의 enemy정보를 우겨넣는다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyControl : MonoBehaviour
{
[SerializeField] private int id;
[SerializeField] private int hp;
public void LoadStatData(int id, int hp)
{
this.id = id;
this.hp = hp;
}
public void DisplayStat()
{
Debug.Log(this.hp + ", " + this.id);
}
}
참고로 원래 몬스터의 hp는 8이고, 불러온 GameInfo객체의 담은 몬스터 hp 정보는 16이다.
프로그램을 실행시켜서 hp가 16인지 확인해보자.
'Unity3D > 수업 내용' 카테고리의 다른 글
22.01.27 런타임마다 외부의 데이터로 갱신하는 법 (0) | 2022.01.27 |
---|---|
22.01.26 애니메이터 임팩트 타임에 따라 적에게 피해 입히기 (0) | 2022.01.26 |
22.01.25 Simple RPG - 애니메이터, 파티클, JSON (0) | 2022.01.25 |
22.01.24 Ray를 이용하기 (0) | 2022.01.24 |
22.01.24 Sling Chestnut (0) | 2022.01.24 |