- Home /
Static Coroutine being called endlessly
So I needed a StartCoroutine in a static method, however since this is not possible I stumbled across a StaticCoroutine script (found here: http://benbeagley.com/2013/10/14/calling-a-static-ienumerator-in-unity/, original credits to user @whydoidoit).
The function I need to call makes the character turn towards another character he just walked to. It is being called like this in my static IEnumerator method:
public static IEnumerator doWalkingAction() {
if (subject._noun == "player") {
setWalkerScript(playerObj);
if (npcNames.Contains(direct._noun.ToLower())) {
startMovingToNPC(direct._noun.ToLower());
bool walkingNotDone = true;
while (walkingNotDone) {
if (playerObj.GetComponent<AgentWalker>().arrivedOrNot()) {
npcObj = GameObject.Find(direct._noun.ToLower());
StaticCoroutine.DoCoroutine(turnToFaceSmoothly(playerObj.transform, npcObj.transform));
playerObj.GetComponent<Animation>().animation.Play("idle");
Destroy(playerObj.GetComponent("AgentWalker"));
walkingNotDone = false;
} else {
yield return new WaitForSeconds(0.5f);
}
}
yield return null;
}
} else {
}
}
And the code of 'turnToFaceSmoothly' looks like this:
public static IEnumerator turnToFaceSmoothly (Transform targetThatWalks, Transform targetToLookAt) {
while (Vector3.Dot (targetThatWalks.forward, (targetToLookAt.position - targetThatWalks.position).normalized) < 0.95f) {
Vector3 dir = targetToLookAt.position - targetThatWalks.position;
targetThatWalks.rotation = Quaternion.Slerp(targetThatWalks.rotation, Quaternion.LookRotation(dir), 5f * Time.smoothDeltaTime);
targetThatWalks.eulerAngles = new Vector3(0f, targetThatWalks.eulerAngles.y, 0f);
yield return null;
}
}
When running my game, I noticed that this turnToFaceSmoothly method gets called non-stop, giving of course a very undesirable result!
Why does it do this? Thank you in advance for anyone who can help
Where do you start the coroutine? I mean, where do you call the StaticCoroutine.DoCoroutine method? Please copy/paste the entire block ins$$anonymous$$d of 1 line.
@Xtro thank you for commenting! I edited my question including the complete method with the method call!
Answer by Xtro · Dec 29, 2014 at 05:07 PM
You are starting the coroutine in another coroutine named doWalkingAction. Maybe, doWalkingAction is being started multiple times. Pls make sure it's not started constantly like in an update event. Please copy/paste where you start doWalkingAction coroutine.
@Xtro I am starting this coroutine in a coroutine yes! Is this a problem? I am quite confident that doWalkingAction is not started multiple times since my Start() calls a method, which calls a method, which calls ... -> eventually we get in this method where the doWalkingAction gets called, it is here:
public IEnumerator animateExpr(Game$$anonymous$$ove gm) {
passive = gm._interpr._passive;
if (passive) {
} else {
subject = gm._interpr._subject;
verb = gm._interpr._predicate._verb;
direct = gm._interpr._predicate._direct;
indirect = gm._interpr._predicate._indirect;
}
//Animation part
StoryFlowAction.setInterpretations (passive, subject, verb, direct, indirect, npcNames, textSynonyms, mailSynonyms);
switch (verb) {
case "goes-to":
case "walks-to":
yield return StartCoroutine (StoryFlowAction.doWalkingAction());
break;
case "talks-to":
break;
case "says-to":
break;
case "says":
break;
case "says to":
yield return StartCoroutine (StoryFlowAction.doTalkingToAction());
break;
case "texts to":
yield return StartCoroutine (StoryFlowAction.do$$anonymous$$essageNowAction("text"));
break;
case "sends to":
break;
case "emails to":
yield return StartCoroutine (StoryFlowAction.do$$anonymous$$essageNowAction("email"));
break;
case "gives to":
yield return StartCoroutine (StoryFlowAction.doGiveTo());
break;
case "picks-up":
case "grabs":
yield return StartCoroutine (StoryFlowAction.doPickupNowAction());
break;
case "receives from":
yield return StartCoroutine (StoryFlowAction.do$$anonymous$$essageReceivedFromAction());
break;
}
yield return null;
}
A lot of Debug's in between my code also shows me that it definitely not called multiple times!
Coroutine in coroutine is not a problem. I see that you set walkingNotDone to false so your while loop should break. With this info, I can't see any problem :(
@Xtro , thank you nontheless for looking at the problem!
Do you think it might be a problem with the StartCoroutine script? It is literally a copy and paste from http://benbeagley.com/2013/10/14/calling-a-static-ienumerator-in-unity/. $$anonymous$$aybe it has something to do with how this one handles stuff? Yield return null?
This 3rd party script is fine. It's just starting your static coroutine on its own gameobject because coroutines can only live on gameobjects.
If your project is small, I can look at it if you send me a zip file. If the project is big, maybe you can create an empty project and copy the required scripts in it to see if it has the same behavior.
P.S. : If you decide to send me the project, 1) enable meta files in editor settings. 2) only zip the "assets" and "project settings" folders, Not anything else. This is how you share with others If you didn't do it before.
Thank you for your help Xtro! I will find an alternative.
Answer by Nostrum Key · Dec 30, 2014 at 08:07 PM
Oh hey, thanks for checking out my blog. I will admit that post is a little old and honestly I try not to make static co-routines unless I really have to because, as you see here, it can get messy.
I think I can see the issue. You keep calling the static co-routine turnToFaceSmoothly while (walkingNotDone). turnToFaceSmoothly has its own contained while loop so calling it continually is going to cause issues.
Instead, try turning turnToFaceSmoothly into a static void method and turn the while loop into an if statement e.g.
public static void turnToFaceSmoothly (Transform targetThatWalks, Transform targetToLookAt)
{
if(Vector3.Dot (targetThatWalks.forward, (targetToLookAt.position - targetThatWalks.position).normalized) < 0.95f)
{
//code...
}
}
You also need a yield return (null or otherwise) contained in all your co-routine while loops that you want to run simultaneously with your other code. Simply, yield return allows the co-routine to wait until a target frame to continue running e.g. yield return null waits for the next frame. If you don't include it then the while loop will run and try to complete all in the same frame.
I hope I've been of some help. And thanks again for using my blog =D
He sets walkingNotDone to false in the first encounter so while loop breaks. It doesn't look like starting the coroutine repeatedly.
Thanks guys! I kinda figured out my code probably was not the best, so I rewrote a huge portion of it and it is working fine. This part of the code remained the same and works now, so I guess somewhere else something weird happened!Thanks a lot for helping me out Xtro! @Nostrum $$anonymous$$ey nice blog :-)
Your answer
Follow this Question
Related Questions
Why is this coroutine only firing once? 3 Answers
bounce player back to position while jumping 0 Answers
Lerp not working inside Coroutine. 1 Answer
Calling IEnumerator function with variables does not do anything 1 Answer
Smooth moving object 2 Answers