[구현 목록]
1. 씬 실행시 HeroData를 로드한 뒤, 빈 slot의 thump(이미지)에 HeroData의 Sprite_name을 통해 Atlas의 sprite 를 불러와 각 slot의 thump에 적용
2. Application.persistentDataPath
(기본주소 = C:/Users/user/AppData/LocalLow/DefaultCompany/SaveAndLoad/hero_info.json)의 위치에 hero_info.json이 없다면 신규유저, 있다면 기존유저 판단.
3. 신규 유저라면 처음 slot들은 모두 오픈(캐릭터 이미지로 적용)되어 있으며, 슬롯 클릭시 클릭된 슬롯 제외한 나머지 슬롯 lock(자물쇠)로 변경 및 생성 불가.
4. 기존 유저라면 hero_info에 저장되어있는 id를 제외한 나머지 슬롯들은 모두 lock(자물쇠)으로 sprite 변경 및 생성 불가
5. hero가 없다면 슬롯 클릭시 생성, hero가 있다면 슬롯 클릭시 제거
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json; //네임 스페이스 추가
using UnityEngine.UI;
using System;
using System.IO;
using UnityEngine.U2D;
public class AppMain : MonoBehaviour
{
//프리팹이 저장될 변수
private List<GameObject> prefabs = new List<GameObject>();
[SerializeField]
private Button[] btns; //버튼 배열 인스턴스 선언
[SerializeField]
private Image thumb;
[SerializeField]
private SpriteAtlas atlas;
[SerializeField]
private UISlot[] uiSlots;
private GameObject currentHero; // 현재 존재하는 영웅 참조
void Start()
{
DataManager.instance.LoadHeroData();
LoadPrefabs();
string filePath = string.Format("{0}/hero_info.json", Application.persistentDataPath);
if (File.Exists(filePath)) // 기존 유저
{
string jsonData = File.ReadAllText(filePath);
HeroInfo heroInfo = JsonConvert.DeserializeObject<HeroInfo>(jsonData);
InitializeSlotsForExistingUser(heroInfo.id);
}
else // 신규 유저
{
InitializeSlotsForNewUser();
}
}
void InitializeSlotsForExistingUser(int unlockedHeroId)
{
List<HeroData> heroDatas = DataManager.instance.HeroDatas();
for (int i = 0; i < heroDatas.Count; i++)
{
UISlot slot = this.uiSlots[i];
HeroData data = heroDatas[i];
Sprite sp;
if (data.id == unlockedHeroId)
{
sp = this.atlas.GetSprite(data.sprite_name);
}
else
{
sp = this.atlas.GetSprite("lock");
slot.isLocked = true;
}
slot.Init(data.id, sp);
slot.onClick = (id) => { if (!slot.isLocked) CreateHero(id); };
}
}
void InitializeSlotsForNewUser()
{
List<HeroData> heroDatas = DataManager.instance.HeroDatas();
for (int i = 0; i < heroDatas.Count; i++)
{
UISlot slot = this.uiSlots[i];
HeroData data = heroDatas[i];
Sprite sp = this.atlas.GetSprite(data.sprite_name);
slot.Init(data.id, sp);
slot.onClick = (id) =>
{
if (!slot.isLocked) // 잠긴 슬롯을 클릭시 hero 생성 x
{
CreateHero(id);
LockAllSlotsExcept(id);
}
};
}
}
void LockAllSlotsExcept(int unlockedHeroId)
{
foreach (UISlot slot in this.uiSlots)
{
if (slot.id != unlockedHeroId)
{
slot.img.sprite = this.atlas.GetSprite("lock");
slot.isLocked = true;
}
}
}
private void CreateHero(int id)
{
if (currentHero != null)
{
Destroy(currentHero); // 이미 존재하는 영웅 삭제
currentHero = null;
return;
}
string filePath = string.Format("{0}/hero_info.json", Application.persistentDataPath);
Debug.Log(filePath);
HeroInfo heroInfo = null; //변수 정의
if (File.Exists(filePath)) //있다 (기존유저)
{
Debug.Log("<color=red>기존유저</color>");
// 파일 로드 후 역직렬화, HeroInfo 객체 생성
string jsonData = File.ReadAllText(filePath);
heroInfo = JsonConvert.DeserializeObject<HeroInfo>(jsonData);
}
else //없다 (신규유저)
{
Debug.Log("<color=green>신규유저</color>");
HeroData heroData = DataManager.instance.GetHeroData(id);
heroInfo = new HeroInfo(heroData.id, heroData.max_hp, heroData.damage);
// 생성된 HeroInfo 객체를 직렬화하여 JSON 파일로 저장
string jsonData = JsonConvert.SerializeObject(heroInfo);
File.WriteAllText(filePath, jsonData);
}
int index = id - 100;
Debug.LogFormat("index: {0}", index);
GameObject prefab = this.prefabs[index];
Debug.Log(prefab);
GameObject heroGo = new GameObject();
heroGo.name = "Hero";
currentHero = heroGo;
GameObject model = Instantiate<GameObject>(prefab, heroGo.transform); // model은 heroGo의 자식객체로 인스턴스화
Hero hero = heroGo.AddComponent<Hero>();
hero.Init(heroInfo, model); //Hero 컴포넌트에 model과 info를 넘김
}
private void LoadPrefabs()
{
List<string> heroPrefabNames = DataManager.instance.GetHeroPrefabNames();
foreach (string prefabName in heroPrefabNames)
{
string path = string.Format("Prefabs/{0}", prefabName);
Debug.Log(path);
GameObject prefab = Resources.Load<GameObject>(path);
this.prefabs.Add(prefab);
}
Debug.LogFormat("프리팹들이 로드 되었습니다. count: {0}", this.prefabs.Count);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UISlot : MonoBehaviour
{
public int id;
public System.Action<int> onClick;
[SerializeField]
private Button btn;
public Image img;
public bool isLocked = false; // 잠금 상태를 판별할 변수
public void Init(int id, Sprite sp)
{
this.id = id;
//sprite_name
//atals
img.sprite = sp;
this.btn.onClick.AddListener(() => {
this.onClick(this.id);
});
}
// Update is called once per frame
void Update()
{
}
}
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class DataManager
{
public static readonly DataManager instance = new DataManager();
private Dictionary<int, HeroData> dicHeroDatas = new Dictionary<int, HeroData>();
private DataManager()
{
}
public void LoadHeroData()
{
TextAsset asset = Resources.Load<TextAsset>("Data/hero_data"); //Unity의 Resources 폴더에서 파일을 로드
Debug.Log(asset.text); //JSON 형식의 문자열을 확인
HeroData[] heroDatas = JsonConvert.DeserializeObject<HeroData[]>(asset.text); //JSON 문자열을 HeroData[] 타입으로 역직렬화
foreach (HeroData data in heroDatas) //역직렬화된 HeroData 객체들의 정보를 순회하며 출력
{
Debug.LogFormat("{0} {1} {2} {3} {4} {5}", data.id, data.name, data.max_hp, data.damage, data.prefab_name, data.sprite_name);
this.dicHeroDatas.Add(data.id, data); //Dictionary에 추가
Debug.LogFormat("data.sprite_name = {0}",data.sprite_name);
}
Debug.LogFormat("<color=red> HeroData 로드완료 : {0} </color>", this.dicHeroDatas.Count); //빨간색으로 로그 호출
}
public List<string> GetHeroPrefabNames() //prafab의 이름을 저장한 리스트 가져오기
{
List<string> list = new List<string>();
foreach (HeroData data in this.dicHeroDatas.Values)
{
list.Add(data.prefab_name);
}
return list;
}
public HeroData GetHeroData(int id)
{
return this.dicHeroDatas[id];
}
public List<HeroData> HeroDatas()
{
return this.dicHeroDatas.Values.ToList();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hero : MonoBehaviour
{
private HeroInfo info; //hero의 가변적 데이터
private GameObject model; // hero의 프리팹
public void Init(HeroInfo info, GameObject model)
{
this.info = info;
this.model = model;
Debug.LogFormat("Init: {0}, {1}", this.info, this.model);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeroData
{
public int id;
public string name;
public float max_hp;
public float damage;
public string prefab_name;
public string sprite_name;
}
**hero_data를 수정할 때 , hero_data의 위치 및 문법이 맞는지 꼭 확인하자.
'KDT > 유니티 심화' 카테고리의 다른 글
LearnUGUI 연습 (2. 버튼 만들기) (0) | 2023.09.05 |
---|---|
LearnUGUI 연습 (1. 프로젝트 세팅하기) (0) | 2023.09.04 |
유니티 데이터 연동 연습 (完) (0) | 2023.09.02 |
[SpaceShooter] 라이트 프로브 연습 (0) | 2023.08.31 |
[SpaceShooter] 라이트 매핑 연습 (0) | 2023.08.31 |