2014년 4월 11일 금요일
Vector3 vOriginPos = //원래 위치.
Vector3 vMovePos = //이동할 위치.
//체인지 버튼을 누르면 호출되는 함수.
public void MoveStartObject()
{
TweenPosition tp = TweenPosition.Begin(gameobject, 1f, vMovePos);
tp.from = //원래위치.
tp.to = //이동위치.
tp.duration = //이동할때걸리는 시간.
tp.eventReceiver = gameobject; //이동이 끝나면 호출되는 콜백 -
tp.callWhenFinished= "MoveEnd";
}
//무빙이 끝나면 호출되는 콜백함수.
void MoveEnd()
{
TweenScale ts = TweenScale.Begin(gameobject, 커지는 시간, 크기);
ts.from = //원래 크기.
ts.to = //커질 크기.
ts.delay = //이동후에 바로 커질것인가 딜레이타임을 주고 커질것인가.
ts.duration = //커지는 시간.
}
boardObject.SetActive(true);
TweenAlpha tweenAlpha = boardObject.AddComponent<TweenAlpha>();
tweenAlpha.from = 0.0f;
tweenAlpha.to = 1.0f;
tweenAlpha.onFinished = delegate(UITweener tween)
{
UIScale uiScale = tween.gameObject.AddComponent<UIScale>(); // 현재의 컴포넌트와 연결된 게임오브젝트에 다른 트윈 추가.
GameObject.Destroy(tween); // 실행이 끝난 현재의 트윈 컴포넌트를 제거.
uiScale.onFinished = // 여기에 새로운 트윈이 끝난시점의 내용을 위와 똑같이 추가.
uiScale.Play(); // 새로운 트윈을 실행.
};
2014년 4월 5일 토요일
개발 시작...
1. 카메라 세팅
다른 방법이 있다고는 하지만.. 사실 알지 못하고..
나는 카메라를 세개 사용합니다.
먼저 게임 카메라...
게임안에 조작과 각종 화면을 담당합니다.
두번째 ui카메라로 .. ngui 카메라입니다.
여기서 각종 ui를 담당합니다.
세번째는 fx 카메라로..
화면에 특수 효과를 담당합니다.
실제로 2d 게임등에는.. ui위로.. 특수효과가 나오는 경우가 있습니다.
이때를 대비하여 만든 것입니다.
이부분은 차후 수정이 필요한것으로..
게임 화면에서 동전을 먹고
그 동적인 ui에 가서 번쩍이려면...
게임 구조가 달라져야 하기 때문입니다.
2. 해상도 세팅..
해상도는 ngui 에 의지합니다.
어차피.. 카메라는..기기별로 달라집니다.
그냥.. 액션게임이면 신경 안써도 되고..(조금 화면이 넓어진다고 뭔 상관이겠습니까)
퍼즐 등이면 미리 보완을 합니다.
ui 카메라가 문제인데...
해상도는 오토로 사용합니다.
그리고 각 부분은 앵커를 박아서 사용합니다.
이렇게 되면.. 세로 해상도를 기준으로..
ui가 늘어지지 않고
조금씩 위치를 넓혀 가면서... 보여지게 됩니다.
요기까지만 와도.. 게임 개발의 ABC중 a는 확실하게 온것입니다.
이제부터 본화면과 함께... 개발에 들어갑니다.
개발은 소스를 위주로 하겠습니다..
1. 카메라 세팅
다른 방법이 있다고는 하지만.. 사실 알지 못하고..
나는 카메라를 세개 사용합니다.
먼저 게임 카메라...
게임안에 조작과 각종 화면을 담당합니다.
두번째 ui카메라로 .. ngui 카메라입니다.
여기서 각종 ui를 담당합니다.
세번째는 fx 카메라로..
화면에 특수 효과를 담당합니다.
실제로 2d 게임등에는.. ui위로.. 특수효과가 나오는 경우가 있습니다.
이때를 대비하여 만든 것입니다.
이부분은 차후 수정이 필요한것으로..
게임 화면에서 동전을 먹고
그 동적인 ui에 가서 번쩍이려면...
게임 구조가 달라져야 하기 때문입니다.
2. 해상도 세팅..
해상도는 ngui 에 의지합니다.
어차피.. 카메라는..기기별로 달라집니다.
그냥.. 액션게임이면 신경 안써도 되고..(조금 화면이 넓어진다고 뭔 상관이겠습니까)
퍼즐 등이면 미리 보완을 합니다.
ui 카메라가 문제인데...
해상도는 오토로 사용합니다.
그리고 각 부분은 앵커를 박아서 사용합니다.
이렇게 되면.. 세로 해상도를 기준으로..
ui가 늘어지지 않고
조금씩 위치를 넓혀 가면서... 보여지게 됩니다.
요기까지만 와도.. 게임 개발의 ABC중 a는 확실하게 온것입니다.
이제부터 본화면과 함께... 개발에 들어갑니다.
개발은 소스를 위주로 하겠습니다..
프로그램....순서
일단 먼저 틀을 잡아야 할 것이다.
나는 유니티를 기반으로 ngui를 위주로 사용한다.
먼저 스크립트는 크게 분야별로 나눈다.
1. 데이터 클래스
게임에서 제공되는 각종 정보를 받거나 저장하는 클래스와
게임내부에서 사용되는 각종 정보 클래스...
여기서..
데이터를 받아롤때...
웹에서 받을 것인지... 를 정해야 하며
기본 작업에서는 그렇게까지 할 필요는 없다.
그럼에도.. xml 을 상용하고자 하면..이것도 큰 문제는 없다.
2. 연결하는 클래스..
xml 에 데이터를 받아서 클래스에 넘겨주는 클래스..
즉, xml 에서 정보를 받아서 가공하여
본 게임에서 사용할수 있게 해주는 클래스이다.
3. 게임 관련 클래스..
가공된 데이터등으로 본 게임에서 직접 게임을 제어하는 클래스....이다.
게임은 기본적으로 위에 세가지 클래스를 기반으로 작업된다.
게임의 규모가 작다면
클래스는 하나로 유지해도 상관없다.
끽해야 몇장 나온다.
그러나 광범위하게 작업되려면...
각각의 작업에 관련한 클래스를 정의해서 가지고 있어햐 한다
물론.. 이렇게 한다고 특별하게 뭔가가 정의되는 것은 아니지만..
어차피 큰 파이프 라인은 가지고 있어야 한다.
어느 클래스를 어디에서 쓰고
다시 어디로 연결하고 하는지.. 알아야 한다.
모르면 상황 웃겨진다.
서로 협의하는데만 시간 십만년 걸린다.
문제는 설명해주는 쪽이..
자시는 긴 작업과 회의 끝에 내용이 정리되 것임에도
설명을 받는 쪽에...게
이거 간단한거 아냐... 이렇게 생각하는데 있다...
긴시간이 흐르고서야.. 왜 우리가 늦어졌지.. 이렇게 생각하게 된다.
나는 유니티를 기반으로 ngui를 위주로 사용한다.
먼저 스크립트는 크게 분야별로 나눈다.
1. 데이터 클래스
게임에서 제공되는 각종 정보를 받거나 저장하는 클래스와
게임내부에서 사용되는 각종 정보 클래스...
여기서..
데이터를 받아롤때...
웹에서 받을 것인지... 를 정해야 하며
기본 작업에서는 그렇게까지 할 필요는 없다.
그럼에도.. xml 을 상용하고자 하면..이것도 큰 문제는 없다.
2. 연결하는 클래스..
xml 에 데이터를 받아서 클래스에 넘겨주는 클래스..
즉, xml 에서 정보를 받아서 가공하여
본 게임에서 사용할수 있게 해주는 클래스이다.
3. 게임 관련 클래스..
가공된 데이터등으로 본 게임에서 직접 게임을 제어하는 클래스....이다.
게임은 기본적으로 위에 세가지 클래스를 기반으로 작업된다.
게임의 규모가 작다면
클래스는 하나로 유지해도 상관없다.
끽해야 몇장 나온다.
그러나 광범위하게 작업되려면...
각각의 작업에 관련한 클래스를 정의해서 가지고 있어햐 한다
물론.. 이렇게 한다고 특별하게 뭔가가 정의되는 것은 아니지만..
어차피 큰 파이프 라인은 가지고 있어야 한다.
어느 클래스를 어디에서 쓰고
다시 어디로 연결하고 하는지.. 알아야 한다.
모르면 상황 웃겨진다.
서로 협의하는데만 시간 십만년 걸린다.
문제는 설명해주는 쪽이..
자시는 긴 작업과 회의 끝에 내용이 정리되 것임에도
설명을 받는 쪽에...게
이거 간단한거 아냐... 이렇게 생각하는데 있다...
긴시간이 흐르고서야.. 왜 우리가 늦어졌지.. 이렇게 생각하게 된다.
2014년 1월 2일 목요일
퍼즐 게임 만들기..
1. 배치
화면안에.. 퍼즐을 배치한다.
퍼즐을 배치 하기 위해..
기분이 되는 배열을 만든다.
미리 만들어도 되고..
만들면서 배치해도 된다.
나는
randomlist
를 만들어... 가로 새로열을 정한다.
이 배열에... 퍼즐의 종류별로 난수를 발생하여 집어 넣는다...
이 배열은.. 향후 게임의 모든 기준이 된다.
이 배열을 만들면서.. 동시에 이름을 만들어 집어 넣는 배열을 만든다..
이 배열은..
randomnamelist
이 배열에는 1_1_1 이런식으로... 이름을 넣는다...
첫번째는 세로열, 두번째 숫자는 가로열 마지막은 퍼즐의 종류다...
이름을 넣는 이유는 이를 이용해.. 나중에 사용하기 위해서다..
클릭했을때.. 클릭된 자신이 누군지 알아야 하는데..
그를 위해 이렇게 이름을 만들어... 넣는 것이다..
이후..
특정 퍼즐을 클릭하면..
2_3_1 식으로.. 이름을 알수 있다.
이는 이 퍼즐이.. 새로 두번째 가로 세번째의 파란색 퍼즐이란 뜻이다..
이를 문자열로 받아.. 가공하게 된다.
2. 클릭
클릭하면.. 해당 퍼즐의 정보를 받게 된다.
받은 퍼즐의 이름은.. 가공하여..
현재 퍼즐은 어느 위치에 있는 퍼즐이며.. 종류가 무엇인지 알아낸다.
3. 체크
이후 위, 아래, 좌, 우 를 체크하여
화면안에.. 퍼즐을 배치한다.
퍼즐을 배치 하기 위해..
기분이 되는 배열을 만든다.
미리 만들어도 되고..
만들면서 배치해도 된다.
나는
randomlist
를 만들어... 가로 새로열을 정한다.
이 배열에... 퍼즐의 종류별로 난수를 발생하여 집어 넣는다...
이 배열은.. 향후 게임의 모든 기준이 된다.
이 배열을 만들면서.. 동시에 이름을 만들어 집어 넣는 배열을 만든다..
이 배열은..
randomnamelist
이 배열에는 1_1_1 이런식으로... 이름을 넣는다...
첫번째는 세로열, 두번째 숫자는 가로열 마지막은 퍼즐의 종류다...
이름을 넣는 이유는 이를 이용해.. 나중에 사용하기 위해서다..
클릭했을때.. 클릭된 자신이 누군지 알아야 하는데..
그를 위해 이렇게 이름을 만들어... 넣는 것이다..
이후..
특정 퍼즐을 클릭하면..
2_3_1 식으로.. 이름을 알수 있다.
이는 이 퍼즐이.. 새로 두번째 가로 세번째의 파란색 퍼즐이란 뜻이다..
이를 문자열로 받아.. 가공하게 된다.
2. 클릭
클릭하면.. 해당 퍼즐의 정보를 받게 된다.
받은 퍼즐의 이름은.. 가공하여..
현재 퍼즐은 어느 위치에 있는 퍼즐이며.. 종류가 무엇인지 알아낸다.
3. 체크
이후 위, 아래, 좌, 우 를 체크하여
2013년 12월 25일 수요일
[puzzle] 배치.
배치가 먼저...
배치 하면서.. 배열을 통해.. 해당 이름과 게임 오브젝트를 저장..
이름은.. 넘버링을 해서.. 나중에 참조하기 위해.. 1_1 뭐 이런식으로 저장..
게임오브젝트를 저장하는 것은.. 이를 기본 배열로 사용하기 위해..
이것과 다르게.. 미리 배열을 만들어.. 참조하는 방법도 있습니다.
그게 옳은것 같은데.. 뭐.. 하다 보니.. 이렇게 됐네요.
using UnityEngine;
using System.Collections;
public class csManager : MonoBehaviour {
// 보글 변수..
public static GameObject blue;
public static GameObject red;
public static GameObject green;
public static GameObject yellow;
public static GameObject pupple;
GameObject block_bank;
string block_namelist;
int rows = 7;
int cols = 6;
int totlakind = 5;
bool canDelete=false;
public static int [,] randonList; // 무늬를 저장..
private GameObject [,] bogles; // 게임 오브젝트를 저장..
void Awake(){
randonList = new int[rows,cols];
bogles = new GameObject [rows,cols];
blue=Resources.Load("Prefabs/blue") as GameObject;
red=Resources.Load("Prefabs/red") as GameObject;
green=Resources.Load("Prefabs/green") as GameObject;
yellow=Resources.Load("Prefabs/yellow") as GameObject;
pupple=Resources.Load("Prefabs/pupple") as GameObject;
}
void Start () {
block_bank = GameObject.Find("Block_Bank");
// 기본 시작 위치..
float pos_x=-2.5f;
float pos_y=-1.0f;
//2중 포문으로. 배치 한다..
for(int i=0; i<rows;i++)
{
for(int j=0; j<cols;j++)
{
//int k = Random.Range(0,totlakind);
// 배열에서.. 보글의 칼라를 참조..
randonList[i,j] = Random.Range(0,totlakind);
// 프레펩을.. 정한다..
GameObject block = null;
if(randonList[i,j]==0)
{
block = blue; // 프리펩을.. 정하고..
block_namelist=i+"_"+j; // 이름을 만든다.
}
if(randonList[i,j]==1)
{
block = red;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==2)
{
block = green;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==3)
{
block = yellow;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==4)
{
block = pupple;
block_namelist=i+"_"+j;
}
// 게임오브젝트 배치..
GameObject temp = Instantiate(block,new Vector3(pos_x, pos_y, 0),transform.rotation) as GameObject;
temp.transform.parent = block_bank.transform; // 블록 뱅크 밑에.. 위치..
temp.name = block_namelist;
bogles[i,j] =temp;
pos_x++; // x 만큼.. 우측으로..
}
pos_y++; // y만큼 위로..
pos_x = -2.5f; // 새로 시작하는 위치..
}
//배열 확인.. 구동 되는지..
Debug.Log(bogles[0,0].gameObject.tag);
}
}
배치 하면서.. 배열을 통해.. 해당 이름과 게임 오브젝트를 저장..
이름은.. 넘버링을 해서.. 나중에 참조하기 위해.. 1_1 뭐 이런식으로 저장..
게임오브젝트를 저장하는 것은.. 이를 기본 배열로 사용하기 위해..
이것과 다르게.. 미리 배열을 만들어.. 참조하는 방법도 있습니다.
그게 옳은것 같은데.. 뭐.. 하다 보니.. 이렇게 됐네요.
using UnityEngine;
using System.Collections;
public class csManager : MonoBehaviour {
// 보글 변수..
public static GameObject blue;
public static GameObject red;
public static GameObject green;
public static GameObject yellow;
public static GameObject pupple;
GameObject block_bank;
string block_namelist;
int rows = 7;
int cols = 6;
int totlakind = 5;
bool canDelete=false;
public static int [,] randonList; // 무늬를 저장..
private GameObject [,] bogles; // 게임 오브젝트를 저장..
void Awake(){
randonList = new int[rows,cols];
bogles = new GameObject [rows,cols];
blue=Resources.Load("Prefabs/blue") as GameObject;
red=Resources.Load("Prefabs/red") as GameObject;
green=Resources.Load("Prefabs/green") as GameObject;
yellow=Resources.Load("Prefabs/yellow") as GameObject;
pupple=Resources.Load("Prefabs/pupple") as GameObject;
}
void Start () {
block_bank = GameObject.Find("Block_Bank");
// 기본 시작 위치..
float pos_x=-2.5f;
float pos_y=-1.0f;
//2중 포문으로. 배치 한다..
for(int i=0; i<rows;i++)
{
for(int j=0; j<cols;j++)
{
//int k = Random.Range(0,totlakind);
// 배열에서.. 보글의 칼라를 참조..
randonList[i,j] = Random.Range(0,totlakind);
// 프레펩을.. 정한다..
GameObject block = null;
if(randonList[i,j]==0)
{
block = blue; // 프리펩을.. 정하고..
block_namelist=i+"_"+j; // 이름을 만든다.
}
if(randonList[i,j]==1)
{
block = red;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==2)
{
block = green;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==3)
{
block = yellow;
block_namelist=i+"_"+j;
}
if(randonList[i,j]==4)
{
block = pupple;
block_namelist=i+"_"+j;
}
// 게임오브젝트 배치..
GameObject temp = Instantiate(block,new Vector3(pos_x, pos_y, 0),transform.rotation) as GameObject;
temp.transform.parent = block_bank.transform; // 블록 뱅크 밑에.. 위치..
temp.name = block_namelist;
bogles[i,j] =temp;
pos_x++; // x 만큼.. 우측으로..
}
pos_y++; // y만큼 위로..
pos_x = -2.5f; // 새로 시작하는 위치..
}
//배열 확인.. 구동 되는지..
Debug.Log(bogles[0,0].gameObject.tag);
}
}
2013년 7월 28일 일요일
이미지 폰트
#pragma strict
var tex : Texture2D[] =new Texture2D[10];
var score:int;
function Awake(){
score = 25634;
}
function Update () {
score+=1*Time.time;
}
function OnGUI(){
//simplemode = 세가지 제공.. 그중 아래는 사간 화면 꽉 제운것... true = 알파 브랜딩 오케이
noOkDraw(score,Screen.width/30*0.75,Screen.width/30,10);
}
function noOkDraw(nocheck:int,noSizeXpos:float,noSize:float,noSizeYpos:float){
var a0 = nocheck/10000; // 첫번째 숫자
var a1 = nocheck%10000; // 나머지로 다음 숫자들을 찾은 다음
var a2 = a1/1000; // 두번째 숫자
var a3 = a1%1000; // 나머지로 다음 숫자들을 찾은 다음
var a4 = a3/100; // 세번째 숫자
var a5 = a3%100; // 나머지로 다음 숫자들을 찾은 다음
var a6 = a5/10; // 네 번째 숫자
var a7 = a5%10; // 나머지로 다음 숫자들을 찾은 다음
var a8 = a7/1; // 다섯번째 숫자
var a9 = a7%1; // 나머지로 다음 숫자들을 찾은 다음
GUI.DrawTexture(new Rect(noSizeXpos*2,noSize*noSizeYpos, noSize, noSize),tex[a0], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*3,noSize*noSizeYpos, noSize, noSize),tex[a2], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*4,noSize*noSizeYpos, noSize, noSize),tex[a4], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*5,noSize*noSizeYpos, noSize, noSize),tex[a6], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*6,noSize*noSizeYpos, noSize, noSize),tex[a8], ScaleMode.StretchToFill, true, 0.0F);
}
var tex : Texture2D[] =new Texture2D[10];
var score:int;
function Awake(){
score = 25634;
}
function Update () {
score+=1*Time.time;
}
function OnGUI(){
//simplemode = 세가지 제공.. 그중 아래는 사간 화면 꽉 제운것... true = 알파 브랜딩 오케이
noOkDraw(score,Screen.width/30*0.75,Screen.width/30,10);
}
function noOkDraw(nocheck:int,noSizeXpos:float,noSize:float,noSizeYpos:float){
var a0 = nocheck/10000; // 첫번째 숫자
var a1 = nocheck%10000; // 나머지로 다음 숫자들을 찾은 다음
var a2 = a1/1000; // 두번째 숫자
var a3 = a1%1000; // 나머지로 다음 숫자들을 찾은 다음
var a4 = a3/100; // 세번째 숫자
var a5 = a3%100; // 나머지로 다음 숫자들을 찾은 다음
var a6 = a5/10; // 네 번째 숫자
var a7 = a5%10; // 나머지로 다음 숫자들을 찾은 다음
var a8 = a7/1; // 다섯번째 숫자
var a9 = a7%1; // 나머지로 다음 숫자들을 찾은 다음
GUI.DrawTexture(new Rect(noSizeXpos*2,noSize*noSizeYpos, noSize, noSize),tex[a0], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*3,noSize*noSizeYpos, noSize, noSize),tex[a2], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*4,noSize*noSizeYpos, noSize, noSize),tex[a4], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*5,noSize*noSizeYpos, noSize, noSize),tex[a6], ScaleMode.StretchToFill, true, 0.0F);
GUI.DrawTexture(new Rect(noSizeXpos*6,noSize*noSizeYpos, noSize, noSize),tex[a8], ScaleMode.StretchToFill, true, 0.0F);
}
2013년 7월 25일 목요일
데이터 저장
- 게임 데이터를 게임이 종료된 후에도 사용할 수 있도록 저장하고 싶은 경우
- 기본 타입(type)의 데이터 말고 좀 더 복잡한 데이터를 저장하고 싶은 경우
개요
유니티에서 데이터를 저장하는 게 생각만큼 쉽지 않는 건 사실입니다. 전체 씬, 플레이어 위치 정보 등을 저장하려는 경우에그 작업량이 만만치 않습니다. 이번 튜토리얼 그리고 후에 있을 튜토리얼을 통해 유니티에서 데이터를 저장하는 좀 더 쉬운 방법을 보여드리겠습니다. 이번 튜토리얼에서는 데이터를 저장하는 몇 가지 다른 방법들과 이렇게 저장된 데이터들을 RPC 연결 / 서버에 전달해서, 게임에 사용하는 방법을 보여드리겠습니다.
가장 기본적인 방법
기본적인 방법부터 시작해 보겠습니다. 단순한 데이터형(type)에 대해서는 여러분께서 잘 알고 계실 PlayerPrefs으로 저장하는 방법을 확인 하는 차원에서 한번 알아보도록 하겠습니다. PlayerPrefs는 기본형의 데이터를 문자열키 (string key) 값과 함께 저장할 수 있도록 해줍니다. 단순한 데이터를 저장하고 불러와 사용하기에 좋은 방법입니다.
게임 내의 값들
씬 전환 시에 데이터를 저장하고 이를 공유하고 싶은 경우에 좋은 방법 중 하나는 정적 클래스 (static class)를 만들어 이 클래스에 데이터를 저장하는 방법입니다.
그리고 이 값을 읽고 싶을 때는 아래와 같이 사용하면 됩니다.
이와 같은 클래스를 사용하는 방법의 단점은 인스펙터(Inspector)에서 값을 조절할 수 없다는 점 입니다. (싱글톤으로 매니져 클래스를 구성하면 이 점은 보완할 수 있습니다..)
- 인스펙터와 코드 모두에서 값을 조절하고 싶은 경우에는 DontDestroyOnLoadobject 함수를 이용하는 방법을 고려할 수 있습니다. (아래 코드 참고)
그리고 아래와 같은 방법으로 값에 접근할 수 있습니다.
좀 더 복잡한 데이터 저장하기
위의 예제에서 PlayerPrefs를 사용해서 high score를 저장하는 방법을 살펴봤습니다. 하지만 위에서 살펴본 방법으로는 많은 데이터를 저장하는 데에는 한계가 있습니다. 따라서 아래와 같이 high score를 저장할 수 있는 테이블을 정의해서 저장하는 방법을 고려해볼 때가 왔습니다.
위의 예제를 살펴보면, List를 이용해서 ScoreEntry 클래스 정보를 담아 테이블처럼 사용합니다. 하지만 이 정보를 어떻게 저장해야 할까요? – 바로 BinaryFormatter를 사용하면 됩니다! BinaryFormatter를 사용해서 “파라미터를 갖지 않는 생성자”를 갖는 클래스라면 어떤 클래스도 바이트 배열로 변환하고, 변환된 배열을 다시 문자열 값으로 변환할 수 있습니다. (문자열 값으로 변환하면, PlayerPrefs에 저장할 수 있겠죠?) 아래 보이는 네임 스페이스들을 추가해줘야 한다는 점을 잊지 마시구요.
유니티 오브젝트 저장하기
유니티 오브젝트들을 저장하는 방법은 생각보다 까다로울 수 있습니다. 그래서 대부분 유니티 오브젝트가 갖는 값을 유추해 볼 수 있는 클래스를 새로 생성하고 이 클래스의 값을 저장합니다. 예를 들면, RPC 호출을 통해 여러 개의 AnimationStates를 전달하고 싶은 경우에, AnimationStates를 대신할 수 있는 클래스를 생성해서 이 값을 전달하게 됩니다. 다른 유니티 오브젝트의 값을 전달하려는 경우에도 상황은 마찬가지겠지요.
RPC를 통해 전달하기
아래 코드를 보면, 어떤 클래스라도 문자열로 변환할 수 있도록 하는 방법을 보여줍니다. 이를 이용하면 RPC를 통해 모든 파라미터 값을 보낼 수 있겠죠?
문서화 되지는 않았지만, RPC 역시 byte[]을 보낼 수 있습니다. 이 값은 BinaryFormatter를 이용해서 우리가 원하는 값으로 바로 변환할 수 있도록 도와줍니다. 문자열로부터 변환하는 시간을 줄여주기 때문에 더 좋다고 할 수 있습니다.
이제 highscores 값을 다른 플레이어에 전달할 수 있도록 하는 능력이 갑자기 생겼네요.
웹으로 전달하기
WWWForm 을 이용해서 웹 서버에 데이터를 전달하는 방법은 아주 쉽습니다. 하지만 위에서 보았듯이 Convert.ToBase64String()를 이용해서 바이너리 데이터를 문자열로 변환하는 방법이 제일 쉽지 않을까 생각되네요. (물론 여러분이 사용하시는 서버에 따라 달라질 수 있습니다)
파일로 저장하기
파일로 저장하는 방법도 물론 쉽습니다. 유니티가 제공하는 Application.persistentDataPath를 이용해서 파일을 저장할 위치를 정하고, MemoryStream 대신 FileStream 을 사용하면 됩니다.
결론
이번 튜토리얼을 통해서, 데이터를 저장하고 게임 중에 이 값들을 이용하는 몇몇 새로운 방법들을 익히셨으리라 생각합니다.
출처 http://unitygems.com/saving-data-1-remember-me/
위의 자료 번역했습니다. 처음 번역한거라..많이 부족하지만 읽어 주셔서 감사하고, 원문 확인 하셔도 좋을 것 같습니다.
피드 구독하기:
글 (Atom)