> For the complete documentation index, see [llms.txt](https://ditoland-utplus.gitbook.io/ditoland/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ditoland-utplus.gitbook.io/ditoland/manual/ai-fsm.md).

# AI FSM

NPC나 오브젝트에 AI 상태를 설정하는 기능이에요.

<figure><img src="https://1068493773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lxtl0ocR1cA2G25jLXa%2Fuploads%2Fb0ckh7nGOJbJRrOtT6Ez%2F1.gif?alt=media&amp;token=3d9cc488-196c-43c4-b597-f18cfd4e1611" alt=""><figcaption></figcaption></figure>

샘플맵 바로가기🔗

{% content-ref url="/pages/-MVtfYoN7zHoqLwn7vIV" %}
[Scripting](/ditoland/sample/scripting.md)
{% endcontent-ref %}

### Finite State Machine

오브젝트에 상태 머신🤖을 설정🔧하여 조건에 따른 상태 전환 기능을 제공해요.&#x20;

<figure><img src="https://1068493773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lxtl0ocR1cA2G25jLXa%2Fuploads%2F0YBdufiLDLGTNWlVGzix%2F2.png?alt=media&amp;token=1d3543d4-5c36-49b8-8e46-9a00887a06d1" alt=""><figcaption></figcaption></figure>

#### FinteState

객체의 각 상태를 나타내요.🧍🏃🧘

#### ParallelState

FinteState의 하위 상태에요.⛹️

ParallelState를 설정하면 FinteState와 함께 실행돼요.

FiniteState 하위에는 하나☝️의 ParallelState만 생성할 수 있어요.

하나의 FiniteState에 2개 이상의 ParallelState를 설정하면 마지막에 설정한 ParallelState만 적용돼요.⏭️

####

#### FSM의 상태 플로우(동작 순서)

각 상태🏃마다 EnterEvent > UpdateEvent > ExitEvent 순으로 진행돼요.

💡하위 상태(ParallelState)가 존재하는 경우, \
상위 EnterEvent > 하위 EntetEvent > 상위 UpdateEvent… 순서로 진행돼요.

<figure><img src="https://1068493773-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lxtl0ocR1cA2G25jLXa%2Fuploads%2Fc271uRQMQdJW9pGVq8WB%2F3.png?alt=media&amp;token=f5225082-60f0-4da0-accb-0d42e2b2f75e" alt=""><figcaption></figcaption></figure>

#### FSM 사용 함수

<table><thead><tr><th width="220.33333333333331">함수</th><th width="168">사용가능 스크립트</th><th>설명</th></tr></thead><tbody><tr><td>void AddFSM()</td><td>Server / Client</td><td>대상에게 FSM를 부여해요.</td></tr><tr><td>void AddFiniteState<br>(string StateName)</td><td>Server / Client</td><td>FSM 내부에 상태 추가해요.</td></tr><tr><td>void AddParallelState<br>(string StateName)</td><td>Server / Client</td><td>FSM 추가된 상태에 하위 상태를 추가해요.<br>각 상태마다 하나씩만 추가할 수 있어요.</td></tr><tr><td>EnterEvent</td><td>Server / Client</td><td>상태가 <strong>시작될 때</strong> 호출되는 이벤트에요.</td></tr><tr><td>UpdateEvent</td><td>Server / Client</td><td>상태가 <strong>진행중일 때</strong> 호출되는 이벤트에요.</td></tr><tr><td>ExitEvent</td><td>Server / Client</td><td>상태가 <strong>끝날 때</strong> 호출되는 이벤트에요.</td></tr><tr><td>void AddTransition<br>(string StateName, <br>string StateName, <br>function, <br>number)</td><td>Server / Client</td><td>다른 상태로 전환할 때 사용하는 함수에요.<br>시작 상태 이름, 전이할 상태 이름, 연결 함수, 우선순위(0에 가까울수록 높아요.)가 <br>필요해요.</td></tr><tr><td>void StartFSM()</td><td>Server/Client</td><td>FSM를 활성화 해요.</td></tr><tr><td>void StopFSM()</td><td>Server/Client</td><td>FSM를 비활성화 해요.</td></tr><tr><td>void GetOrCreateFSM<br>(string StateName)</td><td>Client</td><td>FSM을 생성하거나 Server에 있는 FSM을 <br>불러와요.</td></tr></tbody></table>

####

#### Server에서 FSM 사용 예

```lua
local NPC = Script.Parent

local FSM = Game:AddFSM("FSM") --FSM 추가해요.

---------------------------------------------------------------------
--FSM 상태 추가
local IdleState = FSM:AddFiniteState("Idle")
local MoveState = FSM:AddFiniteState("Move")

--Move의 하위 상태 추가
local JumpState = MoveState:AddParallelState("Jump")

FSM:AddReplicateValue("Timer", 0, Enum.ReplicateType.Changed, 0)

---------------------------------------------------------------------
--각 상태마다 EnterEvent -> UpdateEvent -> ExitEvent 순서로 진행
--Idle 상태
local function EnterIdle(fsm)
    print("GetCurrentState", fsm.CurrentFiniteState) --현재 상태 반환
end
IdleState.EnterEvent:Connect(EnterIdle)

local function UpdateIdle(fsm, updateTime)
    fsm.Timer = fsm.Timer + updateTime
end
IdleState.UpdateEvent:Connect(UpdateIdle)

local function ExitIdle(fsm)

end
IdleState.ExitEvent:Connect(ExitIdle)

---------------------------------------------------------------------
--Move 상태
local function EnterMove(fsm)
    print("GetCurrentState", fsm.CurrentFiniteState) --현재 상태 반환
end
MoveState.EnterEvent:Connect(EnterMove)

local function UpdateMove(fsm, updateTime)
    fsm.Timer = fsm.Timer - updateTime
end
MoveState.UpdateEvent:Connect(UpdateMove)

local function ExitMove(fsm)

end
MoveState.ExitEvent:Connect(ExitMove)

---------------------------------------------------------------------
--하위 상태도 동일하게
--Jump상태
local function EnterJump(fsm)
    print("GetCurrentState", fsm.CurrentFiniteState, " ", JumpState) --현재 상태 반환
    
    NPC:Jump()
end
JumpState.EnterEvent:Connect(EnterJump)

local function UpdateJump(fsm, updateTime)

end
JumpState.UpdateEvent:Connect(UpdateJump)

local function ExitJump(fsm)

end
JumpState.ExitEvent:Connect(ExitJump)

---------------------------------------------------------------------
local function ToMoveCondition(fsm)
   if fsm.Timer >= 1.5 then  return true
   else                      return false   end
end

local function ToStandCondition(fsm)
   if fsm.Timer <= 0 then    return true
   else                      return false   end
end

---------------------------------------------------------------------
--두 상태간 전이 조건 연결하는 함수에요.
--인자로 시작 상태 이름, 전이할 상태 이름, 연결 함수, 우선순위 (0에 가까울수록 높아요.)가 필요해요.
FSM:AddTransition("Idle", "Move", ToMoveCondition, 0)
FSM:AddTransition("Move", "Idle", ToStandCondition, 0)
---------------------------------------------------------------------

FSM.StartFiniteState = "Idle"      --시작 상태를 설정해요.
NPC.FSM = FSM                      --NPC에게 FSM를 할당해요.
NPC:StartFSM()                     --FSM 활성화시켜요.
NPC:StopFSM()                      --FSM 종료할 수 있는 함수에요.
```

####

#### Client에서 FSM 사용 예

```lua
local NPC = Script.Parent

local FSM = Game:GetOrCreateFSM("FSM", NPC:GetKey()) --Server에 있는 FSM를 가져와요.

---------------------------------------------------------------------
--FSM 상태 추가
local IdleState = FSM:AddFiniteState("Idle")
local MoveState = FSM:AddFiniteState("Move")

--FSM 하위 상태 추가
local JumpState = MoveState:AddParallelState("Jump")

---------------------------------------------------------------------
--Idle 상태
local function EnterIdle(fsm)   
   NPC.SurfaceUI.Text:SetText("Idle: Idle")
end
IdleState.EnterEvent:Connect(EnterStand)

---------------------------------------------------------------------
--Move 상태
local function EnterMove(fsm)    
    NPC.SurfaceUI.Text:SetText("State : Move")
end
MoveState.EnterEvent:Connect(EnterMove)

---------------------------------------------------------------------
--Move의 하위 상태
local function EnterJump(fsm)
    NPC.SurfaceUI.Text:SetText("State : Move (Jump)")
end
JumpState.EnterEvent:Connect(EnterJump)

---------------------------------------------------------------------
FSM.StartFiniteState = "Idle"      --시작 상태를 설정해요.
NPC.FSM = FSM                      --NPC에게 FSM를 설정해요.
NPC:StartFSM()                     --FSM 활성화시켜요.
NPC:StopFSM()                      --FSM 종료할 수 있는 함수에요.
```
