프로그래밍/Unity 2016. 7. 15. 19:43

유니티는 플랫폼이 다양하다.
그 중 모바일 플랫폼도 쓰는데, 모바일 플랫폼에서 게임오브젝트 또는 프리팹을 동적으로 생성하는 작업(Instantiate 함수)은 플랫폼 특성상 과부하가 걸릴 수 밖에 없다. 따라서 주기적 / 반복적으로 생성하는 객체는 씬이 처음 로드할 때 모두 생성한 후 사용하는 방식이 속도면에서 유리하다(렉을 방지한다). 이처럼 사용할 객체를 미리 만들어 놓은 후 필요할 때 가져다 사용하는 방식을 오브젝트 풀링이라고 한다.


ex) GameManager.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic; // List 자료형을 사용하기 위해 추가해야 하는 네임스페이스
public class GameManager : MonoBehaviour
{
public Transform[] points;
public GameObject monsterPrefab;
public List<GameObject> monsterPool = new List<GameObject>(); //몬스터를 미리 생성해 저장할 리스트 자료형
public float createTime = 2.0f;
public int MaxMonster = 10;
public bool isGameOver = false;
public static GameManager instace - null; // 싱글턴 패턴을 위한 인스턴스 변수 선언
void Awake()
{
//GameManager 클래스를 인스턴스에 대입
instance = this;
}
void Start()
{
points = GameObject.Find("SpawnPoint").GetComponentsInChildren<Tranform>();
for(int i=0;i<maxMonster;i++)
{
GameObject monster = (GameObject)Instantiate(monsterPrefab);
monster.name = "Monster_" + i.ToString();
monster.SetActive(false);
monsterPool.Add(monster);
}
if(points.Length>0)
{
StartCoroutine(this.CreateMonster());
}
}
IEnumerator CreateMonster()
{
while(!isGameOver)
{
int monsterCount = (int) GameObject.FindGameObjectsWithTag("Monster").Length;
if(monsterCount < maxMonster)
{
yield return new WaitForSeconds(createTime);
int idx = Random.Range(1,points.Length);
Instantiate(monsterPrefab,points[idx].position,points[idx].rotation);
}
else
{
yield return null;
}
}
}
}


posted by 천마서생
:
프로그래밍/Unity 2016. 7. 10. 20:20

static public bool JsonDataContainsKey(JsonData data,string key) { bool result = false; if(data == null) return result; if(!data.IsObject) { return result; } IDictionary tdictionary = data as IDictionary; if(tdictionary == null) return result; if(tdictionary.Contains(key)) { result = true; } return result; }




LitJSON의 JsonData 에 해당 key가 존재하는지 체크하는 함수



'프로그래밍 > Unity' 카테고리의 다른 글

유니티 VideoPlayer.  (0) 2017.08.03
unity JsonUtility 사용법. (저장 / 불러오기)  (0) 2016.07.20
오브젝트 풀  (0) 2016.07.15
posted by 천마서생
:
프로그래밍/C++언어 2016. 6. 7. 04:49

맨 처음 문제가

1. 포인터

2. 동적할당

3. 파일입출력

4. 텍스트 게임 금지(글로만 된 스토리 게임)


필자는 곰곰히 생각하고 하루만에 구현 할 수 있는 쉽고 재밌는 게임인 오목을 만들기로 했다. 


또한, 규칙은 복잡하니 단 하나 5개이상으로 연결만 되면 승리 라는 소박한 규칙만 만들었다.


맨 처음으로 Define.h / Define.cpp 를 만들었다. 필자의 프로그래밍 습관이기도 한데 #include XXX 이렇게 계속 선언할 것을 그냥 헤더파일 하나로 모았다.

// Define.h

#pragma once

#include<iostream>

#include<Windows.h>

#include<conio.h>

using namespace std;

void gotoxy(int x, int y);  // 이동을 지시해 줄 함수

enum { LEFT = 75, RIGHT = 77, UP = 72, DOWN = 80, SPACE = 32 };


// Define.cpp

#include"Define.h"

void gotoxy(int x, int y)

{

COORD Pos = { x,y };

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);

}


그 다음 게임을 만들기 위해서 이동을 해야되지 않겠는가? 필자는 CPoint.h / CPoint.cpp로 그리는 함수, 움직이게 키를 받는 함수, 승리 조건 체크 함수를 만들었다.


// CPoint.h

#pragma once

#include"map.h"

class CPoint : public MAP

{

int x; // x좌표

int y; // y좌표

public:

CPoint(int x, int y); // 생성자

void screen(); // 그리는 함수

void input(int &p); //키를 입력 받는 함수

bool check(int &p); // 승리 조건 체크 함수

};


// CPoint.cpp

#include"CPoint.h"

CPoint::CPoint(int x, int y)

{

this->x = x;

this->y = y;

}

void CPoint::screen()

{

system("cls");

for (int j = 0; j < Get_height(); j++)

{

for (int i = 0; i < Get_width(); i++)

{

if (xy[j][i] == 1)

cout << "★";

else if (xy[j][i] == 2)

cout << "☆";

else if (xy[j][i] == 0)

cout << "╋";

}

cout << "\n";

}

}

void CPoint::input(int &p)

{

int c;

bool turn = true;

while (turn)

{

c = getch();

switch (c)

{

case RIGHT:

{

++x;

if (x >= Get_width() - 1)

--x;

gotoxy(x * 2, y);

break;

}

case LEFT:

{

--x;

if (x <= 0)

++x;

gotoxy(x * 2, y);

break;

}

case UP:

{

--y;

if (y <= 0)

++y;

gotoxy(x * 2, y);

break;

}

case DOWN:

{

++y;

if (y >= Get_height() - 1)

--y;

gotoxy(x * 2, y);

break;

}

case SPACE:

if (xy[y][x] != 0)

break;

if (p == 2)

{

xy[y][x] = 2;

}

else

{

xy[y][x] = 1;

}

turn = false;

break;

}

}

}

bool CPoint::check(int &p)

{

int j, sum = 0;

for (j = -5; j <= 5; j++) // 좌우 체크

{

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y][x + j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 상하 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (p == xy[y + j][x])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 오른쪽 위 왼쪽 아래 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y + j][x + j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

for (j = -5; j <= 5; j++) // 왼쪽 위 오른쪽 아래 체크

{

if (y + j <= 0 || y + j >= Get_height())

continue;

if (x + j <= 0 || x + j >= Get_width())

continue;

if (p == xy[y + j][x - j])

{

sum++;

if (sum == 5)

return false;

}

else

sum = 0;

}

return true;

}


그 다음 맵을 만들려고 했다. 그런데 아까 문제중 파일 입출력을 사용하라고 했는데 오목에서 파일 입출력을 받을 것이라고는 맵 / 랭킹정도 밖에 없다고 생각했다. 하지만 필자는 하루동안 (4시간) 만들어야하는 사명을 가지고 있으므로 맵만 파일입출력을 받기로 했다. 맵 받는게 무진장 쉽다고 생각한 것은 내 착오였다. 

일단 텍스트로 맵 정보를 받는데, 그 크기를 자유자제로 조정할 수 있어야 하므로 맵을 읽어 드리는 2차원 배열또한 크기가 자유자제로 바뀌어야한다. 하지만 여러분들은 (필자포함) 배열의 인덱스는 변경될 수 없다고 배웠을 것이다. 실제로 배열 인덱스에 변수를 넣으면 "변수 넣지마 꺼져" 라는 컴파일 에러를 발견하게 될 것이다 (VS2015기준 / C99였나부터 잘 모르겠지만 가변변수가 배열 인덱스에 허용된다고 한다.) 


따라서 필자는 동적할당으로 배열을 만들겠다는 망상을 가지고 map.h / map.cpp를 만들었다.


//map.h

#pragma once

#include"Define.h"

class MAP

{

private:

int width; // 넓이

int height; // 높이

public:

int **xy=NULL; // 동적할당을 위한 더블포인터 xy

void Init(); // 초기화

void Release(); // 메모리 해제

int Get_width(); // 넓이 가져오기

int Get_height(); // 높이 가져오기

};


//map.cpp

#include"map.h"

void MAP::Init()

{

FILE *fp = fopen("mapsize.txt", "r");

int ret = 0;

while (ret != EOF)

ret = fscanf(fp, "%d %d", &width, &height);

xy = new int*[height];

for (int i = 0; i < height; i++)

{

xy[i] = new int[width];

memset(xy[i], 0, sizeof(int)*width);

}

}

void MAP::Release()

{

for (int i = 0; i < height; i++)

delete xy[i];

}

int MAP::Get_height() { return height; }

int MAP::Get_width() { return width; }



마지막으로 대망의 main.cpp를 만들 차례이다!


//main.cpp

#include"Define.h"

#include"CPoint.h"

int main()

{

CPoint cpt(1, 1);

cpt.Init();

int user = 1;

bool check = true;

char name[2][256];

for (int i = 0; i < 2; i++)

{

cout << i + 1 << "번째 님의 이름을 입력:\n";

cin >> name[i];

}

for (int j = 0; j < cpt.Get_height(); j++)

for (int i = 0; i < cpt.Get_width(); i++)

cpt.xy[j][i] = 0;

cpt.screen();

while (check)

{

gotoxy(0, 20);

cout << name[user - 1] << "님 차례";

cpt.input(user);

cpt.screen();

check = cpt.check(user);

if (user == 1)

user = 2;

else

user = 1;

}

gotoxy(0, 20);

cout << name[user - 2] << "님의 승리" << endl;

cpt.Release();

}


이것으로 오목을 4시간(실제 작업시간은 7시간) 만에 만들고 잤다. 사실 시간이 가장 걸렸던건 2차원 배열을 동적으로 받는것에서 3시간을 날렸다. 후... 다시는 하기 싫은 노가다였다.

posted by 천마서생
: