Search Unity

Character moving randomly

Discussion in '2D' started by RushdiRamz, Sep 3, 2019.

  1. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    Hello, I’m fairly new to both unity and coding (Probably one of the biggest)

    So i am making a 2D game for which I plan on putting on Android and I have set up the character controls using buttons and animations for that character. The problem is when playing the game, I randomly stop moving, but my walking animations still plays.(in happens randomly in the levels)
    Is there a way for me to find the cause of it?

    Sorry for my noobness
     
  2. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    Hi. No worries, we are all noob at something (or were at some point).

    So first you need to make sure to separate in your mind the code that moves the character, and the animation/animator components that displays how the character looks like while moving. The reason for this is to help determine where the problem lies (code or animator).

    Now, it sounds like you are already aware of where the problem lies, which is the walking animation. You say that randomly the animation keeps playing while you stop moving. This has to do with what triggers your walking animation, inside the animator window. You usually add a condition, and if this condition is met, the animation plays out.

    For example: if my character has a speed greater than 0.1f, have the animator runs the walking animation. Now, that would be when you transition INTO the walking animation. What would be your trigger when transitioning OUT the walking animation? For the purpose of this example, it's simple: speed less than 0.1f.

    The above example works if you have an IDLE default animation, and you want to transition into a WALKING animation. You only have 1 variable inside the animator (speed), and you just add a condition for when going in, and a condition for when going out of it.

    In order to find out why your character keeps walking a bit after you stop moving, I recommend moving the Animator Window to a place where you can see this and the Game Window at the same time. Then hit play, select your character, and move. Take a look at when your walking animation starts, and when it ends, and if there are any weird transitions between walking and any other animation. This should help you determine why the animation keeps playing.

    NOTE: code an Animator rules usually go hand in hand (for example, in order for your character to have a speed greater/less than 0.1f he needs to be moving, and you usually do this through input), but when animations get stuck or transition weird, it is usually a good idea to play the game and have the Animator window open to see what is happening to it.
     
    m2artur606 likes this.
  3. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    Thanks so much for your response!

    Unfortunately I think I didn’t say the problem clearly, so as to which you might have misunderstood.

    When I move my character in any direction, it moves as it should, but at some point (very random and happens quite often) the character stops moving while I haven’t released the button, and the walking animation still appears. It’s as if something’s blocking my path, but there isn’t anything.

    I’m using the standard assets from the asset store. And I use the CrossPlatformInputManager for the UI buttons for my character to move. I don’t have any idea what’s blocking my player.
     
  4. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    I see. Ok that clears it up a bit. It now sounds to me that there might be something blocking the player as you said. Just to make sure, is your character moving on a 2D platform? as in... just a piece of geometry? if yes, is it a perfect box/rectangle? does it have any outstanding geometry like rocks or spikes? Also, is your character using a box collider or a circle/capsule collider?
     
  5. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    Yep, my character is moving on a 2D platform which is a perfect box. I haven't Added anything on top of it, and yes I am using a box collider 2D on my character, and the blocks (Which are of one type) are made using the tilemap, and has tilemap colider 2D in it (which I believe applies to all my tiles)
     
  6. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    That's interesting. I also use the tilemap, havent really ran into a collider issue with perfect boxes. I did learn that for climbing hills and things like that, you want to use a Capsule Collider instead, so the character can actually go up/down the hills. Also recommended to avoid the player getting one of the box corners stuck onto a platform, like, stuck in the air but next to one.

    Ok so, next step, how do you move and animate your character? Can you show us the code you are using to call the Animator component? Also can you show us the variable you use in the Animator to start the animation sequence? That would really help get an idea of how things are setup and see if there's something funky in there.
     
  7. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    Alright,
    I use 2 C# scripts for moving my character one is PlayerMovement.cs and CharacterController2D

    PlayerMovement.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityStandardAssets.CrossPlatformInput;
    5.  
    6. public class PlayerMovement : MonoBehaviour
    7. {
    8.     public CharacterController2D controller;
    9.     public float runSpeed = 40f;
    10.     float horizontalMove = 0f;
    11.     bool jump = false;
    12.     public Animator animator;
    13.  
    14.     // Update is called once per frame
    15.     void Update()
    16.     {
    17.         horizontalMove = CrossPlatformInputManager.GetAxis("Horizontal") * runSpeed;
    18.  
    19.         animator.SetFloat("Speed", Mathf.Abs(horizontalMove));
    20.  
    21.         if (CrossPlatformInputManager.GetButtonDown("Jump"))
    22.         {
    23.             jump = true;
    24.             animator.SetBool("isJumping", true);
    25.         }
    26.     }
    27.  
    28.     public void isJumping()
    29.     {  
    30.         animator.SetBool("isJumping", true);
    31.     }
    32.  
    33.     public void OnLanding ()
    34.     {
    35.         animator.SetBool("isJumping", false);
    36.     }
    37.  
    38.     void FixedUpdate()
    39.     {
    40.         controller.Move(horizontalMove * Time.fixedDeltaTime, false, jump);
    41.         jump = false;
    42.  
    43.     }
    44.    
    45. }
    46.  
    and CharacterController2D (which I got from Brackeyes tutorial on moving 2D objects)

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3.  
    4. public class CharacterController2D : MonoBehaviour
    5. {
    6.     [SerializeField] private float m_JumpForce = 850f;                            // Amount of force added when the player jumps.
    7.     [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f;            // Amount of maxSpeed applied to crouching movement. 1 = 100%
    8.     [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;    // How much to smooth out the movement
    9.     [SerializeField] private bool m_AirControl = false;                            // Whether or not a player can steer while jumping;
    10.     [SerializeField] private LayerMask m_WhatIsGround;                            // A mask determining what is ground to the character
    11.     [SerializeField] private Transform m_GroundCheck;                            // A position marking where to check if the player is grounded.
    12.     [SerializeField] private Transform m_CeilingCheck;                            // A position marking where to check for ceilings
    13.     [SerializeField] private Collider2D m_CrouchDisableCollider;                // A collider that will be disabled when crouching
    14.  
    15.     const float k_GroundedRadius = .05f; // Radius of the overlap circle to determine if grounded
    16.     private bool m_Grounded;            // Whether or not the player is grounded.
    17.     const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
    18.     private Rigidbody2D m_Rigidbody2D;
    19.     private bool m_FacingRight = true;  // For determining which way the player is currently facing.
    20.     private Vector3 m_Velocity = Vector3.zero;
    21.  
    22.     [Header("Events")]
    23.     [Space]
    24.  
    25.     public UnityEvent OnLandEvent;
    26.  
    27.     [System.Serializable]
    28.     public class BoolEvent : UnityEvent<bool> { }
    29.  
    30.     public BoolEvent OnCrouchEvent;
    31.     private bool m_wasCrouching = false;
    32.  
    33.     private void Awake()
    34.     {
    35.         m_Rigidbody2D = GetComponent<Rigidbody2D>();
    36.  
    37.         if (OnLandEvent == null)
    38.             OnLandEvent = new UnityEvent();
    39.  
    40.         if (OnCrouchEvent == null)
    41.             OnCrouchEvent = new BoolEvent();
    42.     }
    43.  
    44.     private void FixedUpdate()
    45.     {
    46.         bool wasGrounded = m_Grounded;
    47.         m_Grounded = false;
    48.  
    49.         // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
    50.         // This can be done using layers instead but Sample Assets will not overwrite your project settings.
    51.         Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
    52.         for (int i = 0; i < colliders.Length; i++)
    53.         {
    54.             if (colliders[i].gameObject != gameObject)
    55.             {
    56.                 m_Grounded = true;
    57.                 if (!wasGrounded)
    58.                     OnLandEvent.Invoke();
    59.             }
    60.         }
    61.     }
    62.  
    63.  
    64.     public void Move(float move, bool crouch, bool jump)
    65.     {
    66.         // If crouching, check to see if the character can stand up
    67.         if (!crouch)
    68.         {
    69.             // If the character has a ceiling preventing them from standing up, keep them crouching
    70.             if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround))
    71.             {
    72.                 crouch = true;
    73.             }
    74.         }
    75.  
    76.         //only control the player if grounded or airControl is turned on
    77.         if (m_Grounded || m_AirControl)
    78.         {
    79.  
    80.             // If crouching
    81.             if (crouch)
    82.             {
    83.                 if (!m_wasCrouching)
    84.                 {
    85.                     m_wasCrouching = true;
    86.                     OnCrouchEvent.Invoke(true);
    87.                 }
    88.  
    89.                 // Reduce the speed by the crouchSpeed multiplier
    90.                 move *= m_CrouchSpeed;
    91.  
    92.                 // Disable one of the colliders when crouching
    93.                 if (m_CrouchDisableCollider != null)
    94.                     m_CrouchDisableCollider.enabled = false;
    95.             } else
    96.             {
    97.                 // Enable the collider when not crouching
    98.                 if (m_CrouchDisableCollider != null)
    99.                     m_CrouchDisableCollider.enabled = true;
    100.  
    101.                 if (m_wasCrouching)
    102.                 {
    103.                     m_wasCrouching = false;
    104.                     OnCrouchEvent.Invoke(false);
    105.                 }
    106.             }
    107.  
    108.             // Move the character by finding the target velocity
    109.             Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
    110.             // And then smoothing it out and applying it to the character
    111.             m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
    112.  
    113.             // If the input is moving the player right and the player is facing left...
    114.             if (move > 0 && !m_FacingRight)
    115.             {
    116.                 // ... flip the player.
    117.                 Flip();
    118.             }
    119.             // Otherwise if the input is moving the player left and the player is facing right...
    120.             else if (move < 0 && m_FacingRight)
    121.             {
    122.                 // ... flip the player.
    123.                 Flip();
    124.             }
    125.         }
    126.         // If the player should jump...
    127.         if (m_Grounded && jump)
    128.         {
    129.             // Add a vertical force to the player.
    130.             m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
    131.         }
    132.     }
    133.  
    134.  
    135.     private void Flip()
    136.     {
    137.         // Switch the way the player is labelled as facing.
    138.         m_FacingRight = !m_FacingRight;
    139.  
    140.         // Multiply the player's x local scale by -1.
    141.         Vector3 theScale = transform.localScale;
    142.         theScale.x *= -1;
    143.         transform.localScale = theScale;
    144.     }
    145. }
    146.  
    There seems to be a lot of codes, so thanks so much for helping me through this :)
     
  8. Helladah

    Helladah

    Joined:
    May 5, 2018
    Posts:
    254
    maybe it could be an issue with your animator, since you said that sometimes it dosent respodn as it should, i mean, did you put a motion point of the gameobject that you move? cause you have to understand that the animation of moving the character isnt supouse to move the character, so you have to put the animator prefab where your character moves as a children of a gameobject of the script that moves the whole thing, that if you are willing to modife the transform of the gameobject at the animation, anyway you shall check of the transictions conditions to debug the problem

    At YouTube there is a lot of tutorials of how do it right, maybe you shall to check it out one of them
     
  9. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    I also initially started using Brackey's example with a PlayerMovement and CharacterController scripts. I eventually moved to a single player controller/movement script basically because Brackey's Character has a loooot of code and I decided to build a simpler one (based on another example).

    I was checking your code (first part) and I believe everything's pretty much ok, except maybe your jump animation call, it seems you are calling it twice, once once on button down and once on isJumping true...

    animator.SetBool("isJumping", true);

    The animation bool is changed twice, maybe the 2nd one is not needed.

    Either way, dont think that is the problem. I still strongly recommend that you bring up the Animator Window, hit play, repro the issue and pay attention on how the walking animation plays out (how long it takes to play, when it starts, when it ends (if it does), etc...).
     
    Helladah likes this.
  10. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    I think the problem lies in the tilemaps, I may have not set it up properly.

    The animation plays as it should, when my speed is greater than 0.01 it moves, and with the animator window, I hit play and get the bug, the animation still plays, and when I let go of the button it stops. When I press it again the animation still shows, but no movement like im walking towards a wall.

    But when I jump over the area the bug happens, the bug is gone and I’m able to move like normal, until it happens somewhere else.

    I’m using the tiles from the free platform game assets (by BayatGames).
     
  11. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    Ok, one easy way to test this is... use a different surface, not the tilemap, change the ground to 1 sprite with 1 big collider box (you dont even need the sprite, that would be there as a visual aid). Then test, walk on it, jump on it, etc... If you still get the error, then the tilemap is not the problem. If you don't get the error, the problem is the tilemap.

    If the problem is the tilemap, I havent played w that one in particular but there's a chance the Tilemap Collider that is autogenerated to match the terrain has a bump in it or something. It would be a good idea to run a test by selecting both your character and the collider at the same time (so you see both), and go over the bug area.
     
    RushdiRamz and Helladah like this.
  12. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    Yep, the problem was with the tilemap,

    I wrote my own controls to use RigidBody2D and the bug still existed. And now when I tried your suggestion, the bug was gone.

    I guess the tilemap isn’t made for 2D platformers? I have read online and found some people used edge colliders, but I have no idea to use them

    I couldn’t quite understand how to run the test that you mentioned about the character and collider, but I will try and see.

    Thanks so much for your help!
     
    bloodwolftico likes this.
  13. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    I
    I have found the fix!
    I needed to have composite collider for my tile map, it fixed the problem yay

    Thanks for all you help guys!
     
    bloodwolftico likes this.
  14. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    Hey! Glad to hear you found the solution! :)

    Personally, when using Tilemaps, I don't use Edge Collider or Composite (I actually tried once and it didnt work, tiles would fall down due to having a Rigidbody and couldn't change this via grav= 0), but the Tilemap Collider worked fine for me.

    Either way, happy you made it work! :)
     
  15. RushdiRamz

    RushdiRamz

    Joined:
    Aug 30, 2019
    Posts:
    8
    I believe u can change Rigidbody Body type to static, it makes everything not fall off :)
     
    bloodwolftico likes this.
  16. bloodwolftico

    bloodwolftico

    Joined:
    Nov 13, 2017
    Posts:
    100
    That's true :) I will give it a try later.