- Home /
StateMachineBehaviour + StartCoroutine()
Hi there! I'd like to know, if it's possible, how to StartCoroutine() inside a StateMachineBehaviour script.
I've tried the following:
IEnumerator WaitSomeThenResetStuff (Animator anim){
yield return new WaitForSeconds(4f);
//Reset stuff
anim.ResetTrigger("stuff");
}
// OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
StartCoroutine(WaitSomeThenResetStuff(animator));
}
But " StartCoroutine" is unknown to classes that inherits from StateMachineBehaviour.
I thought ( because my knowledge is approssimative) to solve the problem by adding an interface to MonoBehaviour but another error showed up... maybe I made some mistakes or maybe that's not the best approach.
I ended up using the StateMachineBehaviour's Update with a clock to do the same thing, caching Time.time inside OnStateEnter().
Thanks for your time!
Answer by jxz12 · Apr 28, 2017 at 11:28 AM
Hi, I'm a little late but I came across a similar problem and came up with a few solutions that work.
The first is to use a MonoBehaviour attached to the animator's GameObject, and have the function inside that starts the coroutine be public so that you can call it like so:
public class MyScript : MonoBehaviour {
public void DoCoroutine() {
StartCoroutine(/*your routine*/);
}
}
public class MyState : StateMachineBehaviour {
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
animator.GetComponent<MyScript>().DoCoroutine();
}
}
and another way that I'd use if possible would be to just use animation events, which are nice if you like working entirely inside Unity's animation system, which it seems like you do since you're using the StateMachineBehaviours already.
Answer by fafase · Jun 07, 2015 at 01:51 PM
StartCoroutine needs a MonoBehaviour to be used. Your StateMachineBehaviour seems not to be so you probably have a constructor call to create the StateMachine object. This constructor is most likely called from a MonoBehaviour. That'd be when you pass the MonoBehaviour:
private MonoBehaviour monoBehaviour = null;
public StateMachineBehaviour(MonoBehaviour monoBehaviour){
this.monoBehaviour = monoBehaviour;
}
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
this.monoBehaviour.StartCoroutine(WaitSomeThenResetStuff(animator));
}
the other solution is to make your StateMachine inherits from MonoBehaviour which would actually make it consistent with the current naming. Using the term Behaviour generally implies that it includes the Behaviour class in it (not necessarily though).
public class StateMachineBehaviour:MonoBehaviour{}
then you can use it as a component.
State$$anonymous$$achineBehaviour is a built-in class, derived from ScriptableObject, so he can't derive it from $$anonymous$$onoBehaviour.
http://docs.unity3d.com/ScriptReference/State$$anonymous$$achineBehaviour.html
Aaah ok, so yes, add a Init method to your script and when it is created, just pass a $$anonymous$$onoBehaviour reference. Then whenever you need one, you can use it.
You can also override the CreateInstance:
public class $$anonymous$$yClass:State$$anonymous$$achineBehaviour{ private $$anonymous$$onoBehaviour monoBehaviour = null;
public static void CreateInstance($$anonymous$$onoBehaviour new$$anonymous$$onoBehaviour){
CreateInstance(); // Call the original one that actually creates the object
this.monoBehaviour = new$$anonymous$$onoBehaviour;
}
}
But you also need to make sure the reference is an object that will always be there.
Hi fafase! Thanks a lot for your suggestion! Unfortunately I'm not sure to understand, sorry. Could you please elaborate a bit more how would I use the CreateInstance() function?
Right now the script I've posted ( let's say its name is $$anonymous$$yClass) inherits from State$$anonymous$$achineBehaviour ( as $$anonymous$$outon pointed out), and is placed as a component of a state machine' State.
When the game starts, the script is already there so I can't create an instance of it runtime. That is, unless I manage to address that particular stage and instantiate $$anonymous$$yClass as its component.
A side note:
this.monoBehaviour = new$$anonymous$$onoBehaviour;
this is not supported with static, it returned me an error.
Thanks a lot again!
Your answer
![](https://koobas.hobune.stream/wayback/20220613200729im_/https://answers.unity.com/themes/thub/images/avi.jpg)