I am building an Enemy AI State Machine, Where I have these scripts.
Setup
- Enemy
- EnemyStateManager
- EnemyStateBase
States
- InitialState
- RoamingState
- PursuingState
- AttackingState
- RetreatingState
When I am inside of an enemy state, for example, let's say Pursuing State, where the enemy's role is to chase the target until its within attack range. I am not sure if I should be programming the decision-making process of the enemy inside the state, or have a separate script that will call actions on the current state, and the state relaying whether that action is possible within the state.
Currently, the EnemyStateManager is set up like this.
public class StateMachine : MonoBehaviour {
private EnemyStateBase _currentState;
private Enemy _enemy;
public Enemy Enemy { get => _enemy; set => _enemy = value; }
private void Start() {
_currentState = new RoamingState(this);
}
public void ChangeState(State newState) {
_currentState.ExitState();
_currentState = newState;
_currentState.EnterState();
}
public void Update(){
_currentState.UpdateState();
}
}
Example of Question
Below you see that I am in Pursuing State and checking to see on Update if I am within attack range. It feels weird to try to evaluate AI Logic inside the state, but if this seems like a common practice and follows coding guidelines then I guess I'm worried for nothing.
public class PursuingState : EnemyStateBase {
private EnemyStateManager _esm;
public PursuingState (EnemyStateManager esm){
_esm = esm;
}
public override void EnterState() {
// Do something when entering the pursuing state
}
public override void UpdateState() {
// Check To See If you Entered Attack Range with target
var targetPos = _esm.Enemy.Target.Transform.Position;
var myPos = _esm.Enemy.Transform.Position;
if(Vector3.Difference(mypos, targetpos) < _esm.Enemy.AttackRange){
_esm.ChangeState(new AttackState(_esm));
}
}
public override void ExitState() {
// Do something when exiting the pursuing state
}
Non-AI Situation
If I were to build a state machine that was from player input then the player is the decision maker, and the input is relayed to the state machine, and the state machine will respond with appropriate action based on my input.
Summary
The Enemy AI example seems like AI input comes from within the state itself, whereas in a traditional setup with player input, it comes from outside the state machines. Is the Enemy AI example seem like a typical example?
Yes, it is! Do you know about Design Patterns? They're commum designed solutions of commum problems that you find whe designing a software. This example shows the State Pattern, used to control the state of a class during runtime and create cohesive state machines.
Here is a link if you want to know more about it.