====== 목표 ======
작성하려는 로직
===== 로직 시나리오 =====
임의 오브젝트에 대해서, 아래 과정을 반복한다.
- 최초 위치로 이동 시킨다
* 판단 부분 추가
* 초기 위치로 이동시킬 것인가?
* 현재 위치에서 바로 다른 움직임을 시작할 것인가?
- 다음 이동 위치를 결정한다
* 다음 중 선택
- 정해진 루트를 순서대로 탐방하는 방식
- 정해진 루트 중에 한 곳을 임의 선택해서 이동
- 정해진 위치로 이동
- 도착하면 다른 오브젝트에 메시지를 전송
- 잠시 대기
- 2번 루트로 되돌아 가서 반복
끝
===== 사용하려는 오브젝트 =====
{{:language:unity:playmaker:pmexam1_hierarchy_2.png|}}
* **MovingObject** : 이동할 오브젝트
* **Position** : 오브젝트가 이동할 경로들의 부모 오브젝트
* **1_MovPath** : 초기 위치. (여기로 이동할 것인가, 초반에 선택)
* **2_MovPath ~ 5_MovPath** : 이동 경로. 순서대로 이동할지, 랜덤하게 선택하게 이동할지 결정.
* **MsgRecver** : MovingObject의 메시지를 받을 서브 오브젝트.
===== 씬 화면 =====
| {{:language:unity:4-playmaker:pmexam1_gameview_1.png|}} | 움직일 오브젝트, **MovingObject** |
| {{:language:unity:4-playmaker:pmexam1_gameview_2.png|}} | **2_MovPath ~ 5_MovPath**에 기즈모 마크 추가 |
====== 1차 : Path 순서대로 이동하기 ======
===== 최종 목표 =====
{{:language:unity:playmaker:pmexam1_movingaround_1.png|}}
==== 움직이는 순서 ====
- 최초이동
- 다음 이동 좌표 구하기
- 정한 좌표로 이동
- 잠시 대기, 2번으로 돌아가서 반복
==== 사용하는 액션 ====
나중에 한번에 찾아보기 좋게 정리해 놓은 것. 지금 봐둘 필요는 없는 부분.
= Bool Test : Bool 타입의 변수에 대해서 IF 문을 수행
= Get Child Count : 자식 오브젝트의 숫자 구하기 (Recursive인지는 모르겠네)
= Find Child : 이름으로 자식 오브젝트 찾기 & 변수에 저장변수는 따로 준비하는 것
= Wait : 대기시키는 액션
= Set Int Value : 정수 입력
= Int Add : Int 타입 변수변수는 따로 준비하는 것에 숫자를 더한다. 정수대 정수 연산은 다른 액션을 사용한다.
= Int Compare : 정수 2개 (값 또는 변수) 비교하고, 결과 값에 따라 같다, 작다, 크다 이벤트 발생
= Convert Int To String : 숫자(int)를 문자열로 변경
= Build String : 문자열을 조립한다.
= Move Towards : 특정 위치로 이동. 중간에 멈출 수 잇는지 아닌지 모름
===== PlayMaker FSM 추가 =====
게임 오브젝트 **MovingObject**에 새로운 FSM 추가.
(PlayMaker 태그가 붙어 있는 스샷 추가)
===== 'Init' State 추가 =====
==== 목표 ====
* 이동할 위치 정보를 얻는다.
* 위치 정보 오브젝트를 가리킬 인덱스를 준비해 놓는다.
==== 작업 preview ====
=== 추가할 변수 ===
^ Name ^ Type ^ Desc ^
| PathObjectCount | Int | Path 위치 역할을 하는 오브젝트의 최대 개수 |
| PathObjectIndex | Int | 여러 패스 중에 몇번째 패스 오브젝트 위치를 참조할 것인가? |
=== 사용할 액션 ===
* Set Int Value
* Get Child Count
==== 변수 추가 ====
**Variables** 탭을 눌러서 앞으로 사용할 변수를 추가
{{:language:unity:4-playmaker:pmexam1_fm_var_1.png|}}
= PathObjectIndex : **MovingObject \ Position**의 Child 오브젝트 개수를 구한다.
= : 이동할 위치 정보를 갖고 있는 GameObject의 개수를 구한다.
= PathObjectCount : 이동 위치 정보 GameObject의 인덱스를 저장할 변수를 추가하고 초기화
==== FSM에 'Init' State 추가 ====
|< 100% 40% - >|
| {{:language:unity:4-playmaker:pmexam1_fm_init.png|}} | 초기 State **Init**를 추가 |
**Init** 상태State에 액션 추가
| < 100% 40% - > | |
| {{:language:unity:4-playmaker:pmexam1_fm_init_1.png|}} | PathObjectIndex \\ **Set Int Value** 액션 |
| {{:language:unity:4-playmaker:pmexam1_fm_init_2.png|}} | PathObjectCount \\ **Get Child Count** 액션 |
| \\ **Get Child Count** 액션에서 GameObject에 **Position** 오브젝트를 할당. \\ ||
* **Init** State가 되면, 이번에 추가된 액션이 위->아래 순서로 실행 되면서 필요한 값을 저장.
* 플레이어를 실행 하면, 값이 저장되는 것을 확인 가능
===== 'First React' 추가 =====
==== 목표 ====
- 처음 시작 위치로 이동할 것인지
- 바로 이동할 위치 정보를 설정해서 이동할 것인지
If문 역할 하는 State를 추가하는 것을 봅니다.
==== 작업 preview ====
=== 추가할 변수 ===
^ Name ^ Type ^ Desc ^
| useEnteringMotion | Bool | 최초 '특정 위치'로 이동한 다음 Fixed경로이동을 시작할 것인지? |
=== 추가할 이벤트(Event) ===
* First Positioning
* Goto NextReact
FINISHED는 내장 이벤트. 현재 State가 종료되때를 가리킨다.
=== 사용할 액션 ===
* Bool Test
=== 추가할 State ===
|< 100% - >|
^ **Bool Test** 액션 결과 값에 따라, 이동할 State를 준비한다. ^
* MoveToFirstPosition
* Next React
테스트
==== State, Event 추가 ====
{{:language:unity:playmaker:pmexam1_fm_firstreact_3.png|}}
- **First React**라는 State 추가.
- **Init** State에 **FINISHED** 트랜지션을 추가
- **FINISHED** 트랜지션을 **First React** State로 연결 : 마우스를 **FINISHED** 에서 **First React** 로 클릭&드래깅!!
----
{{:language:unity:playmaker:pmexam1_fm_firstreact_1.png|}}
목표 1,2 중에 어떤 것을 선택할 것인지 확인할 bool 변수 추가.
* true : 목표1 실행
* false : 목표2 실행
----
{{:language:unity:playmaker:pmexam1_fm_firstreact_2.png|}}
true, false 일때 보낼 이벤트를 추가.
* true : **First Positioning** 이벤트 사용
* false : **Goto NextReact** 이벤트 사용
----
**First Positioning**, **Goto NextReact** \\ : 이벤트가 설정 되었을때, 액션의 결과 조건으로 이벤트가 선택 되는 경우 이동할 새로운 State를 추가한다.
* MoveToFirstPosition : **First Positioning** 이벤트면 이 State로 이동
* NextReact : **Goto NextReact** 이벤트면 이 State로 이동
{{:language:unity:playmaker:pmexam1_fm_firstreact_4.png|}}
===== 다시정리 =====
- StateA를 만든다.
- StateA에서 액션을 추가해서, 로직을 실행한다.
* 이때, 변수를 사용할 필요가 있으니 필요한변수를 추가한다.
- StateA에서 액션 실행 중 또는 완료시, 다른 State로 변경 되어야 한다면
* 이벤트를 추가한다. (추가하거나, 기존 것을 사용하거나)
* State 변경 여부는 액션의 결과(변수 값 변경 후, 검사해서 State 변경 필요 여부를 알아낸다.)
- StateB 와 같이 변경될(이동할 State를 추가한다.)
- 잘 써먹는다
==== First React 로직 추가 ====
FSM에서 **Init** State를 선택하고 **State** 탭에 액션 추가
|< 100% - >|
^ Bool 테스트 액션 추가 ^
| {{:language:unity:playmaker:pmexam1_fm_firstreact_5.png|}} |
* IsTrue, IsFalse 옵션에 맞는 상태 설정
* 각 이벤트가 어떤 State로 변경Transition되는지 설정되지 않아서 경고가 뜬 상태.
|< 100% - >|
^ 상태변경(Transition)메뉴에서 각 이벤트를 추가 ^
| {{:language:unity:playmaker:pmexam1_fm_firstreact_6.png|}} |
이 이벤트면 상태변경이 발생된다, 라는 뜻.
|< 100% - >|
^ 각 이벤트에서 새로운 State를 연결 ^
| {{:language:unity:playmaker:pmexam1_fm_firstreact_7.png|}} |
**useEnteringMotion** 변수 값에 의해,
* True면 **MoveToFirstPosition** State로 이동
* False면 **Next React** State로 이동
Variables 탭에서 "useEnteringMotion" 변수 값을 변경해서 맞는 State로 이동하는지 확인.
===== 이동 경로 State 처리 =====
====목표====
- 다음에 이동할 위치 정보를 얻어서 이동
- **Position** 게임 오브젝트의 Child 오브젝트를 순서대로 돌아가며 이동.
- 목표 지점까지 이동한 다음, 잠깐 대기
- 다시 1번으로 돌아가서 반복
====추가할 부분====
- 특정 오브젝트를 이름으로 찾기
- 찾아낼 오브젝트의 이름String을 조합
- 오브젝트를 이동시킨다
- 잠시 대기
====FSM 로직 상태 정리 (간단히)====
1. 'Next React'새로 추가 에서,
* 지금은 다른 조건이 없으므로 바로 이동할 위치를 찾는 FSM으로 이동
2. 'Setup Next Position'새로 추가 에서
^ 목적 ^ 실제로 할 것 ^
| **Position**의 child 오브젝트를 찾기 위한 \\ **스트링을 조합** | **PathObjectIndex** 변수를 사용해서 찾아낼 오브젝트 이름 만들기 |
| 오브젝트를 찾은 다음, 저장해 놓기 | **savedNextMovingPosition** 변수 추가해서 여기에 저장 |
| **PathObjectIndex** 변수 값 증가 | **PathObjectCount**보다 크면 다시 1로 설정 |
3. 'MoveTo'새로 추가 State
* 목표 지점으로 이동
* 완료되면 'Wait' State로 전환
* 'Wait' State 추가
4. 'Wait'새로 추가 State
* 잠시 대기
* **Next React** State로 이동
===== 'Next React' State 처리 =====
지금은 하는 일이 없기 때문에, **Setup Next Position**으로 바로 이동.
===== 'Setup Next Position' State 처리 =====
==== 1단계 : 스트링 변경 작업 ====
이 액션을 추가
* Convert Int To String
* Build String
^ 실행순서 (**위 -> 아래**) : Convert Int to String -> Build String ^
| {{:language:unity:playmaker:pmexam1_findnextpos_3.png|}} |
==== Convert Int To String & Build String ====
^ 실행 중에, 값이 반영 되어 있는 모습 ^
| {{:language:unity:playmaker:pmexam1_findnextpos_7.png|}} |
* **Int Variable** 에 **PathObjectIndex** 선택
* **String Variable** 선택할 수 있는 것이 없으니 새 String 변수 추가
* **nextPathObjName** 라고 이름 짓고.
결과 : **PathObjectIndex** 숫자 값이, **nextPathObjName** 스트링으로 변경.
뭐... 코드를 안쓰려고 하다보니 이런 짓도 해야 함.
==== 2단계 : 위치 정보 저장 ====
이 액션을 추가
* Find Child
^ 위에서 만들어둔 오브젝트 이름으로 Child 를 찾아서, **savedNextMovingPosition**에 저장한다. ^
| {{:language:unity:playmaker:pmexam1_findnextpos_8.png|}} |
===== 이동,대기 =====
목표
* 이전 단계에서 찾아놓은 오브젝트(이동할 위치)로 이동한다.
* 이동이 끝나면 잠시 대기
간단한 부분이므로 퀵 정리
===== 'MoveTo' State 처리 =====
==== State 추가 ====
* **MoveTo** State 추가
* 이 State에 **FINISHED** Transition을 추가해 놓는다.
* 빨간 딱지는 우선 무시해도 된다. \\ {{:language:unity:playmaker:pmexam1_findnextpos_moveto_1.png|}}
==== 액션 추가 ====
* **Move Towards** 액션추가 \\ {{:language:unity:playmaker:pmexam1_findnextpos_moveto_2.png|}}
* 이전 단계에서 찾아 놓은 위치 정보 오브젝트를 **Target Object**로 설정
* 딱 그 위치까지 움직이게 할 것이므로, **Finish Distance**를 **0.1**으로 설정.0으로 설정했을때 제대로 움직이는 것 확인 후에, 0으로 수정 하면 된다. 0.1로 정하면 동작은 보장 되니까.
* **Max Speed**는 뭐 임의대로
==== State 간 연결(Transition) ====
^ **Setup Next Position**-FINISHED -> **MoveTo** 로 연결 ^
| {{:language:unity:playmaker:pmexam1_findnextpos_moveto_3.png|}} |
대충 메모 하고, 은근 슬쩍
* **MoveTo/FINISHED**에서 **Wait** 상태로 연결한다.
실행 후 에러가 없다면 성공.
위치 오브젝트에 대한 변경이 없어서, 제자리에 가만 있는 것 같지만..
==== 'Wait' State 처리 ====
{{:language:unity:playmaker:pmexam1_findnextpos_wait_1.png|}}
* 이 State에 **FINISHED** Transition 추가
* State가 끝나도 이동하는 곳이 없기 때문에 빨간 마크가 있지만, 지금은 무시.
{{:language:unity:playmaker:pmexam1_findnextpos_wait_2.png|}}
* **Wait** 액션 추가
* 2초 대기 후, **Finish Event**에 **FINISHED** 항목선택
2초 대기 후, FINISHED 이벤트에서 **Next React** State로 이동(한다)
===== 새로 필요한 것 =====
지금 실행 해보면 동작 하지만에러나면 에러.. 한자리에 가만 있는다. **위치 오브젝트를 변경한 적이 없기 때문에** 당연한 현상.
* **이동할 위치 정보**는 **savedNextMovingPosition**이 갖고 있어야 한다.
* 현재는 **1_MovPath** 오브젝트만 저장하고 있기 때문에 다른 오브젝트를 찾아서 넣어 줘야 한다.
==== 앞으로 할 것 ====
**Setup Next Position**에서
* **PathObjectIndex** 숫자 값과 "_MovPath"를 조합해서 위치 정보를 갖고 있는 Child 오브젝트를 찾는다.
* **PathObjectIndex** 값을 증가시켜서 (1,2,3.. 이런 순서) 다음 오브젝트를 찾게 한다.
==== 새로 추가할 State ====
* **%%++NextObject Index%%** : PathObjectIndex 값을 1 증가 시킨다.
* **Reset NextObject Index** : PathObjectIndex 값이 **Position** 오브젝트의 Child 개수보다 크면 (PathObjectIndex > PathObjectCount) \\ PathObjectIndex를 1로 리셋한다. 첫번째 Child 오브젝트로 이동
===== '++NextObject Index' State =====
별로 복잡하지 않아서 퀵 설명.
- **Int Add** 액션을 추가해서 **PathObjectIndex**에 1을 더한다. (1이면 2가 되겠지)
- **Int Compare**를 추가해서 (PathObjectIndex > PathObjectCount) 요런 상태인지 확인한다.
* 맞다면, **Need PathObjIndex** 이벤트이 이벤트 추가 필요를 쏜다.
| {{:language:unity:playmaker:pmexam1_intindex_add_1.png|}} |
| {{:language:unity:playmaker:pmexam1_intindex_add_2.png|}} |
===== 추가 State 필요한 타이밍 =====
요 경우가 **왜 State를, 언제 분리하는게 좋은가** 알려줌
* 현재 State에서 PathObjectIndex를 리셋할 수 없기 때문에, 숫자 리셋을 위한 별도 State를 추가한다.
* State 내의 액션은 위->아래로 순서대로 실행된다.
* 액션 일부분만 실행 되도록 할 수 없기 때문에,한 State에서 특정 액션만 실행 시키려면 더 많은 검사를 해서 각 액션들이 수행 될 것인지 판단하게 구성 해야 한다 이때 State를 분리하는 것.
Event를 잘 활용하면 되긴 되지만, 복잡해질 것 같은데.
숫자를 리셋하는 타이밍을 찾는 조건 또한 다른 방법을 취할 수 있다.
Find Child 결과가 null인지 확인한다든지. null이면 숫자를 리셋하는거지.
===== 'Reset NextObject Index' State =====
^ State를 추가한다. ^
| {{:language:unity:playmaker:pmexam1_intindex_add_3.png|}} |
^ 단순히 **PathObjectIndex**를 1로 초기화 한다. ^
| {{:language:unity:playmaker:pmexam1_intindex_add_4.png|}} |
==== State 연결 ====
| {{:language:unity:playmaker:pmexam1_intindex_add_4.png|}} |
* **Setup Next Position**이 끝나면FINISHED \\ "MoveTo" 대신 \\ **%%++NextObjectIndex%%**로 이동한다.
* **%%++NextObjectIndex%%**에서 숫자 비교 후, **PathObjectIndex가 리셋될 필요**가 있으면 **Need PathObj Index**이름 잘못 지었네 이벤트를 쏜다. (화면 상에서는 선택하는 거지만)
* **Need PathObj Index** 에서 **Reset NextObject Index** State로 이동 (연결)한다. 숫자가 리셋되겠지.
이 두 State 모두,
* 종료FINISHED된 경우 **MoveTo**로 이동
===== 중간 확인 =====
실행 실행 실행
지금까지 된 부분으로, 오브젝트가 Position의 Child 오브젝트들을 따라 움직여야 한다!
====== 2차 : 남은 부분 ======
* **MoveToFirstPosition** State 처리
* 각 움직이는 지점에 도착했을때, 다음 이동할 좌표를 아래 처럼 선택한다.
* 랜덤하게 선택해서 이동한다.
* 1차 부분대로 순서대로 따라 간다.
귀찮은데 종료할까.. 생각보다 굉장히 긴데.
===== 'MoveToFirstPosition' State 처리 =====
여긴 나중에 정리
* **First React** State에서 초기 위치 이동에 대한 변수값이 true인 경우, 이 상태로 이동.