Skip to content

Commit 1c48151

Browse files
committed
Merge branch 'feature/docs' into develop
2 parents 9c3ae6f + 21641ae commit 1c48151

File tree

1 file changed

+305
-0
lines changed

1 file changed

+305
-0
lines changed

README.md

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
# Fluid State Machine
2+
3+
Fluid State Machine is a Unity plugin aimed at creating state machines in pure code. It allows state actions to be re-used and customized on a per-project basis.
4+
5+
* Extendable, write your own re-usable state actions
6+
* Heavily tested with TDD
7+
* Open source and free
8+
9+
Get the [latest release](https://github.com/ashblue/fluid-state-machine/releases).
10+
11+
## Getting Started
12+
13+
State machines are formatted as so. For example here we have a door that demonstrates a simple open and close mechanism.
14+
15+
```c#
16+
using UnityEngine;
17+
using CleverCrow.FluidStateMachine;
18+
19+
public class Door : MonoBehaviour {
20+
private IFsm _door;
21+
public bool Open { private get; set; }
22+
23+
public enum DoorState {
24+
Opened,
25+
Closed,
26+
}
27+
28+
private void Start () {
29+
_door = new FsmBuilder()
30+
.Owner(gameObject)
31+
.Default(DoorState.Closed)
32+
.State(DoorState.Closed, (close) => {
33+
close.SetTransition("open", DoorState.Opened)
34+
.Update((action) => {
35+
if (Open) action.Transition("open");
36+
});
37+
})
38+
.State(DoorState.Opened, (open) => {
39+
open.SetTransition("close", DoorState.Closed)
40+
.Update((action) => {
41+
if (!Open) action.Transition("close");
42+
});
43+
})
44+
.Build();
45+
}
46+
47+
private void Update () {
48+
// Update the state machine every frame
49+
_door.Tick();
50+
}
51+
}
52+
```
53+
54+
### Examples
55+
56+
More complex usage examples can be found in `Assets/FluidStateMachine/Examples` you'll find multiple example projects and code snippets. If you plan on running any of the example scenes you'll want to read `Assets/FluidStateMachine/Examples/README.md` to add any missing dependencies.
57+
58+
### Releases
59+
60+
To get the latest build simply grab a copy from the [releases](https://github.com/ashblue/fluid-state-machine/releases) page. If you're using Node.js you can keep this package up to date by installing it with the following code via NPM. If you use the NPM package it's strongly recommended to exclude the built files `Assets/Plugins/FluidStateMachine` from version control.
61+
62+
CODE COMING SOON
63+
64+
## Table of Contents
65+
66+
* [Getting Started](#getting-started)
67+
+ [Examples](#examples)
68+
+ [Releases](#releases)
69+
* [Action Library](#action-library)
70+
+ [Defaults](#defaults)
71+
- [Enter](#enter)
72+
- [Exit](#exit)
73+
- [Update](#update)
74+
- [RunFsm](#runfsm)
75+
+ [Triggers](#triggers)
76+
- [Enter](#enter-1)
77+
- [Exit](#exit-1)
78+
- [Stay](#stay)
79+
+ [Animators](#animators)
80+
- [Set Animator Bool](#set-animator-bool)
81+
- [Set Animator Float](#set-animator-float)
82+
- [Set Animator Int](#set-animator-int)
83+
- [Set Animator Trigger](#set-animator-trigger)
84+
* [Creating Custom Actions](#creating-custom-actions)
85+
86+
## Action Library
87+
88+
Pre-made actions included in this library are as follows.
89+
90+
### Defaults
91+
92+
Actions targeted at hooking the default state machine lifecycle.
93+
94+
#### Enter
95+
96+
Triggers whenever a state is initially entered.
97+
98+
```c#
99+
.State(MyEnum.MyState, (state) => {
100+
state.Enter((action) => Debug.Log("Code goes here"));
101+
})
102+
```
103+
104+
#### Exit
105+
106+
Triggers whenever a state is exited.
107+
108+
```c#
109+
.State(MyEnum.MyState, (state) => {
110+
state.Exit((action) => Debug.Log("Code goes here"));
111+
})
112+
```
113+
114+
#### Update
115+
116+
Every frame a FSM's `Fsm.Tick()` method is called and the state is active this will run.
117+
118+
```c#
119+
.State(MyEnum.MyState, (state) => {
120+
state.Update((action) => Debug.Log("Code goes here"));
121+
})
122+
```
123+
124+
#### RunFsm
125+
126+
Used to run a nested FSM inside of a state. This action will continue running until the nested FSM triggers an Exit event through `Fsm.Exit()`. When exit is triggered the passed transition will automatically fire.
127+
128+
```c#
129+
var nestedFsm = new FsmBuilder()
130+
.Default(OtherStateId.A)
131+
.State(OtherStateId.A, (state) => {
132+
state.Enter((action) => Debug.Log("Nested FSM triggered"));
133+
// This will notify the fsm that triggered nestedFsm to stop running it
134+
state.Update((action) => action.ParentState.ParentFsm.Exit());
135+
})
136+
.Build();
137+
138+
var fsm = new FsmBuilder()
139+
.Default(StateId.A)
140+
.State(StateId.A, (state) => {
141+
state.SetTransition("next", StateId.B);
142+
// First argument is the transition triggered when `nestedFsm.Exit()` is detected
143+
state.RunFsm("next", nestedFsm);
144+
})
145+
.State(StateId.B, (state) => {
146+
state.Enter((action) => Debug.Log("Success"));
147+
})
148+
.Build();
149+
```
150+
151+
### Triggers
152+
153+
Hook's Unity's collider trigger system. Note that a collider component set to trigger must be included in order for this to work.
154+
155+
#### Enter
156+
157+
Logic fired when trigger is entered with a specific tag.
158+
159+
```c#
160+
.State(MyEnum.MyState, (state) => {
161+
state.TriggerEnter("Player", (action) => Debug.Log("Code goes here"));
162+
})
163+
```
164+
165+
#### Exit
166+
167+
Logic fired when trigger is exited with a specific tag.
168+
169+
```c#
170+
.State(MyEnum.MyState, (state) => {
171+
state.TriggerExit("Player", (action) => Debug.Log("Code goes here"));
172+
})
173+
```
174+
175+
#### Stay
176+
177+
Logic fired when trigger is exited with a specific tag.
178+
179+
```c#
180+
.State(MyEnum.MyState, (state) => {
181+
state.TriggerExit("Player", (action) => Debug.Log("Code goes here"));
182+
})
183+
```
184+
185+
### Animators
186+
187+
Talks to the current Animator. Note that an Animator component must be included on the passed GameObject owner.
188+
189+
#### Set Animator Bool
190+
191+
Sets an animator bool by string.
192+
193+
```c#
194+
.State(MyEnum.MyState, (state) => {
195+
state.SetAnimatorBool("myBool", true);
196+
})
197+
```
198+
199+
#### Set Animator Float
200+
201+
Sets an animator float by string.
202+
203+
```c#
204+
.State(MyEnum.MyState, (state) => {
205+
state.SetAnimatorFloat("myFloat", 2.2);
206+
})
207+
```
208+
209+
#### Set Animator Int
210+
211+
Sets an animator int by string.
212+
213+
```c#
214+
.State(MyEnum.MyState, (state) => {
215+
state.SetAnimatorInt("myInt", 7);
216+
})
217+
```
218+
219+
#### Set Animator Trigger
220+
221+
Sets an animator trigger by string.
222+
223+
```c#
224+
.State(MyEnum.MyState, (state) => {
225+
state.SetAnimatorTrigger("myInt");
226+
})
227+
```
228+
229+
## Creating Custom Actions
230+
231+
Here we'll cover how to create a custom action and use it in a way that gets free updates from this library. It's important you create new actions this way to prevent new versions from causing errors.
232+
233+
234+
The first thing you'll need to do is create a **custom action**.
235+
236+
```c#
237+
using UnityEngine;
238+
using CleverCrow.FluidStateMachine;
239+
240+
public class MyAction : ActionBase {
241+
public MyAction (string newName) {
242+
Name = newName;
243+
}
244+
245+
// Triggers when entering the state
246+
protected override void OnEnter () {
247+
Debug.Log($"Custom action {Name} activated");
248+
}
249+
250+
// Triggers when exiting the state
251+
protected override void OnExit () {
252+
}
253+
254+
// Runs every time `Fsm.Tick()` is called
255+
protected override void OnUpdate () {
256+
}
257+
}
258+
```
259+
260+
After the custom action is complete you'll need to create a **state builder** that inherits from the default state builder class.
261+
262+
```c#
263+
using CleverCrow.FluidStateMachine;
264+
265+
public class CustomStateBuilder : StateBuilderBase<CustomStateBuilder> {
266+
public CustomStateBuilder MyAction (string newName) {
267+
_actions.Add(new MyAction(newName));
268+
return this;
269+
}
270+
}
271+
```
272+
273+
The state builder must then be plugged into an **FSM builder** class to properly encapsulate newly created states.
274+
275+
```c#
276+
using CleverCrow.FluidStateMachine;
277+
278+
public class FsmBuilderCustom : FsmBuilderBase<FsmBuilderCustom, CustomStateBuilder> {
279+
}
280+
```
281+
282+
You've created a custom extendable FSM and state class that can be used anywhere in your code base. Try it out with a snippet like this.
283+
284+
```c#
285+
using UnityEngine;
286+
using CleverCrow.FluidStateMachine;
287+
288+
public class FsmBuilderCustomUsage : MonoBehaviour {
289+
private enum StateId {
290+
A,
291+
}
292+
293+
private void Awake () {
294+
var fsmBuilder = new FsmBuilderCustom()
295+
.State(StateId.A, (state) => {
296+
state
297+
.MyAction("custom name")
298+
.Update((action) => { });
299+
});
300+
301+
var fsm = fsmBuilder.Build();
302+
fsm.Tick();
303+
}
304+
}
305+
```

0 commit comments

Comments
 (0)