Search Unity

c# Mecanum problem

Discussion in 'Scripting' started by clearrose, Aug 18, 2015.

  1. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Hello, again unity community I come to you with a problem that has stalled our development for about a day and half. Our Player uncontrollably won't stop cycling through he's animation states over and over again in a endless loop. Even though the parameters for his transitions in mecanum haven't been meant. Below I have posted a breakdown of the problem.

    Breakdown from the editor:

    The player's animations are cycling like this uncontrollably:



    Besides this the print statements in my code, Just won't stop printing over and over again. When they should be printing only once per player input. Another symptom to the problem I guess.



    My profiler also showed that my function (to set the animation's parameter) is being called over and over again when there is no input from the player:



    Code Breakdown:

    From SwimmingTurtlePlayer to TurtleBack (TurtleBack is a Blend tree between to clips) we were using a float parameter for speed (note that the player is moving backwards on the x-axis in the negative direction);

    Code:

    Code (CSharp):
    1.  
    2.     public Animator TurtlePlayer;
    3.     public Rigidbody2D Turtle;
    4.     public Vector2 velocity;
    5.     public Vector2 backVelocity;
    6.     public float BackVelocity;
    7.     public float Velocity;
    8.  
    9. if (Input.GetKey (KeyCode.Mouse2)) {
    10.  
    11.        Turtle.MovePosition (Turtle.position - backVelocity *Time.fixedDeltaTime);
    12.              //move player's rigid body backwards.
    13.  
    14.        TurtlePlayer.SetFloat ("TurtleSpeed",BackVelocity);  
    15.              //set float parameter for player's speed.
    16.  
    17.             Invoke("StartReverseTrans", 3); // invoke new function to give player time to move before starting the coroutine.
    18.         }
    Then from TurtleBack to TurtleBackToNormal we are using a bool parameter called TurtleSwimNow that is set equal to true.

    Code:

    Code (CSharp):
    1. void StartReverseTrans()
    2.     {
    3.         TurtlePlayer.SetBool("TurtleSwimNow",true); // set player's animation bool parameter.
    4.         Turtle.velocity = Vector2.zero; // set player's speed to zero as a reset. Speed will change upon player's new input.
    5.         print ("I'm A transitioning Turtle");
    6.        
    7.         StartCoroutine(TurtleSwimNow()); //start coroutine.
    8.     }
    Finally, from TurtleBackToNormal to SwimmingTurtlePlayer the bool parameter TurtleSwimNow is set to false.

    Code:

    Code (CSharp):
    1. IEnumerator TurtleSwimNow ()
    2.     {
    3.         TurtlePlayer.SetBool ("TurtleSwimNow", true);  // set player's animation bool parameter.
    4.        
    5.         yield return new WaitForSeconds (2f);
    6.        
    7.         TurtlePlayer.SetBool ("TurtleSwimNow", false); // set player's animation bool parameter. Player then returns to default animation in mecanum.
    8.         print ("I'm Swimming Normally Now");
    9.     }
    Can someone help us, we will appreciate it.
     
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Can you post more code. The first segment you posted doesnt appear valid.
     
  3. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    I send you a message.
     
  4. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Anymore suggestions?
     
  5. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Yeah, don't send private messages to individuals. Just because they respond once doesn't make them obligated to keep helping until the problem is solved. Also, more than half of debugging is trial and error, with printing/Debug.Logs making up the rest. By keeping part of the problem-solving process out of the thread and in private messages, you're killing some of the "trial and error" benefits- in other words we don't know what someone else may have already told you to try, so we're likely to tell you to try some of the same things and waste time.
    Code (csharp):
    1. if (Input.GetKey (KeyCode.Mouse2)) {
    needs to be:
    Code (csharp):
    1. if(Input.GetKeyDown(KeyCode.Mouse2)) {
    It's checking it every single frame for "if mouse button is held down", which means it's triggering your invoke method several dozen times per second, which is then starting several dozen coroutines a second. If you want movement to be possible on GeyKey and animation triggering to occur on GeyKeyDown and GetKeyUp, those need to be separate conditionals.
     
    Last edited: Aug 20, 2015
  6. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Noted, I'm very sorry about that, I do apologize.

    Well, I tested it and the player's backwards animation doesn't even play. However I do see the print statements from the method that gets invoked and the print statement from the coroutine.
     
  7. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    If you look at the parameter list while in Play mode, you can see what the values are at any given moment (just remember to select your character in the scene view, rather than leaving it on the prefab or w/e, or else it won't show the "instance" version in the Animator screen).

    With Debug.Logs that aren't jamming up on the console 10,000 times a second and combined with the parameter values being shown, you should be able to narrow down where things are messing up.
     
  8. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    While, I went through and added a Debug.Log statement for each line and I got all of them back:



    Code (CSharp):
    1. if (Input.GetKeyDown(KeyCode.Mouse2))
    2.         {
    3.             Turtle.MovePosition(Turtle.position - backVelocity * Time.unscaledDeltaTime);
    4.             Debug.Log("player is moving backwards");
    5.             TurtlePlayer.SetFloat ("TurtleSpeed",BackVelocity);
    6.             Debug.Log("player's animation is set");
    7.         }
    8.  
    9.         else if (Input.GetKeyUp(KeyCode.Mouse2) && !invokeReset)
    10.         {
    11.             Invoke("StartReverseTrans", 3);
    12.             Debug.Log("player's aniamtion method is invoked");
    13.             invokeReset = true;
    14.             Debug.Log("player's invoke reset is true");
    15.         }
    Code (CSharp):
    1. void StartReverseTrans()
    2.     {
    3.         TurtlePlayer.SetBool("TurtleSwimNow",true);
    4.         Debug.Log("player's animation bool is set");
    5.         Turtle.velocity = Vector2.zero;
    6.         Debug.Log ("player's velocity is reset");
    7.         invokeReset = false;
    8.         print ("I'm A transitioning Turtle");
    9.        
    10.         StartCoroutine(TurtleSwimNow());
    11.     }
    Code (CSharp):
    1. IEnumerator TurtleSwimNow ()
    2.     {
    3.         TurtlePlayer.SetBool ("TurtleSwimNow", true);
    4.         Debug.Log ("player's animation bool is true, start to transition");
    5.        
    6.         yield return new WaitForSeconds (2f);
    7.        
    8.         TurtlePlayer.SetBool ("TurtleSwimNow", false);
    9.         print ("I'm Swimming Normally Now");
    10.     }
    However the player doesn't move backwards anymore so the parameter for his speed isn't being triggered. But the parameter for bool is.

    Should I change the line of code that moves the player? why isn't the player movement working now when it was before with get key vs get key down? I thank you for helping me solve this problem.
     
  9. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Oh, that. Sorry, I was more worried about the infinite Invoke than anything.

    GetKeyDown is only allowing the inside of the conditional to run for a single frame- when the button is first pressed- it won't return true again until you release and press the button again. You should move the "MovePosition" to within a separate GetKey conditional (which will activate every frame the button is held), or alternatively you could create a "moving direction" Vector2 value that serves to activate a separate conditional in FixedUpdate when it's "not Vector2.zero", and... well, like this:
    Code (csharp):
    1. if(moveDirection != Vector2.zero)
    2. {
    3.     Turtle.MovePosition(Turtle.position - (moveDirection * Time.unscaledDeltaTime));
    4. }
    You'll just have to pre-multiply moveDirection with your forward/backward velocity when the button is pressed, and then it'll keep going until the button is released, at which point you'll set moveDirection to Vector2.zero again.

    Hope that helps!
     
  10. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Well, I got him to move backwards again, by adding another conditional for GetKey and placing the player movement code there.

    Code (CSharp):
    1. if (Input.GetKey(KeyCode.Mouse2))
    2.         {
    3.             Turtle.MovePosition(Turtle.position - backVelocity * Time.unscaledDeltaTime);
    4.             Debug.Log("player is moving backwards");
    5.            
    6.             TurtlePlayer.SetFloat ("TurtleSpeed",BackVelocity);
    7.             Debug.Log("player's speed animation is set");
    8.         }
    9.  
    10.         else if (Input.GetKeyUp(KeyCode.Mouse2) && !invokeReset)
    11.         {
    12.             Invoke("StartReverseTrans", 3);
    13.             Debug.Log("player's aniamtion method is invoked");
    14.             invokeReset = true;
    15.             Debug.Log("player's invoke reset is true");
    16.         }
    However the speed parameter still isn't working. I found some strange behavior in my blend tree ("TurtleBack"), My speed parameter was set to transition SwimmingTurtlePlayer to Turtleback if speed is less than -0.01. When I look at the slider in my blend tree before I start play mode it is normal, but when I start play mode and press the middle mouse key, the slider jumps to 30. Thus keeping my animations from playing and transitioning properly.



     
  11. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Code (csharp):
    1. TurtlePlayer.SetFloat("TurtleSpeed",BackVelocity);
    This says you're setting it to whatever value "BackVelocity" is in the inspector, which I now assume is 30. There's nothing in any of the scripts you've shown that has you setting BackVelocity or TurtleSpeed to anything other than this, so either this is the problem, or it's in some script you haven't posted- either way there's absolutely no way for me to figure it out from here.

    Need to go get some sleep so I won't be able to help you further, I hope you get it all figured out!
     
  12. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    You were right I set to 30 in the inspector, at least now it's set back to normal. Well I hope that you get a good sleep :).

    Anyways, I got the infinite loop between animations again just like before. As a test I cut out the invoke to see if that is what was causing the loop. So when I did cut it from the code it stills loops. could is possibly be the coroutine?

    new code:

    Code (CSharp):
    1. if (Input.GetKey(KeyCode.Mouse2))
    2.         {
    3.             Turtle.MovePosition(Turtle.position - backVelocity * Time.unscaledDeltaTime);
    4.             //Debug.Log("player is moving backwards");
    5.  
    6.             TurtlePlayer.SetFloat ("TurtleSpeed",BackVelocity);
    7.             //Debug.Log("player's speed animation is set");
    8.         }
    9.  
    10.         else if (Input.GetKeyUp(KeyCode.Mouse2))
    11.         {
    12.             TurtlePlayer.SetBool("TurtleSwimNow",true);
    13.             //print ("I'm A transitioning Turtle");
    14.            
    15.             StartCoroutine(TurtleSwimNow());
    16.         }
    Code (CSharp):
    1. IEnumerator TurtleSwimNow ()
    2.     {
    3.         TurtlePlayer.SetBool ("TurtleSwimNow", true);
    4.         //Debug.Log ("player's animation bool is true, start to transition");
    5.        
    6.         yield return new WaitForSeconds (2f);
    7.  
    8.         TurtlePlayer.SetBool ("TurtleSwimNow", false);
    9.         //print ("I'm Swimming Normally Now");
    10.     }
     
  13. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Hello, again I just run another test to diagnose this problem. I put another Debug.Log at the beginning of the if statement with the Player's movement code. When tested the console printed that statement 46 times even I only pressed the middle mouse button once. Also note that the other print statements printed only once, including the ones in the coroutine.



    Code (CSharp):
    1. if (Input.GetKey(KeyCode.Mouse2))
    2.         {
    3.             Debug.Log ("Start moving Turtle Backwards");
    4.  
    5.             Turtle.MovePosition(Turtle.position - backVelocity * Time.unscaledDeltaTime);
    6.             //Debug.Log("player is moving backwards");
    7.  
    8.             TurtlePlayer.SetFloat("TurtleSpeed",BackVelocity);
    9.             //Debug.Log("player's speed animation is set");
    10.         }
    11.  
    12.         else if (Input.GetKeyUp(KeyCode.Mouse2))
    13.         {
    14.             TurtlePlayer.SetBool("TurtleSwimNow",true);
    15.             //print ("I'm A transitioning Turtle");
    16.            
    17.             StartCoroutine(TurtleSwimNow());
    18.         }
     
  14. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    That sounds like it's doing what it's supposed to be doing- GetKey fires every frame that the button is held. How exactly are the parameter transition requirements set in the Animator window? Click on the arrow between TurtleBack and TurtleBackToNormal for me and screenshot it, please.
     
  15. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Ok, this first transition is our speed parameter from "swimming turtle player" to "turtle back":





    This is from "turtle swim back" to "turtle back to normal", we used a bool here thats set to true:





    Finally, this transition is from "turtle back to normal" to "Swimming turtle player". The bool parameter is now set to false:



     
  16. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I think the problem is you need to uncheck has exit time. Im no mecanim expert though. I never got to look at your code, but it seems like youve had plenty of help here.

    tbh, you dont need to worry about posting full code. There wasnt anything special about it, and often you get people that will give you tips on how to improve it. ie, I would cache your co-routine enumerators.
     
  17. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thanks, I'm just wondering what you meant by "cache your co-routine enumerators" ?

    But, I did turn off the exit time and I still got the same result.
     
    Last edited: Aug 24, 2015
  18. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
  19. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
  20. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Houston we are still having problems. The animation is still acting weird
     
  21. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Plz, any help is appreciated. This problem is holding back our project.
     
  22. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
  23. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
  24. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Still need help...