Added how to make a Finite state machine

This commit is contained in:
Chloe 2024-10-25 07:58:48 -04:00
parent 691fe3e36b
commit 69c42be7dd
3 changed files with 121 additions and 31 deletions

View File

@ -4,39 +4,20 @@
"type": "split", "type": "split",
"children": [ "children": [
{ {
"id": "6b652dc38b9873a1", "id": "9f8b5d21e348d59f",
"type": "tabs", "type": "tabs",
"children": [ "children": [
{ {
"id": "eca0df4907039a3d", "id": "973dac369b06c184",
"type": "leaf", "type": "leaf",
"state": { "state": {
"type": "markdown", "type": "empty",
"state": { "state": {},
"file": "Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
"mode": "source",
"source": false
},
"icon": "lucide-file", "icon": "lucide-file",
"title": "Enemy AI - Unity NavMesh (tutorial)" "title": "New tab"
}
},
{
"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)"
} }
} }
], ]
"currentTab": 1
} }
], ],
"direction": "vertical" "direction": "vertical"
@ -184,23 +165,23 @@
"daily-notes:Open today's daily note": false, "daily-notes:Open today's daily note": false,
"templates:Insert template": false, "templates:Insert template": false,
"command-palette:Open command palette": false, "command-palette:Open command palette": false,
"obsidian-git:Open Git source control": false, "obsidian-git:Open Git source control": false
"copilot:Copilot Chat": false
} }
}, },
"active": "be6bc070960af330", "active": "973dac369b06c184",
"lastOpenFiles": [ "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/UnityEngine.AI/Classes/NavMesh.md",
"Scripting/Classes/Physics/Raycast.md", "Scripting/Classes/Physics/Raycast.md",
"Scripting/Classes/Physics", "Scripting/Classes/Physics",
"Scripting/Classes", "Scripting/Classes",
"copilot-conversations/Robot_can_you_search_the_web@20241023_164312.md", "copilot-conversations/Robot_can_you_search_the_web@20241023_164312.md",
"copilot-conversations", "copilot-conversations",
"Tutorials/Enemy AI - Unity NavMesh (tutorial).md",
"Scripting/UnityEngine.AI/Classes", "Scripting/UnityEngine.AI/Classes",
"Scripting/UnityEngine.AI", "Scripting/UnityEngine.AI",
"Scripting", "Scripting",
"Tutorials/README.md",
"README.md", "README.md",
"LICENSE", "LICENSE",
"Unity-Notes/README.md", "Unity-Notes/README.md",

View File

@ -22,7 +22,7 @@ using UnityEngine.AI;
public class EnemyMovement : MonoBehaviour public class EnemyMovement : MonoBehaviour
{ {
public transform target; public Transform target;
private NavMesh agent; private NavMesh agent;
// Remember: Start runs **AT THE START OF THE GAME** and only once. // Remember: Start runs **AT THE START OF THE GAME** and only once.

View 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.