====== 목표 ====== 작성하려는 로직 ===== 로직 시나리오 ===== 임의 오브젝트에 대해서, 아래 과정을 반복한다. - 최초 위치로 이동 시킨다 * 판단 부분 추가 * 초기 위치로 이동시킬 것인가? * 현재 위치에서 바로 다른 움직임을 시작할 것인가? - 다음 이동 위치를 결정한다 * 다음 중 선택 - 정해진 루트를 순서대로 탐방하는 방식 - 정해진 루트 중에 한 곳을 임의 선택해서 이동 - 정해진 위치로 이동 - 도착하면 다른 오브젝트에 메시지를 전송 - 잠시 대기 - 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인 경우, 이 상태로 이동.