Added how to make a Finite state machine
This commit is contained in:
parent
691fe3e36b
commit
69c42be7dd
41
.obsidian/workspace.json
vendored
41
.obsidian/workspace.json
vendored
@ -4,39 +4,20 @@
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "6b652dc38b9873a1",
|
||||
"id": "9f8b5d21e348d59f",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "eca0df4907039a3d",
|
||||
"id": "973dac369b06c184",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"type": "empty",
|
||||
"state": {},
|
||||
"icon": "lucide-file",
|
||||
"title": "Enemy AI - Unity NavMesh (tutorial)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "be6bc070960af330",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Enemy AI - Unity NavMesh (tutorial)"
|
||||
"title": "New tab"
|
||||
}
|
||||
}
|
||||
],
|
||||
"currentTab": 1
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
@ -184,23 +165,23 @@
|
||||
"daily-notes:Open today's daily note": false,
|
||||
"templates:Insert template": false,
|
||||
"command-palette:Open command palette": false,
|
||||
"obsidian-git:Open Git source control": false,
|
||||
"copilot:Copilot Chat": false
|
||||
"obsidian-git:Open Git source control": false
|
||||
}
|
||||
},
|
||||
"active": "be6bc070960af330",
|
||||
"active": "973dac369b06c184",
|
||||
"lastOpenFiles": [
|
||||
"Tutorials/How to make a Finite State Machine (FSM).md",
|
||||
"Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
|
||||
"Tutorials/README.md",
|
||||
"Scripting/UnityEngine.AI/Classes/NavMesh.md",
|
||||
"Scripting/Classes/Physics/Raycast.md",
|
||||
"Scripting/Classes/Physics",
|
||||
"Scripting/Classes",
|
||||
"copilot-conversations/Robot_can_you_search_the_web@20241023_164312.md",
|
||||
"copilot-conversations",
|
||||
"Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
|
||||
"Scripting/UnityEngine.AI/Classes",
|
||||
"Scripting/UnityEngine.AI",
|
||||
"Scripting",
|
||||
"Tutorials/README.md",
|
||||
"README.md",
|
||||
"LICENSE",
|
||||
"Unity-Notes/README.md",
|
||||
|
@ -22,7 +22,7 @@ using UnityEngine.AI;
|
||||
|
||||
public class EnemyMovement : MonoBehaviour
|
||||
{
|
||||
public transform target;
|
||||
public Transform target;
|
||||
private NavMesh agent;
|
||||
|
||||
// Remember: Start runs **AT THE START OF THE GAME** and only once.
|
||||
|
109
Tutorials/How to make a Finite State Machine (FSM).md
Normal file
109
Tutorials/How to make a Finite State Machine (FSM).md
Normal file
@ -0,0 +1,109 @@
|
||||
This is a tutorial i didn't know I needed, so here we go:
|
||||
|
||||
## Create the State Interface
|
||||
When using state interfaces, it's essentially a "Manager" it holds sub classes within, and it helps you manage the states of your characters.
|
||||
|
||||
Here is an example of a State Interface. When writing this code to your project, it should be outside of the main class, it will be it's own class.
|
||||
|
||||
```csharp
|
||||
public interface IState
|
||||
{
|
||||
void Enter(); // Called when entering the state
|
||||
void Exit(); // Called when exiting the state
|
||||
void Update(); // Called every frame while in the state
|
||||
}
|
||||
```
|
||||
### What are we doing in this code sample
|
||||
1. We are defining three methods that the class will essentially automatically run, assuming it implements the `IState` interface.
|
||||
## Create the States
|
||||
You can now create the "State" itself, In this case, our state will be "Idle" which means it will **not have any goals** it'll just be sitting there.
|
||||
|
||||
```csharp
|
||||
public class IdleState : IState
|
||||
{
|
||||
public void Enter()
|
||||
{
|
||||
Debug.Log("Entering Idle State");
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
Debug.Log("Exiting Idle State");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
Debug.Log("Updating Idle State");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### What does this code do?
|
||||
This code is doing the same as the other code snippet, but it is defined for a specific state. **Each state must include three methods: `Enter()`, `Exit()`, `Update()`.**
|
||||
|
||||
**Remember:** The code is not meant to go within your main class, in fact, **It could even be added to it's own script** if you so pleased.
|
||||
|
||||
## The final result
|
||||
|
||||
```csharp
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
private StateMachine _stateMachine;
|
||||
private IdleState _idleState;
|
||||
private PatrolState _patrolState;
|
||||
private ChaseState _chaseState;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_stateMachine = new StateMachine();
|
||||
|
||||
// Initialize the states
|
||||
_idleState = new IdleState();
|
||||
_patrolState = new PatrolState();
|
||||
_chaseState = new ChaseState();
|
||||
|
||||
// Start with the Idle state
|
||||
_stateMachine.ChangeState(_idleState);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Call the State Machine's Update method
|
||||
_stateMachine.Update();
|
||||
|
||||
// Example of switching between states for demonstration purposes
|
||||
if (Input.GetKeyDown(KeyCode.I))
|
||||
{
|
||||
_stateMachine.ChangeState(_idleState);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.P))
|
||||
{
|
||||
_stateMachine.ChangeState(_patrolState);
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.C))
|
||||
{
|
||||
_stateMachine.ChangeState(_chaseState);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### What does this code do?
|
||||
The code does the following:
|
||||
1. Defines a StateMachine as `_stateMachine;` which will be handling our state transitions.
|
||||
2. Defines an IdleState, PatrolState, and ChaseState as `_idleState;`, `_patrolState;`, `_chaseState;` respectively, which are our classes, remember?
|
||||
3. In the start method, it
|
||||
1. Creates a new `StateMachine();` on `_stateMachine`
|
||||
2. Creates new individual states (I like to say this is essentially "Making the state available" to the StateMachine.)
|
||||
3. Then changes the state to idle
|
||||
4. In the update method, it
|
||||
1. Runs the "Update" method on the state machine (Which means it will run the state functionality)
|
||||
2. Based on the keyboard input, **it switches the state for testing purposes.** You are free to change this.
|
||||
|
||||
## Attach it to a GameObject
|
||||
Now that the script is done, you can add your script to your enemy game object. **Make sure it has a Nav Mesh Agent!**
|
||||
|
||||
## That's it!
|
||||
Thanks for reading! Forgive me if I am wrong about some details, this is a learning exercise for me too.
|
Loading…
Reference in New Issue
Block a user