1. MVC 패턴을 사용하는 곳은 슬롯에 있는 아이템을 제거할때이다.
그리고 절대로 데이털르 직접 건드리는것은 아니다.
요청하는 것 일 뿐입니다.
2. MVP 패턴은 View와 Presenter가 1:1매칭이라는 것 입니다.
어떠한 UI를 위해 Presenter를 썼으면 다른 UI를 위해서 쓰면 안된다.
UI에 유저가 어떤 Action이 들어왔는데 그 Action별 명령들을 Presenter에 구현해놓을려고 만든 것입니다.
그 명령들은 다양한 Data Model에 의존할 수 있습니다.
ex) 상점에다가 아이템 파는 오더
3. MVVM 패턴은 이론만 배우고 써보지 못했다.
4. 모바일 게임은 Stack으로 UI관리
PC게임은 LinkedList로 UI관리
PC게임에서는 더이상 UI는 Singleton이 되거나 Resources에서 Instantiate를 하지 않고 UIManager에서 가져올 것 입니다.
5. MonoBehaviour는 게임오브젝트의 컴포넌트입니다.
따라서 MonoBehaviour가 붙은 것들은 게임오브젝트가 생성된 후 Load가 되어야 에러가 생기지 않는다.
6. Scene에다가 배치를 미리 해두면 instance 멤버가 초기화가 안되기 때문에 Scene에 배치가 되있든 말든 GameObject를 생성을 합니다.
그럼 Scene에 미리 배치를 해놨을 때 Instnace는 언제 초기화를 하죠? 바로 Awake에서 초기화를 합니다.
따라서 Monobehaviour를 쓰는 친구들은 Awake에서 초기화하는 것도 만들어주긴 해야합니다.
즉, Awake에서 초기화하는 경우는 미리 배치가 되어있는 GameObject인 경우이
다.
7. Collection 일반적인 자료구조 형태를 가지고 있는데 인터페이스는 인덱서 접근 긴으을 가지고 있다. 즉, 내가 구현한 인터페이스 + Collection<T> 까지 상속받아서 인덱서 접근 기능까지 추가로 사용 가능하게 하는 것이 IList<T>를 상속받은거와 같기 때문입니다.
8. Collection<T> 를 상속받아서 Add라는 함수를 쓸때는 어차피 InsertItem이 마지막에 호출이 되기때문에 override한 InsertItem함수를 구현하고 그 안에 event 함수를 통해서 통지만 해줘도 구현이 똑같이 Add처럼 됩니다.
9. Collection을 상속받으면 생성자를 호출하느 순간 Item 들도 생성이 된다.
10. 항상 InventoryDataModel에서 아이템을 직접 수정하면 안되고 Set함수를 사용해서 바꿔줘야 합니다. Set함수를 사용해야 저장이 되기 때문입니다.
11. InventoryDataModel에서 필요한 것은 ObservableDataModelBase<ItemPair>와 같은 알림 통지 그리고 Save, Load가 필요합니다.
또한 안에서 사용할 Inner Class Data가 필요합니다.
아이템들을 IEnumeralbe<ItemPair> copy로 받아오고 new List<ItemPair>(copy); 로 저장합니다.
Data 이너클래스 안에는 아이템을 저장하는 List<ItemPair> 가 있습니다.
결론 IEnumerable<ItemPair>로 받아온 것은 List<T>에 초기화 해줄 수 있다.
왜냐하면 List<T>는 IENumerable<T>를 상속받기 때문이다.
12. Presenter도 DependencySource를 가진다 여기서 DependencySource란 이 Presenter가 관리하고 있는 DataModel의 정보를 Presenter에서도 가지고 있는 것이다.
결국 Presenter의 Source는 DataModel을 가져오라는 뜻이다.
13. Action tmpHandler = null;
대리자의 파라미터들은 주소참조를 쓰기 때문에 for(int i)에 있는 i같은 것을 쓰면안되고 int tmpIdx = i;처럼 선언을 한다음 i대신 써야한다. 공식으로여기자
14. UI와 Presenter는 1:1 매칭입니다. ViewModel은 1:다 Model이기때문에 보통 이제 ViewModel을 만들어 놓고 UI들을 연결해주면 되고 Presneter를 사용하는 MVP같은 형태들은 UI가 처음에 초기화될때 Presenter을 생성해서 참조해서 하면 편합니다.
15. Controller를 만들때는 각각을 다 분리를 해줘야합니다. Equipment에 있는 아이템을 핸들링하는 Controller를 만들어주고 Inventory에 있는 아이템을 핸들링하는 Controller를 따로 만들어주는 것 나중에 단축키에 등록할 Handling Controller를 따로 만들어주는 것 이렇게 따로 만들어줘야 합니다.
왜냐하면 내가 반드시 한번에 하나의 Controller만 활성화 될 수 있다는 것만 Managing 할 수 있는 ControllerManager를 만들어 놓고 UI에서 Click Event가 발생하면 그때는 ControllerManager한테 그 UI의 Slot에 해당하는 Controller만 활성화 제어권을 넘겨주는 것 입니다.
그럼 다른 Controller는 비활성화가 되기 때문에 문제가 생길일이 없게됩니다.
16. ControllerManager를 만든 이유는 결론적으로 UI단에 User 입력이 들어왔을때 이벤트 처리를 해주기 위해 만든 것이다.
17. ControllerManager의 Register의 함수를 호출해서 Manager에 등록을 해야하는데 그걸 Controller라는 추상 클래스를 만들어서 상속받으면 다른 Controller를 만들때도 상속만 받으면 되니까 해줍니다.
18. private void OnGUI()는 UI가 갱신될때 호출되는 함수입니다.
19. GraphicRacaster는 UI를 쓰는거고 우리는 물리적으로 쓸대는 Physics.Rayscast를 사용합니다.
20. BaseRaycaster를 상속받은 특정 Raycaster들이 있는데 특정 Evnet가 발생했을 때 object위에 있는 지 판별하는 함수인 IsPointerOverGameObject를 사용해서 현재 사용된 Raycast 종류가 Graphic 이라면 UIEvent이고 아니라면 World가 클릭된 것이기 때문에 아이템을 버리면 됩니다.
21. IsPointerOverGameObject<T>는 GameObject 1개만 가져오는것 TryGetHovered는 RayCast된 UI 싹다 가져오는것
22. 게임오브젝트는 is를 못쓴다.
23. Serialization 직렬화는 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것을 말한다.
직렬화 과정을 거치는 이유는 값 형식 데이터(Value Type) 우리가 흔히 선언해서 사용하는 int,float,char 등, 값 형식 데이터들은 스택에 메모리가 쌓이고 직접 접근이 가능하다.
참조 형식 데이터(Reference Type)은 C#에서 Object 타입 혹은 C++에서 포인터 변수들이 여기에 해당된다. 해당 형식의 변수를 선언하면 힙에 메모리가 할당되고 스택에서는 이 힙 메모리를 참조하는(힙에 메모리 번지 주소를 가지고 있음) 구조로 되어있다.
이 두가지 데이터 중에서 디스크에 저장하거나 통신에는 값 형식 데이터(Value Type)만 가능하다.
참조 형식 데이터(Reference Type)은 실제 데이터 값이 아닌 힙에 할당되어있는 메모리 번지 주소를 가지고 있기 때문에 저장, 통신에 사용할 수 없다.
따라서 직렬화를 하게 되면 각 주소값이 가지는 데이터들을 전부 끌어모아서 값 형식 데이터로 변환해준다.
결론, 직렬화를 쓰는 이유는 사용하고 있는 데이터들을 파일 저장 혹은 데이터 통신에서 파싱 할 수 있는 유의미한 데이터를 만들기 위함이다.
24. Math.Truncate(Decimal or Double); 숫자의 정수 부분을 계산합니다. 소수 자릿수를 삭제한 후 남은 숫자입니다.
25. StringBuilder를 쓰는 이유는 골드라는 친구를 구조체를 쓰는 이유는 멤버변수들의 도합이 메모리의 크기가 총합이 16byte이하이기 때문에 썼는데 StringBuilder타입 참조 변수를 추가하는 순간 넘어가 버리죠. 그러기 때문에 property로 쓰겠습니다. 접근 편의를 위해
또한 static을 안붙여주면 메모리를 잡아먹습니다.
26. StringBuilder란 C#의 StringBuilder는 변경할 수 없는 string과 달리 변경 가능한 문자열을 나타내는데 사용하는 클래스입니다. string 객체는 값이 변경되면 메모리에서 이전 참조 값을 버리고 새로운 참조 값으로 변경되지만, StringBuilder 객체는 참조 값이 변경되지 않고 힙 메모리에서 값이 삽입, 추가, 제거됩니다.
27. 데이터 모델을 만들고 Presenter를 만들고 UI단을 만든다.
28. UI를 만들때에는 클릭 했을때 클릭이 먹어야 하는 대상 빼고는 다 RayCast Target 대상이 되면 안됩니다. 어쨌든 UI를 클릭하는 것 자체도 Physical한 물리적인 충돌을 감지해가지고 연산을 하는 것입니다.
29. Decorator는 Invoke를 override 받고 구현까지 해준다 왜냐하면 상속받은 개체들이 결국은 내 바로 아래의 1개의 자식을 Decorate 한 다음 반환해주고 그 결과값을 왜곡하기 때문이다.
30. Composite는 Invoke를 override 하지 않는다 왜냐하면 Composite는 그 자체로 쓰는 것이아니라 자식을 여러개 가지고 있다 라는 뜻의 의미만 가지는 용도 이기 때문입니다.
31. 랜덤하게 뽑고싶을때는 Linq를 사용해서 Guid를 이용할 것인데 Guid는 글로벌하게 유의미한 아이디를 생성해줘라라는 구조체를 사용해서 고유한 아이디를 부여합니다. UnityEngine에도 Object들도 보면은 Object를 보면 고유의 인스턴스 아이디가 있었죠. 해시코드 아이디를 만들어서 보통 사용하는데 이런 특별한 아이디를 만들어서 사용하는데 이걸 정말 랜덤하게 섞고싶다 그러면 모든 자식들에 대해서 Random한 아이디를 생성하고 Random하게 생성된 아이디를 오름차순으로 정렬하게 해달라고 하면 완전히 섞이는 거죠
OrderBy(c => Guid.NewGuid())
를 넣어줍니다.
32. Sequence는 자식들중 하나라도 Success가 아니라면 실패반환.
33. Selector는 자식들중 하나라도 Failure가 아니라면 성공반환
34. (여기서 항상 bool 반환이라고해서 Predicate를 반환해서는 안된다 그 이유는 Predicate는 항상 bool을 반환하는 대리자지만 Predicate는 인자를 반드시 1개 이상 받아야하는 대리자이기 때문입니다. Func 대리자는 그러지 않습니다.)
35. 지금 보면 builder라고 만드는 함수들이 다 똑같이 생겼죠 그래서 나중에 C#을 좀 Deep 하게 공부하고나면은 이런 코드들을 저희가 일단 행동 종류에대해서 추가할때마다 BehaviourTree 함수들을 추가해줘야하잖아요 귀찮으니까 Code Generator를 학습을 해보시고 우리가 가지고 있는 행동들의 우리가 행동의 종류의 클래스를 하나 추가했다. 그럼 Build 함수를 알아서 만들어 주는 Code Generator도 한번 공부해보시는 것도 나쁘지 않습니다.
36. 2D Freeform Directional는 파라미터 2개를 가지고 Blending을 하는데 그 두가지 파라미터의 값에 따라서 또 다른 애니메이션들을 블랜딩 할 수 있는 거죠.
37. Has Exit Time이란 Exit Time 은 파라미터에 의존하지 않고 상태의 정규화된 시간에 의존하는 특별한 전환입니다. Exit Time에서 지정한 시간에 전환이 발생하도록 확인해야 합니다.
결국 Has Exit Time체크박스가 활성화된 경우 일정 시간이 지나면 전환이 자동으로 수행되고 상태 머신은 다음 상태를 플레이합니다. 자신이 만든 게임이 전환이 발생하는 시점을 적절히제어해야 한다면 비활성화하는 것이 좋습니다.
Hash Exit Time이 체크가 되어 있지 않으면 최소 1개의 Parameter가 필요하기 때문입니다.
즉, Conditions가 반드시 필요하다는 겁니다.
38. AnimatorMachineMonitor 라는 스크립트는doMove를 True 한다음에 Move에 대해서 이 Move가 정상적으로 애니메이션이 SubState로 넘어왔다라는 것이 호출이되고 호출이 되면은 Jump가 가능하다고 해야합니다. 즉, 내가 점프를 할려고 한다. 그러면은 현재 Move상태라는게 보장이 되어야합니다. 그걸 보장해주는 스크립트를 짜야합니다.
해시코드는 stateInfo의 fullPathHash에 있습니다.
39. AnimatorWrapper 란 Wrapper Class로써 기본 Class가 있으면은 캡슐화 해가지고 한번 더 감싸가지고 추가적인 기능이나 부호같은것을 구현하는 것을 Wrapper라고 합니다.
즉, AnimatorWrapper는 내가 움직이는 캐릭터 or 몬스터 와 같은 것들한테 Component 시킬 것이다.
Wrapper의 특징은 다른곳에서 Animator Component를 직접 가져와서 쓰지않고 Wrapper를 가져와서 쓸 것이기 때문에 Animator의 일부 기능들을 구현해줘야합니다.
그 기능은 Animator의 Parameter를 세팅하는 함수들을 Parameter의 값을 읽어오는 함수들을 Wrapping 함수들을 다 하나씩 만들어 주도록 합니다.
또한, Animation 클립의 시간에 따른 현재 진행 시간을 비율로 반환해주는 것이 NormalizedTime 입니다.
40. SetBoolParameterBehaviour 란 어떤 상태에 진입할 때 특정 bool Parameter를 true를 할 것이고 나갈때 false 할 것입니다. 따라서 StateMachineBehaviour를 상속받습니다.
(공격이나 스킬을 다 썼을때 마지막 모션일때 자연스럽게 Exit이 되게만들기 위해서 입니다.)
41. Length / Count 차이점
Length - 배열의 속성
Count - List의 클래스 속성이다.
하지만 Count는 양쪽에 사용가능하다.
42. 트리거(Trigger)란 영어로 방아쇠라는 뜻인데, 방아쇠를 당기면 그로 인해 총기 내부에서 알아서 일련의 작업을 실행하고 총알이 날아갑니다. 이처럼 데이터베이스에서도 트리거(Trigger)는 특정 테이블에 INSERT, DELETE, UPDATE 같은 DML 문이 수행되었을 때, 데이터베이스에서 자동으로 동작하도록 작성된 프로그램입니다. 즉! 사용자가 직접 호출하는 것이 아니라, 데이터베이스에서 자동적으로 호출하는 것이 가장 큰 특징입니다.
43. BehaviourTreeForCharacter를 만들기 위해서는 AnimatorWrapper를 가지고 있어야합니다.
이유는 AnimatorWrapper 안에 있는 Animator의 Parametor를 가져올 것이기 대문입니다.
44. 열거자 IEnumerator는 MoveNext()를 통해서 실행하는 것이다.
1. 열거자는 최소 한 개의 yield 문을 가지고 있어야 한다.
2. 열거자는 변수처럼 대입하여 사용할 수 있다.
3. MoveNext 메소드를 통해 열거자 내부의 내용을 실행할 수 있다.
또한, 열거자에 대하여 MoveNext를 실행하기 전의 Current는 null이다.
45. MotionCommand는 모든 Motion의 class들이 상속받을 만한 내용을 적어둔 것입니다.
안의 내용은 어떤 모션을 실행시키고 모션이 정상적으로 끝날때까지 기다린 다음 끝나지 않았다라면 Running을 반환하는 것으로 행동에 머물러 있어야 합니다.
끝나게 되면은 그때되어서야 Success 같은 것을 반환해서 다시 탐색을 할 수 있도록 해야합니다.
46. 코루틴을 실행한 주체가 비활성화되면 코루틴도 돌아가지 않습니다.
47. Is Kinematic : 외부에서 가해지는 물리적 힘에 반응하지 않는 오브젝트라는 의미.
48. MovementBase를 만든 이유는 자연스러운 Animation을 위해서 애니메이션의 Transform의 변경되는 내용들을 직접 실제 플레이어의 포지션에다가 적용할 것이고 우리는 RootMotion을 쓴다고 했다.
그래서 RootMotionMode일때는 들어온 애니메이션에 대해서 float값을 세팅을 해주고 ManualMode다 라고 하면은 미리 저장해놓은 관성 inertia를 사용해서 움직이게 해줍니다.
49. 에러 'Player - Yuji' AnimationEvent 'Land' on animation 'Unarmed-Land' has no receiver! Are you missing a component? 라고 뜨면
Jump->Fall->Land로 넘어가는 Has Exit Time와 Conditions들을 확인해줍니다.
50. SetBoolParameterBehaviour.cs 는 어떤 상태에 진입할 때 특정 bool Parameter를 true를 할 것이고 나갈때 false하는 것 입니다.
51. 트리거의 특성은 쓸때는 쓰는 것인데 한번 읽으면 그 값이 꺼져야 합니다.
즉, true상태로 get 접근이 한번 일어나는 순간 false가 됩니다.
52. target 프로퍼티에서 뜨는건가여
근데 Set 인데 왜 null reference 인거죠
53. NavMesh
54. dirty Set AnimatorMonitor에서 해보기
55. Serializable 이 필요할때 3가지 경우
생성한 객체를 파일로 저장할 일이 있을 수도 있습니다.
저장한 객체를 읽을 일이 생길 수도 있습니다.
다른 서버에서 생성한 객체를 받을 일도 생길 수 있습니다.
56. enum의 요소를 enum이라는 Type 자체가 열거형인데 enum Type은 처음부터 끝까지 값에 따라 순회하려는 내용으로도 사용한단 말입니다.
안타까운건 Unity .net 버전이 최고 높은게 4.s버전까지인데 거기까지 지원하는 C#버전이 7.0인가 까지일것입니다.
EnumType에서 특정타입을 순회를 하는 방법이 Enum이라는 Class에 있는데 그 Class에 GetValues 라는 것이 있습니다.
57. Enum타입에 정해져있는 모든 요소들을 Array로 받아오는 것 입니다.
Array Enum.GetValues(Type enumType) 으로 Type을 받아오고 Array를 받아오는 것 입니다.
58. 하지만 Array를 받아올 때 언박싱이 일어납니다. 아마 C# 9.0부터는 Generic을 지원하는데 유니티에서는 사용을 못하기 때문에 박싱 언박싱이 일어날 것입니다.
'기타' 카테고리의 다른 글
모의 면접 질문 (3가지) (0) | 2024.09.29 |
---|---|
2024-08-09 금요일 TIL 마무리 (0) | 2024.08.09 |
Stack과 Heap의 차이점 (0) | 2024.07.08 |
혼자 포폴하면서 느낀점 - 2 (0) | 2024.06.24 |
스파르타코딩클럽 - 스타터 노트 작성 - 박용현(Node.js_6기) (0) | 2024.06.19 |