1. 템플릿 제작
다음 스테이지 이동, 자동차 선택 등의 기능을 구현하기 전에 템플릿을 제작해보겠습니다.
팀마다 부르는 법이 다르긴 했지만, 엑셀에 미리 입력했던, 게임 중에 수정되지 않는 데이터 템플릿이라 불렀던 팀도 있었습니다.
그래서 이 프로젝트에서 엑셀에서 미리 입력해둔 데이터를 템플릿이라고 부르기로 했습니다.
처음에는 ScriptableObject이용해 만들려고 했지만 아래 단점들 때문에 포기하고 엑셀을 사용하기로 하였습니다.
- 서버를 유니티로 만들지 않는 이상 서버에서 쓸 수 없다.
- 개발 도중에 소스코드를 바꿨다가 힘들게 입력했던 데이터들이 날아 갈 수 있다.
프로젝트 폴더에 taxi-game-3d-templates 폴더 추가하였습니다.
taxi-game-3d-templates 폴더에 Template(Dev).xlsx 파일을 추가하였습니다.
리브레 오피스로 xlsx파일을 열었을 때 생기는 lock 파일을 깃 허브에 올려버리지 않도록 아래 내용을 적은 .gitignore 파일을 추가하였습니다.
(저는 크랙을 찾기 귀찮아서 개인적으로 하드에 저장된 xlsx파일을 수할 때는 LibreOffic Calc사용합니다.)
.~lock.*.xlsx#
xlsx 파일에 Car 시트를 추가한 후 임시로 데이터를 입력하였습니다.

xlsx 파일에 Stage 시트를 추가한 후 임시로 데이터를 입력하였습니다.

그리고 위에 입력한 데이터들은 파이썬을 이용하여 JSON으로 변환한 후 리소스 폴더에 넣는 작업을 하기로 하였습니다.
과거에 유니티 에디터를 이용하여 xlsx파일을 JSON이나 BSON으로 변환하도록 구현하였습니다.
하지만 게임에 들어가는 정보가 많아져 시트 하나에 몇 만줄되어 버렸고, 그 데이터를 불러와서 변환하다가 유니티 에디터가 멈춘 후, 강제종료되어 버렸습니다.
이 문제를 급하게 해결하기 위해 csv로 바꿨던 경험이 있었기 때문에 이번에는 파이썬을 사용해보기로 하였습니다.
파이썬은 왜 설치했었는지 까먹었지만 어쨌든 설치되어 있어 설치과정을 생략하겠습니다.
콘솔창을 열어 아래 문구를 입력하여 openpyxl을 설치하였습니다.
pip install openpyxl
taxi-game-3d-templates 폴더에 deploy-car-dev.py 파일을 추가하여 간단하게 JSON으로 변환하는 기능을 테스트 해보았습니다.
import json
from openpyxl import load_workbook
book = load_workbook('./Template(Dev).xlsx', data_only=True)
sheet = book['Car']
skip = 0
temp_group = []
for row in sheet.rows:
if skip < 2:
skip += 1
continue
if row[0].value == None:
continue
new_temp = {
'Id': row[0].value,
'Name': {
'Table': row[1].value,
'Key': row[2].value
},
'Icon': row[3].value,
'Prefab': row[4].value,
'Cost': row[5].value
}
temp_group.append(new_temp)
with open('car.json', 'w') as f:
json.dump(temp_group, f)
한글이 이상하게 나왔습니다.
[{"Id": "car1", "Name": {"Table": null, "Key": "\ucc281"}, "Icon": "icons/car1.png", "Prefab": null, "Cost": 0}, {"Id": "car2", "Name": {"Table": null, "Key": "\ucc282"}, "Icon": "icons/car2.png", "Prefab": null, "Cost": 1000}, {"Id": "car3", "Name": {"Table": null, "Key": "\ucc283"}, "Icon": "icons/car3.png", "Prefab": null, "Cost": 2000}]
인터넷에서 해결방법을 찾아 수정하였습니다.
with open('car.json', 'w', encoding='UTF-8-sig') as f:
json.dump(temp_group, f, ensure_ascii=False)
[{"Id": "car1", "Name": {"Table": null, "Key": "차1"}, "Icon": "icons/car1.png", "Prefab": null, "Cost": 0}, {"Id": "car2", "Name": {"Table": null, "Key": "차2"}, "Icon": "icons/car2.png", "Prefab": null, "Cost": 1000}, {"Id": "car3", "Name": {"Table": null, "Key": "차3"}, "Icon": "icons/car3.png", "Prefab": null, "Cost": 2000}]
유니티 리소스 폴더에 json파일을 옮기는 기능을 구현하기 전에 미리 json을 저장할 폴더를 만들어 두었습니다.(taxi-game-3d-client/Assets/_TaxiGame/Resources/Templates)
taxi-game-3d-client/Assets/_TaxiGame/Resources/Templates 폴더에 변환된 json을 저장하도록 수정하였습니다.
client_path = '../taxi-game-3d-client/Assets/_TaxiGame/Resources/Templates/Car.json'
with open(client_path, 'w', encoding='UTF-8-sig') as f:
json.dump(temp_group, f, ensure_ascii=False)
동일한 방법으로 deploy-stage-dev.py 파일을 만들어 스테이지 정보도 전달할 수 있도록 구현하였습니다.
그리고 각각의 파일들을 따로 실행하지 않고, 한꺼번에 실행할 수 있도록 deploy-all-client.bat 파일도 만들었습니다.
python deploy-car-client.py
python deploy-stage-client.py
2. 클라이언트 연동
다음으로 클라이언트에서 json파일들을 불러오는 기능을 구현하였습니다.
Assets/_TaxiGame/Scripts/Templates 폴더 추가한 후 CarTemplate.cs, StageTemplate.cs, LocalizationTemplate.cs, TemplateManager.cs 추가하였습니다.
JSON은 개인적으로 사용하기 편했던 Newtonsoft.Json을 사용하기로 하였습니다.
Package Manager를 통해 Newtonsoft.Json 추가하였습니다.

새로 추가한 소스코드에 내용을 작성하였습니다.
- TemplateManager.cs
public class TemplateManager : MonoBehaviour
{
public static TemplateManager Instance
{
get;
private set;
}
public List<CarTemplate> Cars
{
get;
private set;
}
public List<StageTamplate> Stages
{
get;
private set;
}
void Awake()
{
Instance = this;
DontDestroyOnLoad(gameObject);
Cars = Load<CarTemplate>("Templates/Car");
Stages = Load<StageTamplate>("Templates/Stage");
}
List<T> Load<T>(string path)
{
var asset = Resources.Load<TextAsset>(path);
return JsonConvert.DeserializeObject<List<T>>(asset.text);
}
}
- CarTemplate.cs
public class CarTemplate
{
public string Id { get; set; }
public LocalizationTemplate Name { get; set; }
[JsonProperty("Icon")]
public string IconPath { get; set; }
[JsonProperty("Prefab")]
public string PrefabPath { get; set; }
public int Cost { get; set; }
}
- StageTemplate.cs
public class StageTamplate
{
public string Id { get; set; }
[JsonProperty("Scene")]
public string SceneName { get; set; }
}
- LocalizationTemplate.cs
public class LocalizationTemplate
{
public string Table { get; set; }
public string Key { get; set; }
}
GameLogic 클래스에 템플릿이 잘 읽어지는지 테스트하는 코드 추가하였습니다.
if (TemplateManager.Instance == null)
new GameObject("TemplateManager", typeof(TemplateManager));
foreach (var carTemp in TemplateManager.Instance.Cars)
Debug.Log(JsonConvert.SerializeObject(carTemp));
foreach (var stageTemp in TemplateManager.Instance.Stages)
Debug.Log(JsonConvert.SerializeObject(stageTemp));
구현 결과

다음에는 자동차 프리팹과 스테이지 씬들을 만들어 템플릿에 실제로 입력할 계획입니다.
깃 허브 저장소 : taxi-game-3d-unity
'개발노트 > Taxi Game 3D' 카테고리의 다른 글
Devlog) Taxi Game 3D) 9) 맵 제작 2 (2) | 2023.12.09 |
---|---|
Devlog) Taxi Game 3D) 8) 맵 제작 1 (2) | 2023.12.04 |
Devlog) Taxi Game 3D) 6) 게임 로직 구현 3 (2) | 2023.11.28 |
Devlog) Taxi Game 3D) 5) 게임 로직 구현 2 (3) | 2023.11.23 |
Devlog) Taxi Game 3D) 4) 게임 로직 구현 1 (0) | 2023.11.21 |