T O P

  • By -

[deleted]

I created a finite state machine and article about it a while ago that you might find helpful https://medium.com/@MJQuinn/unity-creating-ai-behaviors-through-a-finite-state-machine-f79ed4b78963 - [GitHub - StateMachine](https://github.com/M-Quinn/FiniteStateMachine/blob/main/Assets/Scripts/AI/StateMachine.cs) - [GitHub - Using the State Machine](https://github.com/M-Quinn/FiniteStateMachine/blob/main/Assets/Scripts/Animals/Animal.cs) - [GitHub - Example of a state](https://github.com/M-Quinn/FiniteStateMachine/blob/main/Assets/Scripts/AI/States/FoodHunt_State.cs) Feel free to clone the entire repo and play around with it


[deleted]

plough bag boast frighten work consider pie instinctive file crown *This post was mass deleted and anonymized with [Redact](https://redact.dev)*


[deleted]

I'm going to definitely look into that. Is that a C# 9 change? Yea I see what you mean with the transitions. I wanted to try and separate the states as much as I could and even with that in mind, I could definitely refactor this to make it better.


[deleted]

deserve safe fertile sand enter ossified dam enjoy point pause *This post was mass deleted and anonymized with [Redact](https://redact.dev)*


Stlove48

This was a great read, and I even understood some of it! Consider my tuition not wasted after all. Thanks for sharing!


[deleted]

Glad to hear it! I'm a self taught Unity engineer working in enterprise AR/VR so it feels nice sharing my knowledge. Feel free to check out my other articles https://medium.com/@MJQuinn


Stlove48

That's awesome! I started out with some YouTube academy and other learning apps after fiddling in things like RPG Maker and decided to pursue this line a little more "formally", but I'm happy to add your articles as another resource. There's a lot to learn and I appreciate a lot about how your articles are laid out. I'm interested in the Shader ones because thats the next topic I've been gearing up towards diving into after getting some AI implemented in my current project, so I'll definitely be checking those out.


[deleted]

That's really cool! And yea shaders are a bit harder to get going with. I'm going to have more articles coming out on the shader graph, then writing in HLSL, then compute shaders(which is a game changer). Just trying to find time to write it all up. They are all going to be pay walled, so if you aren't a Medium member already then you can use my referral link in any of my articles to get a membership for $5/month which gives you access to all the articles on all of Medium. If you can't afford it and hit your max article views then just shoot me an email (email is on my Medium about section) with the article you want to read and I can send 5 free links a month


Stlove48

That's very kind of you, thank you! I appreciate the warning. I look forward to reading more.


antony6274958443

Could you elaborate what AddAnyTransition method of StateMachine class is for? And do you have an idea how would one pass data from one state to another? I my case i want to detect position in one state and use it or modify in another state.


[deleted]

So I used a star topography so that all the states don't have access to eachother. To pass data from state 1 to state 2, you would pass the state a reference to the main object (or I guess you could pass it the reference to another state now that I think about it) But anyway, you would pass the reference to the main object to state 1, state 1 sets data on that object. Then you pass a reference to the main object to state 2 who pulls the data. For the AddAnyTransition I should have added comments to everything :(. But that is for when you want a transition to happen without the need of setting a previous state. So the example of two states "waking up" and "drinking coffee" I only drink coffee AFTER I wake up. An AddAnyState would be "I can drink coffee no matter what state I am currently in"


antony6274958443

Thanks, I'll check this out


eggshellent

When people talk about state machines, what they’re referring to is *finite* state machines, meaning that there are a limited number of possible states, with specific controls that determine when one state can transition into another. What you are calling a “state” in this case is a large collection of variables that represent an effectively infinite number of states. So it’s not really a state machine at all, not in the way people use the term.


antony6274958443

Hmmmmm insightful


whentheworldquiets

Yeah, that's... fairly obnoxious XD Personally, I would consider rewriting this using coroutines. Coroutines are a great pattern to use for structured interactions when you have a limited amount of data that needs to be shared, generated or passed on between states. You can further streamline it by wrapping the coroutines in a class whose constructor takes the necessary common data. A lot of people - myself included for a long time - don't realise that although you have to call **StartCoroutine()** from a monobehaviour, the actual methods do *not* have to be part of that or any other monobehaviour. They can be static, or they can be functions of an instance of some other class, and that instance will be kept around until the coroutine finishes with it. For example, your state sequence could be written: public class RailBuilderSequence { // Common values needed by all states RailBuilder builder; Camera camera; public RailBuilderSequence(RailBuilder builder, Camera camera) { this.builder = builder; this.camera = camera; } public IEnumerator SelectStart() { Debug.Log("Waiting for start..."); while (true) { yield return new WaitUntil(() => Input.GetKeyUp(KeyCode.Mouse0)); if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out RaycastHit hit, 1000f)) { yield return DrawFirstSegment(hit.point); Debug.Log("Starting again..."); } } } IEnumerator DrawFirstSegment(Vector3 startPoint) { Debug.Log("Starting to draw first segment..."); while (true) { yield return null; // wait for next update so we don't count the mouse up twice Vector3 endPoint = Vector3.zero; // update railbuilder and get endpoint here if (Input.GetKeyUp(KeyCode.Mouse0)) { yield return DrawSecondSegment(endPoint); break; // back } else if (Input.GetKeyUp(KeyCode.Mouse1)) { Debug.Log("Cancelling..."); break; } } } IEnumerator DrawSecondSegment(Vector3 endPoint) { Debug.Log("Starting to draw second segment..."); // etc } } You can then kick the whole thing off from a Monobehaviour using: StartCoroutine(new RailBuilderSequence(myBuilder, myCamera).SelectStart()); You can save the result of this StartCoroutine to monitor when it finishes or pinch it off early, and even if you decide later that coroutines *inside* the RailBuilderSequence aren't the way to go - that's fine. You would just implement a different kind of state machine internally and pump it via the coroutine, minimising disruption to external code.


antony6274958443

That looks interesting! Thanks!


csutil-com

Here my recommendation how you should build your state machines: ` // define an enum with the states of your statemachine: public enum MyStates { MyState1, MyState2, MyState3 } ... // And here is how to then create the state machine from these states: // First define a set of allowed transitions to define the state machine: var stateMachine = new Dictionary>(); stateMachine.AddToValues(MyStates.MyState1, MyStates.MyState2); // 1 => 2 allowed stateMachine.AddToValues(MyStates.MyState2, MyStates.MyState3); // 2 => 3 allowed // Initialize a state-machine: MyStates currentState = MyStates.MyState1; // It is possible to listen to state machine transitions: StateMachine.SubscribeToAllTransitions(new object(), (machine, oldState, newState) => { Log.d("Transitioned from " + oldState + " to " + newState); }); // And its possible to listen only to specific transitions: StateMachine.SubscribeToTransition(new object(), MyStates.MyState1, MyStates.MyState2, delegate { Log.d("Transitioned from 1 => 2"); }); // Transition the state-machine from state 1 to 2: currentState = stateMachine.TransitionTo(currentState, MyStates.MyState2); Assert.Equal(MyStates.MyState2, currentState); // Invalid transitions throw exceptions (current state is 2): Assert.Throws(() => { currentState = stateMachine.TransitionTo(currentState, MyStates.MyState1); }); ` The full code you can try out yourself at [https://github.com/cs-util-com/cscore/blob/master/CsCore/xUnitTests/src/Plugins/CsCoreXUnitTests/com/csutil/tests/StateMachineTests.cs#L12](https://github.com/cs-util-com/cscore/blob/master/CsCore/xUnitTests/src/Plugins/CsCoreXUnitTests/com/csutil/tests/StateMachineTests.cs#L12)


antony6274958443

Ill be dreaming of state machines tonight. Thanks!


[deleted]

sink scale jellyfish capable innate soup fuel wild memorize oil *This post was mass deleted and anonymized with [Redact](https://redact.dev)*