유니티 유한상태기계 - FSM(Finite State Machine)
유데미 강의듣고 정리중
기본 구조
Enemy 스크립트는 근거리 적, 원거리 적, 보스 등 다양하게 파생될수 있음.
그러므로 공통적인 모든것을 가지고 있어야함.
- 예를들어 Enemy_Melee(근접 몬스터)는 Enemy를 상속
Enemy 스크립트의 기본 틀 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Enemy : MonoBehaviour
{
public EnemyStateMachine enemyStateMachine { get; private set; }
protected virtual void Awake()
{
enemyStateMachine = new EnemyStateMachine();
}
protected virtual void Start()
{
}
protected virtual void Update()
{
}
}
Idle, Move(내비메쉬) 기능 등을 추가한 Enemy 스크립트 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Enemy : MonoBehaviour
{
[Header("Idle data")]
public float idleTime;
public float aggresionRange;
[Header("Move data")]
public float moveSpeed;
public Transform[] patrolPoints;
int currentPatrolIndex;
public Transform player { get; private set; }
public NavMeshAgent agent { get; private set; }
public EnemyStateMachine enemyStateMachine { get; private set; }
protected virtual void Awake()
{
enemyStateMachine = new EnemyStateMachine();
agent = GetComponent<NavMeshAgent>();
}
protected virtual void Start()
{
foreach (var p in patrolPoints)
{
p.parent = null;
}
}
protected virtual void Update()
{
}
public Vector3 GetPatrolDestination()
{
Vector3 destination = patrolPoints[currentPatrolIndex].transform.position;
currentPatrolIndex++;
if (currentPatrolIndex >= patrolPoints.Length)
currentPatrolIndex = 0;
return destination;
}
protected virtual void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, aggresionRange);
}
}
Enemy_Melee 스크립트 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Melee : Enemy
{
public IdleState_Melee idleState { get; private set; }
public MoveState_Melee moveState { get; private set; }
protected override void Awake()
{
base.Awake();
idleState = new IdleState_Melee(this, enemyStateMachine, "Idle");
moveState = new MoveState_Melee(this, enemyStateMachine, "Move");
}
protected override void Start()
{
base.Start();
enemyStateMachine.Initialize(idleState);
}
protected override void Update()
{
base.Update();
enemyStateMachine.currentState.Update();
}
}
EnemyState 스크립트 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyState
{
protected Enemy enemyBase;
protected EnemyStateMachine enemyStateMachine;
protected string animBoolName;
public EnemyState(Enemy enemyBase, EnemyStateMachine enemyStateMachine, string animBoolName)
{
this.enemyBase = enemyBase;
this.enemyStateMachine = enemyStateMachine;
this.animBoolName = animBoolName;
}
public virtual void Enter()
{
}
public virtual void Update()
{
}
public virtual void Exit()
{
}
}
EnemyStateMachine 스크립트 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyStateMachine
{
public EnemyState currentState { get; private set; }
// 첫번째 상태를 초기화함
public void Initialize(EnemyState startState)
{
currentState = startState;
currentState.Enter();
}
// 이전상태를 종료하고 바로 다른 상태로 전환
public void ChangeState(EnemyState newState)
{
Debug.Log($"Changing state from {currentState} to {newState}");
currentState.Exit(); // 이전 상태를 종료하고
currentState = newState; // 새로운 상태를 가져와서
currentState.Enter(); // 새로운 상태로 들어감
}
}
IdleState_Melee 스크립트 :
- 타이머를 추가해서 지정한 시간이 지나면 다른 상태로 전환
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IdleState_Melee : EnemyState
{
private Enemy_Melee enemy;
public IdleState_Melee(Enemy enemyBase, EnemyStateMachine enemyStateMachine, string animBoolName) : base(enemyBase, enemyStateMachine, animBoolName)
{
// Enemy_Melee에 있는 다른 상태로 접근 및 전환하기 위해 선언.
// ex) enemyStateMachine.ChangeState(enemy.moveState);
enemy = enemyBase as Enemy_Melee;
}
public override void Enter()
{
base.Enter();
stateTimer = enemyBase.idleTime;
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if(stateTimer < 0)
{
enemyStateMachine.ChangeState(enemy.moveState);
}
}
}
유니티 오브젝트 풀링 기초 (0) | 2025.01.28 |
---|---|
유니티 내위치에서 타겟으로 Y축 회전하기 (0) | 2025.01.25 |
유니티 스킬 쿨타임 (0) | 2025.01.20 |
유니티 몬스터가 캐릭터한테 점프해서 도달하기 (0) | 2025.01.20 |
유니티 Vector3.Distance() 거리구하기, 방향벡터 구하기 (0) | 2025.01.20 |