Search Unity

How to make character change direction when it can't move forward?

Discussion in 'Physics' started by KristoE, Apr 11, 2016.

  1. KristoE

    KristoE

    Joined:
    Oct 13, 2012
    Posts:
    90
    The result I am after is that the character can normally push objects around, but when it is pushing an object against a wall, thus not moving at all, it would turn around and walk the other way. Is there a good way of doing that?

    Right now I'm thinking of actually keeping account of the characters position for the last couple of updates and add up the magnitude of the movement during these updates. Then if the magnitude of movement is below a certain threshold the character would turn around. This would probably work, but seems to be a very clunky way of doing it.

    There surely must be a better way of doing it.

    Thanks in advance.
     
  2. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    The "magnitude of movement" you're referring to is velocity. Does either the character or pushed object have a rigidbody? If so, check for the Rigidbody.velocity.magnitude so you don't need to calculate it yourself. If there are no Rigidbody's present, then calculating velocity is sound; for a close approximation, subtract the current position from last frame's position and get the magnitude of the resultant vector, and divide it by Time.deltaTime.
     
  3. KristoE

    KristoE

    Joined:
    Oct 13, 2012
    Posts:
    90
    Hey, thanks for the answer, but my problem is that I force-set the velocity in script and just plainly turning around when velocity's magnitude is 0 or very close to it will cause some issues. For example when lets say the character gets thrown straight into the air, when he reaches the maximum height velocity will be 0, yet I don't want the character to turn around on that occasion.

    Currently I have something like this set up
    Code (CSharp):
    1. void CheckForStandStill()
    2.     {
    3.         if (moveSpeed != 0)
    4.         {
    5.             magnitude *= 0.9f;
    6.             magnitude += Vector2.Distance(transform.position,lastPos);
    7.  
    8.             if(magnitude<0.01f)
    9.             {
    10.                 magnitude = 1f;
    11.                 moveSpeed = -moveSpeed;
    12.             }
    13.  
    14.             lastPos = transform.position;
    15.         }
    16.     }
    moveSpeed is the horizontal velocity that is forced on the character on each fixed update when it is touching the ground.
    magnitude is a float value that I use as kind of a threshold for when it gets too low, meaning the character hasn't moved too much for a while, I will turn the character around.
    The function gets called every FixedUpdate.

    It is currently working well and I have had no issues, but I was wondering if maybe there is a better universally used way of doing something like that.
     
  4. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Check for when the character is pushing something as well as the velocity. If it's pushing and the velocity is 0, then reverse the direction. Probably the easiest way to do this is to just check to see if it's colliding with the pushable object.

    Also, Rigidbody.velocity is a Vector3. If you are worried about false triggers for things like being launched into the air, then only check velocity.x, not just the magnitude of velocity; this way only horizontal movement is checked.

    That said, if your code works and doens't have bugs, then you could keep it the same.

    Such a small amount of logic won't have any performance impact, but it is a little hard to see what the code is supposed to do at a glance, which is a disadvantage under certain circumstances. Also, if you have to add more logic based on velocity (which is likely) then you'll probably want to just use
    Rigidbody.velocity since it's more accurate and less complex.