'분류 전체보기'에 해당되는 글 495건

  1. 2013.12.06 [펌] 유니티 런닝게임 관련 질문
  2. 2013.12.06 [펌] 유니티 러너 게임 질문
  3. 2013.12.05 [펌] Unity 3D State Manager -> 싱글톤 패턴을 이용한 스크립트
  4. 2013.12.05 [펌] 유니티 메모리 관리
  5. 2013.12.05 유니티 게임 매니저 관련 글
  6. 2013.12.05 유니티 가로 세로 모드 설정
  7. 2013.12.04 유니티 해상도 대응하기
  8. 2013.12.04 cocos2d-x JSON 파일을 다루기 (JSONCpp 사용) (1)
  9. 2013.12.03 헥사 게임 알고리즘
  10. 2013.12.02 비쥬얼드 로직

[펌] 유니티 런닝게임 관련 질문

|

출처:http://devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=35122&sca=&sfl=wr_subject||wr_content&stx=%EB%A7%B5+%EC%83%9D%EC%84%B1&sop=and&currentId=44


[Unity3D] 런닝게임 맵 로드 && 맵 이동 질문드려욤..

윈드러너나 쿠키런 같은 런닝 게임을 만들고 잇는데요.
주인공은 x,z축은 고정이고 y축으로만 점프만 가능한 게임인데요.
이런 류의 게임은 같은거는 어떤식으로 처리하시나요??

생성방법질문좀드릴꼐요
1) 
Instantiate로 매번 생성해버리면 생성할 떄 잠깐 끊김이 있어서 현재는 Instantiate않쓰고 오브젝트를 SetActivite(false)시 키면서위치값을 바꿔주구요 다음이 흐르도록 서로 연결되게 다음  SetActivite(true)시키면서 이런식으로 반복되게 했거 든요.
을 반복적으로 돌리데 위의 방법이 알맞은 방법인가요?(( 다른문제가있는지 모르곘지만  SetActivite(false)시킬때 약간의 끊 김이있는것 같더라구요....))
SetActivite(false)시키고 MapA.transform.position = new Vector3(30, 0, 0);이렇게 위치값 바꿔주고 있습니다.

2) 
윈드러너나 쿠키런보면 이 흐르는 동안 끊김은 거의 찾아 보기 힘들던데 저는 현재 이 흐르는 동안 안에 안에 포함된 동 전이나 장애물 등이 끊기면서 지나가게 보이네요...
이동은 MapA.transform.Translate(Vector3.left * mSpeed *Time.deltaTime, Space.World);
이런형식으로 흐르도록 하였는데 끊김현상이 발생하네요..
끊김현상의 원인이 될만한 지적좀 해주시면 감사하곘습니다..

감사하니다..


새싹1단계 지키수쿠 2013.08.23 16:14:12 댓글달기
저도 런닝게임 만들고있는데요 일단 땅 오브젝트를 3개 만들어놓고 첫번째 땅이 카메라 시야에서 사라지면 세번째 땅 옆에 출력 되도록 만들었어요 이런식으로 하면 효율적일거예요

새싹1단계 용가립 2013.08.23 16:24:15 댓글달기
네.일단 답변감사합닌다.
지키수쿠님 말씀대로라면 3개의 을 모두 로드해놓은 상태에서 카메라 밖에 안보이게 로드해놓은 상태에서 필요한 만 흐르도록해서 카메라에 비춰지도록 해준다는 말씀이시죠??SetActivite(true) or SetActivite(false) 시킬필요 없이말이죠?
그렇다면 지키수쿠님은 카메라시야에서 사라진 첫번째 은 어떻게 뒤로 보내시나요??
MapA.transform.position = new Vector3(30, 0, 0);이렇게 MapA를 MapC뒤로 붙이도록 하시나요?

새싹1단계 jenemia 2013.08.25 17:06:04 댓글달기
길이를 정하시고 3개를 컨베이트벨트처럼 돌려사용하시면 되요.
그 위에 장애물 같은 것은 일정 규칙에 따라 생성하시고..
장애물을 실시간으로 계속 instantiate로 생성하시면 성능 부하가 생기니까
오브젝트 풀을 사용하셔요


Trackback 0 And Comment 0

[펌] 유니티 러너 게임 질문

|

출처 :

http://devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=38886&sca=&sfl=wr_subject||wr_content&stx=%EB%A7%B5+%EC%83%9D%EC%84%B1&sop=and&currentId=44


[Unity3D] 맵 생성 방식에 대해 여쭤볼께요

런닝게임을 제작하고있습니다.
은 가만히 있고 캐릭터가 자동으로 달려가는 방식이며 현재는 테스트를 하기 위하여 을 전부 세팅해두었습니다.
하지만 미래(?)에 이 길어질걸 생각해서라도 은 캐릭터 일정거리 앞에서 생성을 해야할거같은데..
이부분에서 고민이 됩니다

현재 만들고있는 게임에서 은 랜덤으로 생성하지 않고 레벨디자인으로 을 모두 구성해두고
중간중간 아이템 부분만 랜덤으로 뿌려줄예정입니다. (ex:쿠키런 )

의 정보를 기록하여 그때그때 맞는 생성해주어야 한다고 생각해봤지만..
이 워낙 다양하여 효과적일지 의문입니다. 평지에서만 달리는것도 아니고.. 한번 나오고 말 도 있고..

이런걸 생각해보면 차라리 을 전부 세팅해두고 중간중간 아이템이 다르게 나오는 부분만 처리를 해야할까 했지만
을 모두 만들어두면 로딩이나 렉이 생기지 않을까 걱정입니다..

이럴땐 어떤 방식이 렉을 줄이고 좀더 효율적일지 궁굼합니다.ㅠ

요약
고정형(랜덤x) 생성 방식에대한 문제
방법1. 이 아무리 다양하더라도 모두 프리펩으로 만들어 생성한다.
방법2. 을 전부 세팅해두고 중간중간 아이템만 랜덤으로 생성한다.
방법3. 기타 좋은 방법을 알려주세요ㅠ....




새싹1단계 꿈자루 2013.11.20 12:03:40 댓글달기
어떻게든 쪼개서 불러오는게 좋다고 생각합니다.
툴이 있다면 툴에서 부터 그부분을 고려해서 만들어야하지 않을까 싶네요.


새싹1단계 버그가없…
2013.11.20 17:11:10 댓글달기
현재 진행된 상태에 맞춰야 겠네요 처음부터 이부분에 논의가 없었고 이미 리소스나 기획이 너무 많이 진행되서 손쓸수가 없다면 방법2가 좋겠네요. 아직 초기라면 1번 방법으로 하고  생성에 관한 규칙을 기획적으로 확립하는게 우선입니다. 리소스역시 어디에 붙여도 어색하지 않을(최소한 같은 테마의 블럭에는 어색하지 않게) 사전제작을 해야 하니까요. 게다가 방법1은  오브젝트 풀링과 Unactive 같은 최적화 방법 적용때문에 생성 시점에서의 부하도 부담이 덜합니다.

새싹1단계 Serin 2013.11.22 07:46:30 댓글달기
을 한방에 뽑는게 아닙니다.
말씀하신것처럼 랜덤을 사용하는게 아니라면 어떤 방식으로든

단위 묶음으로 저장을 해두시고, 랜덤하게 하나씩 뽑아오셔서
화면 1~2스크롤 이후에 붙여서 로딩하는식으로 합니다.

보통 화면 2배정도의 길이가 보이지않는 화면 앞부분에 붙어있다고 보심되요.

굳이 프리팹으로 하실 필요도 없고,

스트링으로 저장한다음에 특정좌표에 오브젝트 인스턴트해서 사용해도되구요.


Trackback 0 And Comment 0

[펌] Unity 3D State Manager -> 싱글톤 패턴을 이용한 스크립트

|

  1. /*
  2.         Unity 3D: Game State Manager Script Source for State Manager
  3.        
  4.     Copyright 2012 FIZIX Digital Agency
  5.     http://www.fizixstudios.com
  6.        
  7.         For more information see the tutorial at:
  8.     http://www.fizixstudios.com/labs/do/view/id/unity-game-state-manager
  9.        
  10.        
  11.     Notes:
  12.         This script is a C# game state manager for Unity 3D; you should review the gamestart.cs
  13.         script to help understand how to implement game states.
  14. */
  15.  
  16.  
  17.  
  18. using UnityEngine;
  19. using System.Collections;
  20.  
  21. public class gamestate : MonoBehaviour {
  22.        
  23.         // Declare properties
  24.         private static gamestate instance;
  25.         private string activeLevel;                     // Active level
  26.         private string name;                            // Characters name
  27.         private int maxHP;                                      // Max HP
  28.         private int maxMP;                                      // Map MP
  29.         private int hp;                                         // Current HP
  30.         private int mp;                                         // Current MP
  31.         private int str;                                        // Characters Strength
  32.         private int vit;                                        // Characters Vitality
  33.         private int dex;                                        // Characters Dexterity
  34.         private int exp;                                        // Characters Experience Points
  35.        
  36.        
  37.        
  38.         // ---------------------------------------------------------------------------------------------------
  39.         // gamestate()
  40.         // ---------------------------------------------------------------------------------------------------
  41.         // Creates an instance of gamestate as a gameobject if an instance does not exist
  42.         // ---------------------------------------------------------------------------------------------------
  43.         public static gamestate Instance
  44.         {
  45.                 get
  46.                 {
  47.                         if(instance == null)
  48.                         {
  49.                                 instance = new GameObject("gamestate").AddComponent<gamestate> ();
  50.                         }
  51.  
  52.                         return instance;
  53.                 }
  54.         }      
  55.        
  56.         // Sets the instance to null when the application quits
  57.         public void OnApplicationQuit()
  58.         {
  59.                 instance = null;
  60.         }
  61.         // ---------------------------------------------------------------------------------------------------
  62.        
  63.        
  64.         // ---------------------------------------------------------------------------------------------------
  65.         // startState()
  66.         // ---------------------------------------------------------------------------------------------------
  67.         // Creates a new game state
  68.         // ---------------------------------------------------------------------------------------------------
  69.         public void startState()
  70.         {
  71.                 print ("Creating a new game state");
  72.                
  73.                 // Set default properties:
  74.                 activeLevel = "Level 1";
  75.                 name = "My Character";
  76.                 maxHP = 250;
  77.                 maxMP = 60;
  78.                 hp = maxHP;
  79.                 mp = maxMP;
  80.                 str = 6;
  81.                 vit = 5;
  82.                 dex = 7;
  83.                 exp = 0;
  84.                                
  85.                 // Load level 1
  86.                 Application.LoadLevel("level1");
  87.         }
  88.        
  89.        
  90.        
  91.         // ---------------------------------------------------------------------------------------------------
  92.         // getLevel()
  93.         // ---------------------------------------------------------------------------------------------------
  94.         // Returns the currently active level
  95.         // ---------------------------------------------------------------------------------------------------
  96.         public string getLevel()
  97.         {
  98.                 return activeLevel;
  99.         }
  100.        
  101.        
  102.         // ---------------------------------------------------------------------------------------------------
  103.         // setLevel()
  104.         // ---------------------------------------------------------------------------------------------------
  105.         // Sets the currently active level to a new value
  106.         // ---------------------------------------------------------------------------------------------------
  107.         public void setLevel(string newLevel)
  108.         {
  109.                 // Set activeLevel to newLevel
  110.                 activeLevel = newLevel;
  111.         }
  112.        
  113.        
  114.         // ---------------------------------------------------------------------------------------------------
  115.         // getName()
  116.         // ---------------------------------------------------------------------------------------------------
  117.         // Returns the characters name
  118.         // ---------------------------------------------------------------------------------------------------
  119.         public string getName()
  120.         {
  121.                 return name;
  122.         }
  123.        
  124.        
  125.         // ---------------------------------------------------------------------------------------------------
  126.         // getHP()
  127.         // ---------------------------------------------------------------------------------------------------
  128.         // Returns the characters hp
  129.         // ---------------------------------------------------------------------------------------------------
  130.         public int getHP()
  131.         {
  132.                 return hp;
  133.         }
  134.        
  135.         // ---------------------------------------------------------------------------------------------------
  136.         // getMP()
  137.         // ---------------------------------------------------------------------------------------------------
  138.         // Returns the characters mp
  139.         // ---------------------------------------------------------------------------------------------------
  140.         public int getMP()
  141.         {
  142.                 return mp;
  143.         }
  144. }


Trackback 0 And Comment 0

[펌] 유니티 메모리 관리

|

http://unitykoreawiki.com/index.php?n=KrMain.UnderstandingAutomaticMemoryManagement

이사이트에있는 내용은 유니티개발자라면 참고해야할 내용이라고 봅니다.
알고있는 분들도 있겠지만 혹시 모르시는 분들을 위해 올립니다.


자동 메모리 관리의 이해

오 브젝트나 문자열 혹은 배열(array)이 만들어졌을 때, 이를 저장하는 데 필요한 메모리는 __heap_이라고 불리는 중앙 풀(pool)로부터 할당합니다. 그 아이템을 더 이상 사용하기 않을 경우, 그것이 한 때 차지했던 메모리는 다시 회수하여 다른 것을 위해 사용됩니다. 과거에는, 메모리 힙(heap)의 이러한 블록은 할당하고 회수하는 것은 일반적으로 프로그래머에 의해 해당하는 함수 호출을 통하여 명시적으로 이루어 졌습니다. 요즘에는, Unity의 Mono 엔진과 같은 런타임 시스템이 사용자 대신 자동으로 메모리를 관리하여 줍니다. 자동 메모리 관리는 명시적으로 할당/회수에 들어가는 프로그램 코딩 작업에 노력이 덜 필요하고, 메모리 누수의 가능성을 훨씬 줄여줍니다 (메모리가 할당은 되었지만 뒤에 회수가 되지 않은 상황).

값과 참조의(Value and Reference) 타입

함 수가 호출되면, 그 매개변수()의 값이 그 특정 호출에 대해 유보하고 있는 메모리 영역이 복사됩니다. 불과 몇 바이트의 메모리만 차지하는 데이터 타입은 신속하고 쉽게 복사됩니다. 하지만, 오브젝트는 일반적으로 텍스트나 배열(array)로 훨씬 용량이 크며, 이러한 타입의 데이터가 주기적으로 복사되면 매우 비효율적일 것 입니다. 다행히도 이는 피할 수 있습니다; 큰 아이템에 대한 실제 저장공간은 heap으로부터 할당하며, 이 위치를 기억하기 위해 작은 용량의 "pointer" 값을 기억합니다. 거기서부터, 매개변수의 전달 시에는 이 포인터만 복사됩니다. 런타임 시스템이 그 포인터가 알려주는 지점에서 그 아이템을 찾을 수 있는 한, 그 데이터의 일회 복사는 얼마든지 자주 수행할 수 있습니다.

직접적으로 저장되고 매개변수 전달 시에 복사되는 타입을 값의 타입(value type)이라 부릅니다. 이는 integers, floats, Booleans, Unity의 struct 타입 들(예: Color 과Vector3) 등을 포함합니다. Heap에 할당되고 그리고 포인터로 접근하는 타입을 레퍼런스 타입(reference types)이라 부르며, 이는 그 변수에 저장된 변수는 단순히 실제 데이터를 "참조"만 하기 때문입니다. reference types의 예로는 오브젝트, 문자열 그리고 배열을 들 수 있습니다.

할당과 쓰레기 수거(Garbage Collection)

메 모리 관리자는 heap 내에서 미사용으로 알려진 영역을 추적하여 관리합니다. 새로운 메모리 블록의 요청을 받으면(예: 오브젝트가 인스턴스 될 경우), 이 관리자는 그 블록을 할당하기 위해 미사용 영역을 선택하고, 그 메모리를 알려진 미사용 공간에서 제외시킵니다. 뒤따르는 요청도 이와 같은 방식으로 요청하는 블록 사이즈 크기를 수용할 만큼 큰 빈 영역이 고갈 될 때까지 처리됩니다. 이 시점에 heap에 할당된 메모리가 모두 사용될 가능성은 매우 낮습니다. Heap 상의 레퍼런스 아이템은 그것을 찾을 수 있는 레퍼런스 변수가 존재하는 경우에만 접근할 수 있습니다. 메모리 블록에 대한 모든 레퍼런스가 사라지면(예: 레퍼런스 변수가 재할당 되거나 범위 밖인 로컬 변수), 그것이 차지하고 있던 메모리는 안전하게 재 할당 될 수 있습니다.

어 느 heap 블록이 더 이상 사용되지 않는지를 결정하려고, 메모리 매니저는 현재 유효한 모든 레퍼런스 변수를 찾아 그 들이 참조하는 블록을 "live"로 표시합니다. 검색의 마지막에, live 블록 사이의 모든 공간으로 빈 공간으로 간주하고 메모리 관리자는 그것을 후속하는 할당에 사용할 수 있습니다. 이러한 이유로, 사용되지 않는 메모리를 찾아 풀어주는 이 작업은 쓰레기 수거(garbage collection)라고 알려져 있습니다 (축약하여 GC).

최적화

쓰 레기 수거는 자동으로 수행되면 프로그래머에게는 보여지지 않지만, 이 과정은 실제로 배경에서 상당한 CPU 시간을 소요합니다. 올바르게 사용된다면, 자동 메모리 관리는 수동 할당에 비해 전체 성능이 비슷하거나 더 나을 것 입니다. 하지만, 프로그래머는 이 수거작업을 필요이상으로 수행하여 실행의 일시 멈춤을 가져오는 실수를 피하여야 합니다.

얼핏 보기에는 문제가 없어 보이지만 GC 악몽을 유발할 수 있는 유명한 알고리즘이 몇 개 있습니다. 반복된 문자열 연결이 그 클래식한 예 입니다:-

  function ConcatExample(intArray: int[]) {
	var line = intArray[0].ToString();
	for (i = 1; i < intArray.Length; i++) {
		line += ", " + intArray[i].ToString();
	}
	return line;
  }

여 기의 핵심 세부내용은 새로운 것이 제자리에 한 개씩 추가되는 것이 아니라는 것 입니다. 실제로는 각 룹(loop)이 반복될 때 마다 라인의 이전 내용에 있는 변수는 없어진다는 것입니다 – 전체가 원래 문자열에 새로운 부분을 끝에 추가하여 새로운 문자열 전체로써 할당된다는 것 입니다. 변수 i 가 증가함에 따라 그 문자열은 더 길어짐으로, 사용되는 heap의 용량도 커지므로, 각 함수 호출마다 수백 바이트의 빈 heap 공간을 고갈 시킵니다. 만일 많은 문자열을 연결해야 할 필요가 있을 경우, Mono 라이브러리의 System.Text.StringBuilder 클래스가 훨씬 나은 선택이 됩니다.

하지만, 반복되는 연결 동작도 자주 호출되지 않는 한 큰 문제가 되지는 않습니다. 그리고 Unity에서는 이는 보통 다음과 같은 frame 업데이트를 암시합니다:-

  var scoreBoard: GUIText;
  var score: int;
  function Update() {
	var scoreText: String = "Score: " + score.ToString();
	scoreBoard.text = scoreText;
  }

...위는 Update 가 호출 될 때 마다 새 문자열을 할당하고 끊임없이 새로운 쓰레기를 생성할 것 입니다. 이 대부분은 스코어가 바뀔 때만 텍스트를 업데이트 하여 저장할 수 있습니다.:-

  var scoreBoard: GUIText;
  var scoreText: String;
  var score: int;
  var oldScore: int;
  function Update() {
	if (score != oldScore) {
		scoreText = "Score: " + score.ToString();
		scoreBoard.text = scoreText;
		oldScore = score;
	}
  }

다른 문제의 가능성은 함수가 배열(array)을 반환할 경우에 발생합니다:-

  function RandomList(numElements: int) {
	var result = new float[numElements];
	for (i = 0; i < numElements; i++) {
		result[i] = Random.value;
	}
	return result;
  }

이 러한 타입의 함수는 값으로 채우진 새로운 배열을 만들 때 매우 우아하고 편리합니다. 하지만, 이것이 반복적으로 호출되면 매번 새로운 메모리가 할당 될 것 입니다. 배열은 매우 용량이 크므로, 빈 heap 공간은 빠르게 고갈되고, 결과적으로 쓰레기 수거가 자주 발생합니다. 이 문제를 피하는 한 방법은, 배열이 레퍼런스 타입이라는 사실을 이용하는 것 입니다. 매개변수로 함수에 전달된 배열은 그 함수에서 변경하고 그 결과는 함수가 반환된 이후에도 남아있게 됩니다. 이런 함수는 다음과 같은 함수로 종종 대체할 수 있습니다:-

  function RandomList(arrayToFill: float[]) {
	for (i = 0; i < arrayToFill.Length; i++) {
		arrayToFill[i] = Random.value;
	}
  }

이것은 배열의 기존 내용을 단순히 새 값으로 변경합니다. 비록 호출하는 코드에서 초기에는 배열을 할당해야 하지만, 이 함수의 호출이 새로운 쓰레기를 만들어내지는 않습니다.

Requesting a Collection 수거의 요청

위 에서 언급했듯이, 쓰레기 수거는 종종 실행의 일시 정지를 가져오며, 특히 live 오브젝트의 검색이 복잡할 경우 더욱 그렇습니다. 만일 게임플레이 동안 이것이 발생하면 결과는 눈에 보이겠지만, 다른 경우에는 게임에서 일시 멈춤이 별 영향이 없을 수도 있습니다(예: 스크린이 사라졌거나 메뉴가 보여질 때). 부적절한 순간에 멈춤을 피하기 위하여 Heap이 꽉 차지 않았을 경우에도 쓰레기 수거의 수행을 시스템에 요청할 수 있습니다.System.GC.Collect 함수를 사용하여 이 작업을 수행 할 수 있습니다:-

  function NotVeryMuchHappeningInGame() {
	System.GC.Collect();
  }

이 함수가 호출되어도 메모리 매니저가 반드시 수거를 수행하는 것은 아닙니다. 이는 필요하다면 지금이 GC을 수행하기에 좋은 시간이라는 것을 제안할 뿐입니다.

재활용 가능 오브젝트 풀(Reusable Object Pools)

생 성되고 삭제되는 오브젝트의 개수를 줄여서 쓰레기의 배출을 줄일 수 있는 경우도 많이 존재합니다. 게임에는 적군 캐릭터와 같이 한꺼번에는 적은 수만이 같이 나타나지만 반복해서 계속 만나게 되는 오브젝트의 타입이 있습니다. 이러한 경우에, 이전 것을 삭제하고 새것을 대체하기 보다는 오브젝트를 재활용 하는 것이 가능합니다. 예를 들어, 게임에서 적이 죽게 되면, 그 게임오브젝트(Game Object)를 삭제하기 보다는 단순히 숨겨둘 수 있습니다. 그리고, 새 적의 인스턴스가 필요할 때, "dead" 적군은 필요 시 마다 되찾아 올 수 있습니다.

구현

오 브젝트 풀(pool)을 구현하는 가장 간단한 방법은 해당 오브젝트 타입의 배열(array)을 시작하여 풀에 포함하는 것 입니다; 예를 들어, 게임에서 적을 나타내는 게임오브젝트를 풀에 구현한다고 합시다. 그 배열은 동시에 필요할 수 있는 적군의 최대 수를 포함하는 충분한 항목을 가지고 있어야 합니다.

	var enemyPool: GameObject[];
	var enemyPrefab: GameObject;
	var maxNumEnemies: int;
	function InitializeEnemyPool() {
		enemyPool = new GameObject[maxNumEnemies];
		for (i = 0; i < enemyPool.Length; i++) {
			enemyPool[i] = Instantiate(enemyPrefab);
			enemyPool[i].renderer.enabled = false;
		}
	}

한 적군은 배열 항목 중 하나를 단순히 복사하여 구할 수 있습니다. 그 적군이 다시 할당되지 않게 하려면 (필요하지 않을 때 까지), 그 배열 항목은 null로 설정되어야 합니다. 뒤따르는 할당에서 할당을 위해 배열에서 첫 번째 null이 아닌 항목을 검색하는 것보다는, 할당되지 않은 적군을 담고 있는 첫 인텍스를 가리키는 정수의 변수를 하나 두는 것이 최상의 방법입니다.

	var nextAvailableEnemy: int = 0;
	function GetEnemy() {
		var allocatedEnemy = enemyPool[nextAvailableEnemy];
		allocatedEnemy.renderer.enabled = true;
		enemyPool[nextAvailableEnemy] = null;
		nextAvailableEnemy++;
		return allocatedEnemy;
	}

적군이 죽거나 더 이상 필요치 않을 경우, 풀(pool)로 반환합니다. nextAvailableEnemy 바로 전의 배열 인덱스를 찾아 거기에 있는 적을 대체하면 됩니다.

	function ReleaseEnemy(doomedEnemy: GameObject) {
		doomedEnemy.renderer.enabled = false;
		nextAvailableEnemy--;
		enemyPool[nextAvailableEnemy] = doomedEnemy;
	}

효율성(Efficiency)

오 브젝트 풀(pool)은 빠른 속도로 생성되고 짧은 수명 주기를 가지며, 동시간에는 작은 수만 플레이 하는 타입의 오브젝트에 가장 최적입니다. 예를 들어, 입구 지점에서 적의 "무리가" 수도 없이 파도처럼 닥치지만 각자는 재빨리 제압되는 경우입니다. 이와 유사하게, 스펠 불꽃(spell sparkles), 탄환과 폭발 같이 고갈되지 않고 제공되는 물건이지만 게임에서 재빨리 사라지는 것 등입니다. 그러한 오브젝트의 새 인스턴스가 자주 생성되면 사용 가능한 heap 메모리도 빠르게 고갈되고, 쓰레기 수거는 주기적으로 발생할 것 입니다. 하지만, 오브젝트가 재 사용되면 풀이 만들어지고 나면 추가적인 할당이 필요하지 않을 것 입니다.

하 지만, 오브젝트 풀은 성능 면에서 조심하여 사용되어야 합니다. 한가지 문제는, 풀을 만들면 다른 목적으로 사용될 가용 heap 메모리가 줄어든 다는 것 입니다; 이 줄어든 heap에서 할당이 자주 발생하면 더 잦은 쓰레기 수거가 발생하게 됩니다. 다른 문제는, 수거에 소요되는 시간은 live 오브젝트의 수에 따라 증가한다는 것입니다. 이러한 문제를 염두에 두면, 너무 큰 풀을 할당하거나 거기에 포함된 오브젝트가 일정시간 사용되지 않을 경우에 성능저하가 발생한다는 것은 명백해 집니다. 더구나, 많은 오브젝트 타입은 오브젝트 풀과 맞지 않을 수 있습니다. 예를 들어, 게임에서 스펠 효과가 상당 시간 동안 지속되거나, 혹은 한꺼번에 많은 수의 적군이 나타나나 게임이 진행됨에 따라 천천히 죽어가는 경우입니다. 이러한 경우에는, 오브젝트의 성능 오버헤드가 혜택보다 월등하므로, 오브젝트 풀은 사용되어서는 안됩니다.

추가 정보

메모리 관리는 많은 학문적인 노력을 요하는 추상적이고 복잡한 주제입니다. 이에 대하여 더 공부하고 싶을 경우, memorymanagement.org는 훌륭한 자료로 많은 출판물과 온라인 기사를 담고 있습니다. 오브젝트 풀링에 대한 추가 정보는 Wikipedia page 와 Sourcemaking.com에서 찾을 수 있습니다.


Trackback 0 And Comment 0

유니티 게임 매니저 관련 글

|
  1. public class GameManager {
  2.     private static GameMananger instance;
  3.  
  4.     private GameMananger() {
  5.         // initialize your game manager here. Do not reference to GameObjects here (i.e. GameObject.Find etc.)
  6.         // because the game manager will be created before the objects
  7.     }    
  8.  
  9.     public static GameManager Instance {
  10.         get {
  11.             if(instance==null) {
  12.                 instance = new GameManager();
  13.             }
  14.  
  15.             return instance;
  16.         }
  17.     }
  18.  
  19.     // Add your game mananger members here
  20.     public void Pause(bool paused) {
  21.     }
  22. ...
  23. }



사용할때


  1. // Always use the .Instance Property to get the current instance of the GameMananger)
  2. GameManager.Instance.Pause(true);








FSM관리

유한상태기계


게임의 흐름을 제어하는​​ 데 열거형을 사용한다.


  1. public enum StateType
  2. {
  3.     DEFAULT,      //Fall-back state, should never happen
  4.     WAITING,      //waiting for other player to finish his turn
  5.     STARTTURN,    //Once, on start of each player's turn
  6.     PLAYING,      //My turn
  7.     PLACING,      //placing a new obstacle
  8.     BUYING,       //Buying something new
  9.     SHOOTING,     //aiming to shoot
  10.     BALLWAIT,     //Waiting for ball to stop
  11.     TURNOVER,
  12.     GAMEOVER,
  13.     GAMESTART,
  14.     LOBBY,        //Player is in the lobby
  15.     MENU,         //Player is viewing in-game menu
  16.     OPTIONS       //player is adjusting game options
  17. };

Update() function 에 아래와 같이 정의해서 사용합니다.

  1. switch (state)
  2.         {
  3.             case StateType.PLACING:
  4.                 if (objectToPlace != null)
  5.                     PlaceObject();
  6.                 else
  7.                     Debug.Log("ERROR: No object to place.");
  8.                 break;
  9.             case StateType.BUYING:
  10.                 break;
  11.             case StateType.BALLWAIT:
  12.                 //StopBouncing();
  13.                 break;
  14.             case StateType.STARTTURN:
  15.                 print("New Turn by: " + nowPlaying);
  16.                 IEvent startTurn = new StartTurn();
  17.                 EventManager.instance.QueueEvent(startTurn);
  18.                 AddEnergy();
  19.                 SetState(StateType.PLAYING, this);
  20.                 break;
  21.             case StateType.PLAYING:
  22.                 //check for numActions > MaxActions
  23.                 break;
  24.             case StateType.SHOOTING:
  25.                 break;
  26.             case StateType.TURNOVER:
  27.                 ChangePlayer(); //Do this last (from server!)
  28.                 SetState(StateType.STARTTURN, this);
  29.                 print("Turn is over!");
  30.                 break;
  31.             default:
  32.                 Debug.Log("ERROR: Unknown game state: " + state);
  33.                 break;
  34.         }


Trackback 0 And Comment 0

유니티 가로 세로 모드 설정

|


GameManager Start 에 아래 함수 추가

 Screen.orientation = ScreenOrientation.Portrait;

Trackback 0 And Comment 0

유니티 해상도 대응하기

|

Android

Screen.SetResolution(int width, int heignt, bool bFullScreen)

800×480 해상도 일 경우, SetResolution(800, 480, true)

Trackback 0 And Comment 0

cocos2d-x JSON 파일을 다루기 (JSONCpp 사용)

|

Json 이란?

JSON(제이슨, JavaScript Object Notation)은, 인터넷에서 자료를 주고받을 때 그 자료를 표현하는 방법이다. 자료의 종류에 큰 제한은 없으며, 특히 컴퓨터 프로그램변수값을 표현하는 데 적합하다.

그 형식은 자바스크립트의 구문 형식을 따르지만, 프로그래밍 언어플랫폼에 독립적이므로 C, C++, C#, 자바, 자바스크립트, , 파이썬 등 많은 언어에서 이용할 수 있다.


Json 홈페이지


json 모듈에는

jsoncpp, jsonBox, rapidjson 등이 있습니다.

안정성은 jsoncpp 속도는 rapidjson 을 선호하는 것 같습니다.

그중에 안전성이 있는 jsoncpp에 대해 알아보겠습니다.

jsoncpp홈페이지에서 파일을 다운받습니다.

http://jsoncpp.sourceforge.net/

jsoncpp-src-0.5.0.tar.gz


첨부파일의 include\json안에 있는 h 파일과

src\lib_json 안에 있는 모든 파일들을 cocos2d-x Class안에 집어넣습니다.












테스트로 읽을 json 파일입니다.

자신의 프로젝트 Resources에 json폴더를 만들고 그 안에 넣어줍니다.

test_data.json

소스입니다.

-> ReadJson버튼 클릭시 readJSON 호출

-> WriteJson버튼 클릭시 writeJSON 호출합니다.

읽을때

void HelloWorld::readJSON( CCObject *pSender )
{
       
    //json 파일 읽기
    //readUserInven("json/test_data.json");
    std::string fileName = CCFileUtils::sharedFileUtils()->fullPathForFilename("json/test_data.json");
       
    unsigned long bufferSize = 0;
    unsigned char* json = CCFileUtils::sharedFileUtils()->getFileData(fileName.c_str(), "rb", &bufferSize );
    std::string clearData((const char*)json,bufferSize); //파일 사이즈만큼 읽어옵니다.
       
    /*
    //파일 끝에 널을 붙여줌
    unsigned long tmpSize = 0;
    unsigned char *fileContent = cocos2d::CCFileUtils::sharedFileUtils()->getFileData( "test.txt", "r", &tmpSize );
    cocos2d::CCString *ccStr = cocos2d::CCString::createWithData( fileContent, tmpSize );
    cocos2d::CCLog( "str: %s", ccStr->getCString() );
    */
   
    //읽기
    readUserInven(clearData);
}




//json 파일 읽기
void HelloWorld::readUserInven( std::string pData )
{
    /*
    읽을 형식
    { "hello" : "world", "t" : true , "f" : false, "n": null, "i":123, "pi": 3.1416, "a":[1, 2, 3, 4] }
    */
    Json::Value root;
    Json::Reader reader;
    bool parsingSuccessful = reader.parse(pData, root);
    if (! parsingSuccessful)
    {
        CCLog("parser failed : \n %s", pData.c_str());
        return ;
    }

    CCLog("JSON ReadTest");

    std::string value1 = root.get("hello", "defaultvalue").asString();
    CCLog("value1 %s", value1.c_str());

    bool value2 = root.get("t", "default").asBool();
    CCLog("value2 %s", value2?"true":"false");

    bool value3 = root.get("f", "default").asBool();
    CCLog("value3 %s", value3?"true":"false");

    bool value4 = root.get("n", "default").isNull();
    CCLog("value4 %s", value4?"null":"?");

    int value5 = root.get("i", "default").asInt();
    CCLog("value5 %d", value5);

    double value6 = root.get("pi", "default").asDouble();
    CCLog("value6 %g", value6);

    {
        //array
        const Json::Value array = root["a"];
        for (unsigned int i = 0; i < array.size(); ++i)
        {
            int item = array[i].asInt();
            CCLog("%d, ", item);
        }
    }
}




파일을 쓸때


void HelloWorld::writeJSON( CCObject *pSender )
{
    //쓰기
    saveUserInven();
}



//JSON 데이터 생성
void HelloWorld::saveUserInven()
{
    // 위와 같은 json 문서 만들기
    Json::Value root;
    root["Name"] = "Hong Gildong";
    root["Age"] = 26;

    Json::Value friends;//배열
    friends.append("Im Kkeokjung");
    friends.append("Elisabeth");
    root["Friend"] = friends;
    root["Sex"] = "male";

    Json::StyledWriter writer;
    std::string strJSON = writer.write(root);

    CCLog("JSON WriteTest : %s" , strJSON.c_str());

    writeFileData( "testJSON.json", strJSON.c_str() );

}
//파일 쓰기
void HelloWorld::writeFileData( std::string pszFileName, const char* pData )
{    
    /*
    {
    "Age" : 26,
    "Friend" : [ "Im Kkeokjung", "Elisabeth" ],
    "Name" : "Hong Gildong",
    "Sex" : "male"
    }
    */

    FILE *fp = fopen(pszFileName.c_str(), "wb");

    if (! fp)
    {
        CCLog("can not create file %s", pszFileName.c_str());
        return;
    }
    else
    {
        CCLog("write file success: %s",pszFileName.c_str());
    }

    fputs(pData, fp); //pdata->fp에 복사

    fclose(fp);

}








jsonTest.zip




'잡다한것들전부 > 심화' 카테고리의 다른 글

cocos2d-x JSON 파일을 다루기 (JSONCpp 사용)  (1) 2013.12.04
Trackback 0 And Comment 1
  1. 브로콜리 2015.01.07 00:51 address edit & del reply

    감사합니다ㅠㅠ

헥사 게임 알고리즘

|
떨어지는 블럭의 위치를 기준으로 체크를 합니다. 이게 하나가 블럭이 떨어진 경우는 쉽게 처리가 가능한데

만약 상쇄되어 여러개가 그 밑으로 내려가서 반응하는 경우를 어렵게 생각하실거 같습니다만

모두를 하나씩 생각한다면 어렵지 않습니다.

 

일단 기본방법은 주위의 블럭을 비교해서 같은 것인지 체크를 합니다. 2차원 배열을 하나 만들어서 없어져야 할 블럭칸을 마킹 합니다.

마킹하고 또 주위 블럭을 검사하고 마킹합니다. 마킹한 블럭은 검사할 필요 없죠. 재귀호출 함수나 길찾기 알고리즘을 이용할 수 도 있습니다.

그래픽툴에서 색칠하기 공식도 유사하구요. 이렇게 해서 1단계 마킹처리가 끝나면 그 마킹된 위치의 블럭들을 없애는 처리를 합니다.

그러면 블럭사이에 빈 공간이 생길 수 있는데 블럭을 내리고 블럭의 칸들을 하나씩 검사해서 위 과정을 뒤풀이 합니다.


'잡다한것들전부 > ' 카테고리의 다른 글

배경 무한 스크롤링  (0) 2013.12.11
포물선 운동 관련 소스  (0) 2013.12.10
헥사 게임 알고리즘  (0) 2013.12.03
비쥬얼드 로직  (0) 2013.12.02
비쥬얼드 3개 블록 맞추는 로직  (0) 2013.12.02
cocos2d-x 3.0 관련 컴포넌트 사용  (0) 2013.12.02
Trackback 0 And Comment 0

비쥬얼드 로직

|
출처 : http://www.emanueleferonato.com/2010/12/16/complete-bejeweled-game-in-less-than-2kb/

package
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.text.TextField;
    public class n extends Sprite {
        private var jw:Array=new Array();
        private var g:Sprite;
        private var s:Sprite=new Sprite();
        private var pr:int=-10;
        private var pc:int=-10;
        private var cl:Array=new Array(0xFF0000,0xFF00,0xFF,0XFFFF00,0xFF00FF,0xFFFF,0xFFFFFF);
        private var cp:Boolean=false;
        private var ts:TextField=new TextField();
        private var th:TextField=new TextField();
        private var sc:uint=0;
        private var m:uint=0;
        public function n() {
            addChild(ts);
            ts.textColor=0xFFFFFF;
            ts.x=500;
            addChild(th);
            th.textColor=0xFFFFFF;
            th.x=550;
            for (var i:uint=0; i<8; i++) {
                jw[i]=new Array();
                for (var j:uint=0; j<8; j++) {
                    do {
                        jw[i][j]=Math.floor(Math.random()*7);
                    } while (rk(i,j)>2||ck(i,j)>2);
                    g=new Sprite();
                    g.graphics.beginFill(cl[jw[i][j]]);
                    g.graphics.drawCircle(30,30,29);
                    g.graphics.endFill();
                    g.name=i+"_"+j;
                    g.x=j*60;
                    g.y=i*60;
                    addChild(g);
                }
            }
            addChild(s);
            s.graphics.lineStyle(2,0xff0000,1);
            s.graphics.drawRect(0,0,60,60);
            s.visible=false;
            stage.addEventListener(MouseEvent.CLICK,ci);
            addEventListener(Event.ENTER_FRAME,ef);
        }
        private function ef(e:Event):void {
            var f:Boolean=false;
            for (var i:int=6; i>=0; i--) {
                for (var j:uint=0; j<8; j++) {
                    if (jw[i][j]!=-1&&jw[i+1][j]==-1) {
                        f=true;
                        jw[i+1][j]=jw[i][j];
                        jw[i][j]=-1;
                        getChildByName(i+"_"+j).y+=60;
                        getChildByName(i+"_"+j).name=(i+1)+"_"+j;
                        break;
                    }
                }
                if (f) {
                    break;
                }
            }
            if (! f) {
                var h:Boolean=false;
                for (i=7; i>=0; i--) {
                    for (j=0; j<8; j++) {
                        if (jw[i][j]==-1) {
                            h=true;
                            jw[0][j]=Math.floor(Math.random()*7);
                            g=new Sprite();
                            g.graphics.beginFill(cl[jw[0][j]]);
                            g.graphics.drawCircle(30,30,29);
                            g.graphics.endFill();
                            g.name="0_"+j;
                            g.x=j*60;
                            g.y=0;
                            addChild(g);
                            break;
                        }
                    }
                    if (h) {
                        break;
                    }
                }
                if (! h) {
                    var r:Boolean=false;
                    for (i=7; i>=0; i--) {
                        for (j=0; j<8; j++) {
                            if (rk(i,j)>2||ck(i,j)>2) {
                                r=true;
                                var tr:Array=[i+"_"+j];
                                var u:uint=jw[i][j];
                                var t:int;
                                if (rk(i,j)>2) {
                                    t=j;
                                    while (chk(u,i,t-1)) {
                                        t--;
                                        tr.push(i+"_"+t);
                                    }
                                    t=j;
                                    while (chk(u,i,t+1)) {
                                        t++;
                                        tr.push(i+"_"+t);
                                    }
                                }
                                if (ck(i,j)>2) {
                                    t=i;
                                    while (chk(u,t-1,j)) {
                                        t--;
                                        tr.push(t+"_"+j);
                                    }
                                    t=i;
                                    while (chk(u,t+1,j)) {
                                        t++;
                                        tr.push(t+"_"+j);
                                    }
                                }
                                for (i=0; i<tr.length; i++) {
                                    removeChild(getChildByName(tr[i]));
                                    var cd:Array=tr[i].split("_");
                                    jw[cd[0]][cd[1]]=-1;
                                    sc+=m;
                                    m++;
                                }
                                break;
                            }
                        }
                        if (r) {
                            break;
                        }
                    }
                    if (! r) {
                        cp=true;
                        m=0;
                    }
                }
            }
            ts.text=sc.toString();
        }
        private function ci(e:MouseEvent):void {
            if (cp) {
                if (mouseX<480&&mouseX>0&&mouseY<480&&mouseY>0) {
                    var sr:uint=Math.floor(mouseY/60);
                    var sc:uint=Math.floor(mouseX/60);
                    if (!(((sr==pr+1||sr==pr-1)&&sc==pc)||((sc==pc+1||sc==pc-1)&&sr==pr))) {
                        pr=sr;
                        pc=sc;
                        s.x=60*pc;
                        s.y=60*pr;
                        s.visible=true;
                    } else {
                        swp(pr,pc,sr,sc);
                        if (rk(pr,pc)>2||ck(pr,pc)>2||rk(sr,sc)>2||ck(sr,sc)>2) {
                            th.text="";
                            cp=false;
                            getChildByName(pr+"_"+pc).x=sc*60;
                            getChildByName(pr+"_"+pc).y=sr*60;
                            getChildByName(pr+"_"+pc).name="t";
                            getChildByName(sr+"_"+sc).x=pc*60;
                            getChildByName(sr+"_"+sc).y=pr*60;
                            getChildByName(sr+"_"+sc).name=pr+"_"+pc;
                            getChildByName("t").name=sr+"_"+sc;
                        } else {
                            swp(pr,pc,sr,sc);
                        }
                        pr=-10;
                        pc=-10;
                        s.visible=false;
                    }
                } else {
                    for (var i:uint=0; i<8; i++) {
                        for (var j:uint=0; j<8; j++) {
                            if (i<7) {
                                swp(i,j,i+1,j);
                                if ((rk(i,j)>2||ck(i,j)>2||rk(i+1,j)>2||ck(i+1,j)>2)) {
                                    th.text = i.toString()+","+j.toString()+"->"+(i+1).toString()+","+j.toString();
                                }
                                swp(i,j,i+1,j);
                            }
                            if (j<7) {
                                swp(i,j,i,j+1);
                                if ((rk(i,j)>2||ck(i,j)>2||rk(i,j+1)>2||ck(i,j+1)>2) ) {
                                    th.text = i.toString()+","+j.toString()+"->"+(i).toString()+","+(j+1).toString();
                                }
                                swp(i,j,i,j+1);
                            }
                        }
                    }
                }
            }
        }
 
        private function swp(r1:uint,c1:uint,r2:uint,c2:uint):void {
            var t:uint=jw[r1][c1];
            jw[r1][c1]=jw[r2][c2];
            jw[r2][c2]=t;
        }
        private function rk(r:uint,c:uint):uint {
            var u:uint=jw[r][c];
            var stk:uint=1;
            var t:int=c;
            while (chk(u,r,t-1)) {
                t--;
                stk++;
            }
            t=c;
            while (chk(u,r,t+1)) {
                t++;
                stk++;
            }
            return (stk);
        }
        private function ck(r:uint,c:uint):uint {
            var u:uint=jw[r][c];
            var stk:uint=1;
            var t:int=r;
            while (chk(u,t-1,c)) {
                t--;
                stk++;
            }
            t=r;
            while (chk(u,t+1,c)) {
                t++;
                stk++;
            }
            return (stk);
        }
        private function chk(g:uint,r:int,c:int):Boolean {
            if (jw[r]==null) {
                return false;
            }
            if (jw[r][c]==null) {
                return false;
            }
            return g==jw[r][c];
        }
    }
}


Trackback 0 And Comment 0
prev | 1 | ··· | 44 | 45 | 46 | 47 | 48 | 49 | 50 | next