http://www.richardfine.co.uk/2012/10/unity3d-monobehaviour-lifecycle/ : MonoBehaviour Lifecycle 팁에 대한 정리을 한다고 했으니까... 오늘 그냥 해봐야 겠습니다. 원본 : http://devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 한글 : http://szone2s.blog.me/70151813805 1. 50 Tips for Working with Unity (Best Pratices) A. 1. Avoid branching assets. Asset 을 여러 버전으로 나누지 말라.항상 모든
Asset은 오직 한 버전으로 있어야 함. B. Each team member should have a second copy of the project checked out for testing 버전 컨트롤을 사용할 경우 각 팀 구성원들은 테스트를 위해 체크 아웃한 프로젝트의 두번째 복사본이 있어야 한다. 두번째 복사본은 clean copy 및 update 을 하고 테스트 해야 한다. C. Consider using external level tools for level editing. 레벨 수정을 위한 외부 레벨 툴을 사용하는 것을 고려하라. Unity 는 완벽한 레벨 에디터가 아니다. 예로 우리는 3D tile 기반의 게임을 위해 레벨 빌드를 TuBee 를 사용하여 만들었다. 우리는 Tile 친화적인 툴을 통해 도움을 받았다.(그리드 가 붙은, 그리고 90도 로 여러 번 회전, 2D 뷰, 빠른 선택). XML 파일을 통한 prefab 초기화는 간단합니다. TuDee : http://www.diorgo.com/v1/?p=366Guerrilla Tool Development : http://devmag.org.za/2009/10/23/guerrilla-tool-development/ (이곳에 자세한 아이디어가 있다고 합니다.) D. Consider saving levels in XML instead of in scenes.레벨 저장을 Scene 대신 XML으로 하는 것을 고려하라.(훌륭한 기술!!!) - 이렇게 만들면 각각의 scene을 다시 만드는게 불필요 함.- 보다 빠르게 로딩 (대부분의 객체가 scene 에서 공유되는 경우) - scene 을 합치는 것이 쉬워짐.(Unity의 새로운 text 기반 scene 은 너무 많은 데이터를 포함하고 있어 합치는 것이 비현실적으로 보임) - 데이터 레벨 수준에서 관리를 할 수 있음.당신은 여전히 Unity 를 레벨 에디터로 사용 할수 있음. 네가 데이터, 에디터와 레벨 로드를 실시간으로 처리 , 에디터로부터 레벨 저장을 해야 할 경우 몇몇의 코드는 직렬화 와 역직렬화를 필요로 하게 된다. 너는 아마 또한 객체간 참조를 유지하기 위해 Unity 의 id System 을 모방 해야 할 것이다. E. Consider writing generic custom inspector code. 일반적인 커스텀 inspector 코드를 작성하는 걸 고려하라Custom inspector 를 작성하는 건 매우
간단하나, Unity 의 시스템은 많은 단점을 가지고 있음. 2. Scene Organisation A. Use named empty game objects as scene folders. Scene 폴더를 빈 게임 오브젝트의 이름으로 사용하라. B. Put maintenance prefabs and folders (empty game objects) at 0 0 0. 관리하는 prefab 과 폴더( 빈 게임 오브젝트) 를 0 0 0 에
넣습니다.만약 위치를 명시하지 않은 채 오브젝트의 위치를 사용 하면, 아마 원점에 있을 것이다. C. Minimise using offsets for GUI components. GUI 컴포넌트의 offset 사용을 최소화 하라. Offset 은 항상 자신의 부모 component 에서 레이아웃 Component 를 사용해야 합니다.그들은 조부모의 위치에 의존해서는 안됨. Offset을 올바르게 표시하기 위해서는 서로를 취소 할 수 없다. 이런 일을 방지 하기 위해서 기본적으로 부모 컨테이너가 임의의 위치로 (100, -50) 이고 자식의 위치가 (10,10) 이기를 희망하는 경우, 위치 정의를 (90,60) [relative to parent] 으로 하면 된다. 이 에러는 컨테이너가 invisible 상태일 때 공통으로 발생하며, 또는 시각적 표현이 없는 경우에 해당함. D. Put your world floor at y = 0. E. Make the game runnable from every scene. 모든 scene 을 게임 실행 가능하게 만들어라.이건 대폭적으로 테스트 시간을 줄일 수 있다. myObject = FindMyObjectInScene(); 3. ART 부분 A. Put character and standing object pivots at the base, not in the centre.캐릭터와 서있는 오브젝트는 pivot
기반이여 하며, center 중심이어서는 아니된다.이런식으로 만들면 보다 쉽게 캐릭터와 오브젝트를 바닥에 올려놓을 수 있다. B.
Make all meshes face in the same direction (positive or negative z axis). 제작하는 모든 메쉬의 바라보는 방향을 일치 하라.(+Z 또는 –Z)캐릭터와 다른 오브젝트들의 메시는 바라보는 방향이 다르게 적용이 됩니다. C. Get the scale right from the beginning시작시 스케일의 규모를 정하도록 한다.만든 작업물을 임포트 할 때 스케일 크기를 1로 하게
되면, 그것의 트랜스폼 스케일은 1 1 1 이 된다. D.
Make a two-poly plane GUI 컴포넌트 와 파티클을 수동으로 생성 해야 할 경우, 2개의 삼각형으로 된 평면을 사용 합니다. E. Make and use test art 테스트 작업물 만들기 및 사용- 스카이 박스들을 위한 사각형 표기. 4. Prefabs A. Use prefabs for everything. 모든 것에 프리팹을 사용하도록 한다.당신의 scene 에 게임 오브젝트만 있는 경우에는 프리팹이 폴더에 있을 필요는 없다. B. Use separate
prefabs for specialisation; do not specialise instances 특수화된 프리팹은 사용해도 좋지만, 특수화 된 인스턴스는 사용하지 말라.만약 당신이 두개의 적 타입을 가지고 있는 경우, 그리고 그것들이 프로퍼티만 다른 경우, 속성에 대해 별도의 프리팹을 만들고, 그것을 링크 합니다. C. Link prefabs to prefabs; do not link instances to instances. 프리팹과 프리팹의 링크는 되나; 인스턴스 와 인스턴스 간의 링크는 안된다. scene 에 프리팹을 끌어 놓을 때 프리팹의 연결이 유지 됩니다.인스턴스에는 링크가 없습니다. 프리팹을 연결할 때마다 scene의 설정을 줄여 주는게 가능해지며,, scene 을 변경 할 경우도 줄여 줄 수 있습니다. D.
As far as possible, establish links between instances automatically. 가능하다면, 인스턴스간의 연결 설정은 자동으로 하라만약 당신이 인스턴스간의 링크를 필요로 한다면, 프로그래밍 적으로 링크를 설정 합니다. E. Use safe processes to branch prefabs. 분기 프리팹에 대해서 안전한 절차를 사용하도록 하라. 1. 복제된 Player 프리팹이 있습니다.2. 복제된 거에 대한 이름을 __Player_Backup 로 변경합니다. 3. Player prefab 으로 생성한 걸 바꿉니다. 4. 작업이 진행 될 경우 __Player_Backup 를 지웁니다.복제후 Player_New 으로 이름을 바꿔선 안되면, 생성된 걸 바꿔선 안됩니다. 일부는 상황이 더 복잡합니다. 예를 들어, 특정 변화는 두 사람을 포함 할 수 있으며, 두사람이 위의 과정을 따라하면서 작업을 완료하면 작업한 scene 을 망가질 수 있습니다. If it is quick enough, still follow the process above 그래도 여전히 필요로 하는 경우, 위의 절차를 따르십시오, 바꾸는데 시간이 오래 걸릴 경우, 다음의 절차를 따라야 할 수 있습니다. 1. 사람 1 :a. Player 프리팹을 복제 합니다. b. 이름을 __Player_WithNewFeature 나 __Player_ForPerson2 로 바꿉니다. c. 복제된 걸로 변경을 하고, 커밋을 하여 [사람 2]에게 제공합니다. 2. 사람 2:a. 새로운 프리팹으로 변경 생성 b. Player 프리팹을 복제하고, __Player_Backup 이라고 부릅니다. c. __Player_withNewFeature 인스턴스를 scene 으로 드래그 합니다. d. 오리지날 Player 프리팹을 인스턴스에 드래그 합니다. 5. Extensions and MonoBehaviourBase A. Extend your own base mono behaviour, and derive all your components from it. 기본 mono behavior 를 확장 하고, 당신의 컴포넌트를 그것으로부터 모두 파생하라.이렇게 하면 몇가지 일반적인 기능을 구현 할 수 있으며, 이러한 유형의 호출에 안전하고 복잡한 호출이 가능해 집니다. (예로 무작위 호출) B. Define safe methods for Invoke, StartCoroutine and Instantiate. Invoke 를 위해 안전한 메서드를 정의 하며, StartCoroutine 과 Instantiate 가 있다. Task delegate 를 정의 하고, 문자열 이름에 의존하지 않는 방법을 정의 하는데 사용합니다.public void Invoke(Task task, float time) C. Use extensions to work with components that share an interface. 공유 인터페이스를 사용하여 컴포넌트를
함께 작동하도록 확장을 사용합니다.가끔 특정 인터페이스의 구현된 컴포넌트를 얻어오는데 편리하거나, 앞의 언급한 컴포넌트를 가지고 오브젝트를 찾는데 편합니다. //Defined in the common base class for all mono behaviours foreach(MonoBehaviour behavior in monoBehaviours) D. Use extensions to make syntax more convenient. 구문보다 편리하게 사용하기 위해 확장을 사용합니다. public static class CSTransform E. Use a defensive GetComponent alternative.
방어적인 GetComponent 를 대안으로 사용하라Sometimes forcing component dependencies (through requiredComponent) can be a pain. public static T GetSafeComponent<T>(this GameObject obj) where T : MonoBehaviour 6. Idioms A. Avoid using different idioms to do the same thing. 비슷한 일에 다른 해결책을 사용하지 마십시요.대부분의 경우 일을 할 때 마다 하나 이상의 해결책이 있습니다. 7. Time A. Maintain your own time class to make pausing easier. 쉽게 일시 중지 하기 위해 당신만의 Time class 를 유지하라. Wrap time.DeltaTime 와 Time.TimeSinceLevelLoad 은 계정 별 일시 중지와 시간 scale 이 가능합니다.이것을 사용하는데는 훈련이 필요로 하지만, 많은 부분에 대해 쉽게 제작 가능하며, 특히 다른 Time 의 일을 실행하기 편합니다. (예로 interface 애니메이션 과 게임 에니메이션 등) 8. Spawning Object A. Don’t let spawned objects clutter your hierarchy when the game runs. 게임이 실행 될 때 생성되는 개체가 계층 구조를 더럽히게 하지 마라. Set their parents to a scene object to make it easier to find stuff when the game is running. 게임이 실행 중일 때 개체를 쉽게 찾을 수 있도록 scene 개체에 부모를 설정 합니다.비어있는 게임 오브젝트를 사용하거나 behavior 가 없는 싱글톤을 이용하여 만들면 코드에 접근하기 쉽습니다. 이 오브젝트를 DynamicObjects 라고 부릅니다. 9. Class Design. A. Use singletons for convenience. 편의를 위해 싱글톤을 사용하라. public class Singleton<T> : monoBehaviour where T : MonoBehaviour - 고유한 프리팹의 인스턴스를 위한 싱글톤은 사용하는 걸 피하고 관리하지 않는게 좋습니다.(Player 같은) 이 원칙을 준수하지 않으면 상속 계층 구조를 복잡하게 하며, 그리고 특정 유형의 변경을 힘들게 합니다. 오히려 GameManager 에서 참조를 유지하는게 좋습니다.(또는 다른 전지 전능한 클래스)- 종종 클래스 외부에서 사용되는 public 변수 와 메소드 에 대한 static 속성과 메서드를 사용합니다. GameManager.Instance.player 대신에 GameManager.Player 으로 작성이 가능합니다. B. For components, never make
variables public that should not be tweaked in the inspector. Component 들을 들어, inspector 에 변화를 주지 말아야 할 변수는 공개하지 않습니다.그렇지 않으면 그것은 무엇을 하ㄴ는지 알수 없게 되어 디자이너가 변경을 해버리게 됩니다. C. Separate interface from game logic. 게임
로직에서 인터페이를 분리하여 제공합니다.(이것은 기본적인 MVC 패턴입니다.)모든 입력 컨트롤러는 호출되여 알려 해당 컴포넌트에 명령을 제공해야 합니다. D. Separate state and bookkeeping. 별도의 상태와 Bookkeeping Bookkeeping 변수는 빠르게 또는 편리하게 사용하기 위함이며, 그리고 현재 상태로부터 복구하는 걸 가능하게 해준다. 이렇게 분리하면, 당신은 더 쉽게 적용 가능하다.- 게임 상태 저장 그리고 게임 상태 디버그한가지 방법은 게임 로직 클래스를 위해 SaveData 클래스를 정의하는 것이다.[Serializable] Player E. Separate specialisation configuration. 별도의 특성화
구성동일한 메시들로 두개의 적을 고려 하는데, 벨런스 값이 다르다. (Tweakable 들은 상태 데이터가 아니나 구성 데이터로, 그래서 저장할 필요가 없습니다.개체가 로드 되거나 생성되는 경우, tweakable 들은 별도로 자동으로 로드 됩니다.) - 각각의 게임 클래스에 템플릿 클래스를 정의합니다. 예로 , 적인 경우 우리는 또한 enemyTemplate 라고 정의 합니다. 모든 차별화된 tweakable 들은 EnemyTemplate 에 저장합니다.- 게임 로직 클래스 에는, 변수나 템플릿 타입을 정의 합니다. - 적 프리팹을 만들고, 두개의 템플릿 프리팹 WeakEnemyTemplate, and StrongEnemyTemplate 을 만듬. - 로딩 하거나 오브젝트를 생성하면, 정식 템플릿에 템플릿 변수를 설정 합니다.이 방법은 매우 정교한 방법이 될 수 있습니다. 그리고 때로는 불필요하게 복잡하므로 주의! 예를 들어, generic 다형성을 사용하기 위해, 우리는 아마 이런식으로 정의 하는 것이 좋을겁니다. public class BaseTemplate public class ActorTemplate : BaseTemplate public class Entity<EntityTemplateType> where EntityTemplateType : BaseTemplate public class Actor :
Entity <ActorTemplate> F. Don’t use strings for anything other than displayed text. 표시 텍스트 이외에 다른 용도로 문자열을 사용하지 마시오.특히 개체 나 프리팹의 식별을 위해서 문자열을 사용하지
않습니다. G. Avoid using public index-coupled arrays공개된 인덱스 결합 배열을 사용하지 마시오.예로 무기 배열 , 총알 배열, 파티클 배열을 정의 하지 않는 것으로 , 이런 경우에 대해서 좋은 방법은 아래와 같습니다. (역자 : 배열의 인덱스를 직접적으로 사용하는 것 줄이라는 의미) public void SelectWeapon(int index) 오히려, 세 변수를 캡슐화 하는 클래스를 정의하고 그 배열을 확인 하십시요. [Serializable] H. Avoid using arrays for structure other than sequences.
시퀀스 이외의 다른 구조에 대한 배열을 사용하지 마시오.예로 플레이어가 세개의 공격 타입을 가지고 있다고 하면, 각각 현재 무기를 사용하지만 서로 다른 포탄과 다른 동작을 생성합니다. public void FireAttack() Enums 을 사용하면 좀 더 나은 코드가 될 수 있습니다.public void WindAttack() 그것은 별도의 변수를 사용하는 것이 좋기 때문에 어떤 콘텐츠를 넣어도 이름으로 도움말이 될수 있습니다. 타입이 단정지어질 때 클래스를 만듭니다. [Serializable] Fire I. Group data in serializable classes to make things neater in the inspector. Serializable 클래스의 그룹 데이터는
가까운거 끼리 모아 inspector 로 만들어야 한다.어떤 엔티티는 수십개의 조절할게 있을 수 있습니다. - 변수의 그룹에 대한 별도의 클래스를 정의 합니다. 그것들을 public 및 serializable 합니다.- 기본 클래스 에서 , 위와 같이 정의된 각각의 유형의 public 변수를 정의 합니다. - 변수를 Awake 나 Start 에서 초기화 하면 안되며, 그것들은 serializable 이기 때문에 Unity에서 잘 처리 해 줄 것입니다. - 당신은 정의된 변수가 연결되기 전에 초기화를 지정하는게 가능하다. Inspector 의 접을 수 있는 공간의 그룹 변수들은, 관리를 쉽게 합니다.[serializable] public class HealthProperties //not a
monobehaviour public class Player : MonoBehaviour 10. TEXT A. If you have a lot of story text, put it in a file. 스토리 텍스트가 많은 경우 , 파일에 넣도록 하라. inspector 에 에디팅 할 수 있는 영역으로 두지 마라라. 이것은 Unity 에디터를 열지 않고도 변경을 쉽게 해 줄 것이며, 특히 scene 을 저장하지 않고도 가능 할 것입니다.B. If you have a lot of story text, put it in a file. 당신이 로컬라이징을 할 계획이 있다면, 하나의 지역에 모든 문자열을 분리합니다.이 작업을 수행하는 방법에는 여러가지가 있습니다. 11. Teting and Debugging A. Implement a graphical logger to debug physics, animation, and AI. 물리, 애니메이션, 그리고 AI 를 디버깅하기 위해서 그래픽 logger 를 구현
합니다. B. Implement a HTML logger. HTML logger 를 정의합니다.몇가지 경우에 대해서 , logging 은 매우 유용하다, 구문 분석 (컬러 코드, 멀티 뷰, 스크린샷 기록 )을 하게 되면 로그를 디버깅 하는게 훨씬 쾌적 할 수
있습니다. C. Implement your own FPS counter. 당신의 FPS counter 를 구현합니다. Unity 의 FBS counter 가 정말 제대로 측정할지도 모르나, 그것은 프레임 레이트가 아닙니다.직관과 육안 검사와 일치 할 수 있도록 자신의 것을 구현 합니다. D. Implement shortcuts for taking screen shots. 스크린샷을 이용해 바로가기를 구현합니다.많은 버그는 비쥬얼이며, 그리고 당신은 사진을 찍어두면 보고가 좀 더
쉬워집니다. E. Implement shortcuts for printing the player’s world position. 플레이어의 월드 위치를 출력하기 위한 바로가기를 구현합니다.이것은 월드의 특정 장소에서 발생하는 버그의 위치를 리포트를 하기 쉬워질 것이며, 이는 번갈아 가면서도 쉽게 디버깅 할 수 있습니다. F.
Implement debug options for making testing easier. 테스트를 쉽게 만들기 위한 디버그 옵션을 구현합니다. - 모든 아이템 언락- 적 제거 - 플레이어 무적 - 모든 게임 플레이 불가 G. For teams that are small enough, make a prefab for each team member with debug options. 충분히 작은 팀의 경우, 디버그 옵션을 사용하여 각
팀의 구성원을 위한 prefab 을 만듭니다. H. Maintain a scene with all gameplay elements. 모든 게임 플레이 요소와 scene 을 유지 합니다.예로 모든 적이 있는 scene , 당신이 상호 작용 할 수 있는 모든 개체, 그외 등등. 너무 오래 게임을 하지 않고 기능을 테스트 할 수 있도록 합니다. I. Define constants for debug shortcut keys, and keep them in one place. 디버그 바로 가기 키를 위한 상수를 정의하고, 한곳에서
보관합니다.디버그 키는 일반적으로 (또는 편리한) 게임 입력이 처리되는 위치에서 같이 처리 되지는 않습니다. 12. Documentation A. Document your setup. 당신의 setup을 문서화
합니다.대부분의 코드는 문서에 있어야 하며, 하지만 이러한 것은 코드 외부에서 문서화 해야 합니다. - 레이어 사용 (충돌, 컬링, raycasting – essentially , 어떤 항목에 어떤걸 해야)- 태그 사용. - 레이어를 위한 GUI 깊이 (뭇을 통해서 표시해야) - scene 설치 - Idiom 설정 - 프리팹 구조 - 애니메이션 레이어 13. Naming Stanard and Folder Struture A. Follow a documented naming convention and folder structure. 문서화 규칙 및 폴더 구조를 따르시요. i. 무언가를 호출 합니다. bird 는 Bird 를 호출 합니다. ii. 이름을 선택 할 때는 확연하고 기억될 수 있는 이름으로 선택합니다. 만약 당신이 마야 게임을 만든다고 해서, 레벨 이름을 QuetzalcoatisReturn 로 해서는 안됩니다. iii. 일관성을 유지 하십시오. 이름을 선택할때, 기준에 충실해야 합니다. iv. Use Pascal case, like this: ComplicatedVerySpecificObject. Do not use spaces, underscores, or hyphens, with one exception (see Naming Different Aspects of the Same
Thing). v. 버전 번호를 사용하지 말고, 또는 단어로 진행 상태를 표시 하지 마십시오 (WIP, final). vi. Do not use abbreviations: DVamp@W should be DarkVampire@Walk. vii. 디자인 문서의 용어를 사용합니다: 사망 을 문서상 호출 하려면 Die 애니메이션을 부릅니다. DarkVampire@Die, 를 부르며 DarkVampire@Death 는 안됩니다. viii. 구체적인 설명은 왼쪽에 표기 합니다: DarkVampire 는 좋은 방법이며 VampireDark 는 안좋은 방법입니다. PauseButton는 좋은 방법이며 ButtonPaused는 안좋은 방법입니다. 이것을 예로 들면, 모든 버튼이 단어 버튼으로 시작하면 inspector 에서 일시 정지 버튼을 찾기 쉬워집니다. [많은 사람들이 다른 방법을 더 선호하며, 때문에 시각적으로 보다 더 확실히 그룹화를 하여 생성합니다. 이름이 있지만 그룹화를 위한게 아니며, 폴더를 위한것 입니다. 이름이 안정적으로 빠르게 자리 잡고 할 수 있도록 동일한 유형의 객체를 구분하는 것 입니다.] ix. 일부 이름은 순서를 형성합니다. 이름에 숫자를 사용하며, 예로 PathNode0,PathNode1 가 있습니다. 항상 시작은 1이 아닌 0으로 시작합니다. x. 순서를 필요로 하지 않는 일에 번호를 사용하지 마십시오. 예로 Bird0, Bird1,Bird2 는 Flamingo, Eagle, Swallow 라고 표기합니다. xi. 임시 객체는 이중으로 접두사에 언더바를 넣습니다 __Player_Backup. B. Naming Different Aspects of the Same Thing언더바와 핵심 이름을 사용하여 해당 상태에 “세부” 내용을 설명합니다. C. Structure : 당신은 scene 의 구성, 프로젝트 폴더, 그리고 스트립트 폴더는 유사한 패턴을 가져야 합니다. i. Folder Structure Materials ii. Scene Structure Cameras D. Scripts Folder Structure ThirdParty 14. How to Re-implement Inspector Drawing. A. 당신의 모든 에디터를 위한 기본 클래스를 정의 BaseEditor<T> : Editor where T : MonoBehaviour B. Reflection 과 recursion를 사용하여 draw 컴포넌트 에
reflection을 사용public static void DrawDefaultInspectors<T>(GUIContent label, T target) where T : new() foreach(FieldInfo field in
fields) MethodInfo drawMethod = EditorGUI.indentLevel--; private static GUIContent MakeLabel(FieldInfo field) C.
Define new Custom Editors [CustomEditor(typeof(MyClass))] |