유니티를 하다보면 중복되는 오브젝트를 효율적으로 관리하기 위해 프리팹(Prefab)을 많이 사용합니다.
이러한 프리팹으로 스테이지 구성을 하려고 하는데 각 씬별로 스테이지를 만들면 너무나 많은 씬(Scene)이 생성될 것 같다는 생각이 들었어요
스테이지를 수 백개 만들거라서요
한 씬에 스테이지 10개씩 넣어서 카메라를 이동하기에는 로딩이 오래 걸릴 것 같아 씬은 한개고 계속해서 스테이지를 삭제/생성하는 방식으로 할 계획입니다.
예를들면 다음과 같습니다.
stage.csv 파일을 엑셀에서 작성하여 저장합니다.
저는 오브젝트를 원하는 위치에 배치하는 로직을 구현하였습니다.
이후 stage.csv 파일을 메모장으로 열어 인코딩을 UTF-8로 바꾸어 다시 저장합니다.
(혹시 모를 오류가 있을까봐 UTF-8로 변경하였습니다)
이후 제가 작성한 코드를 대입하면
이렇게 csv파일에 있는 내용을 불러와 그대로 적용하였습니다!
CsvParser.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class CsvParser : MonoBehaviour {
private static CsvParser _instance = null;
public static CsvParser GetInstance()
{
if (_instance == null)
{
_instance = new CsvParser();
}
return _instance;
}
public TextAsset csvFile; // Reference of CSV file
protected string[] data;
protected string[] stringList;
protected string text;
protected string id, obj, posX, posY, posZ, rot;
void Awake()
{
_instance = this;
//문자 구분을 위한 변수 선언
text = csvFile.text;
stringList = text.Split('\n'); //한 줄씩 읽어온다.
}
public string getId(int index)
{
data = stringList[index].Split(',');
return data[0];
}
public string getObj(int index)
{
data = stringList[index].Split(',');
return data[1];
}
public float getPosX(int index)
{
data = stringList[index].Split(',');
return float.Parse(data[2]);
}
public float getPosY(int index)
{
data = stringList[index].Split(',');
return float.Parse(data[3]);
}
public float getPosZ(int index)
{
data = stringList[index].Split(',');
return float.Parse(data[4]);
}
public float getRot(int index)
{
data = stringList[index].Split(',');
return float.Parse(data[5]);
}
}
LoadStageManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class LoadStageManager : CsvParser
{
public GameObject[] everything;
private GameObject searchObj;
private StringReader reader;
private string strLine;
private int lineCount;
// Use this for initialization
void Start()
{
//라인 수 카운트를 위한 변수 선언
reader = new StringReader(csvFile.text);
strLine = reader.ReadLine();
int i = 0;
while (strLine != null)
{
strLine = reader.ReadLine();
i++;
}
//최상단은 컬럼명이므로 카운트에서 제외
lineCount = i - 1;
//최상단은 컬럼명이므로 카운트는 1부터 시작
for (int j = 1; j <= lineCount; j++)
{
createObject(getObj(j), getPosX(j), getPosY(j), getPosZ(j), getRot(j));
}
}
public void createObject(string objName, float posX, float posY, float posZ, float rot)
{
int searchIndex = 0;
//foreach문보다 for문이 배열에서의 성능이 2배 이상 높다고 한다.
for (int i = 0; i < everything.Length;)
{
//입력된 오브젝트 이름과 동일한 오브젝트를 생성
if (objName == everything[i].name)
{
searchIndex = i;
break;
}
else
{
i++;
}
}
Quaternion Right = everything[searchIndex].transform.rotation;
searchObj = Instantiate(everything[searchIndex].gameObject, new Vector3(posX, posY, posZ), Right) as GameObject;
//오브젝트 회전은 Y축으로만 조작한다.
searchObj.transform.RotateAround(searchObj.transform.position, Vector3.up, rot);
}
}
csv파일은 Assets 폴더안에 넣으신 뒤 TextAsset csvFile에 드래그로 넣어주면 됩니다.
회전값은 짐벌락 현상이 있어 제대로 구현하지 못하였네요..
쿼터니언으로 하면 짐벌락이 없다고 하던데 저는 왜 있을까요?? ㅠㅠ
해결책 아시는분은 댓글로 남겨주시면 감사하겠습니당