Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Smoothly change the player's speed when he leaves the zone

Discussion in 'Scripting' started by R0tmayer, Jun 18, 2021.

  1. R0tmayer

    R0tmayer

    Joined:
    Mar 13, 2021
    Posts:
    12
    I'm trying to make special zone located on ground that accelerates the player, entering which the player's speed increases. When he gets out of it, the speed smoothly returns to the original. But now, when the player leaves the zone, the speed instantly becomes the original. Don't know how to realize it. Please help:)

    My code:

    PlayerMovement:


    Code (CSharp):
    1. [SerializeField] private Rigidbody _rigidoby;
    2.  
    3.         public bool inZone = false;
    4.  
    5.         private void Update()
    6.         {
    7.             if (inZone == false)
    8.             {
    9.                 _rigidoby.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 500;
    10.             }
    11.         }
    SpecialZone:


    Code (CSharp):
    1. private Vector3 _cachedVelocity;
    2.         private Rigidbody _collisionRigidbody;
    3.         [SerializeField] private PlayerMovement _player;
    4.  
    5.         private void OnTriggerStay(Collider other)
    6.         {
    7.             _player.inZone = true;
    8.  
    9.             if (_collisionRigidbody == null)
    10.             {
    11.                 _collisionRigidbody = other.GetComponent<Rigidbody>();
    12.                 _cachedVelocity = _collisionRigidbody.velocity;
    13.             }
    14.  
    15.             _collisionRigidbody.velocity = new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0, Input.GetAxis("Vertical") * Time.deltaTime) * 1000;
    16.         }
    17.  
    18.         private void OnTriggerExit(Collider other)
    19.         {
    20.             _collisionRigidbody.velocity = _cachedVelocity;
    21.             _player.inZone = false;
    22.         }
     
  2. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    277
    What you are doing here, is setting a physics objects velocity directly, which isn't that great an idea. You basicly bypass the entire physics engine. Look into the AddForce method.

    What you'd want to do in this case, is determine a Vector3 direction, multiply that by a speed, and then use that final Vector3 as the argument for AddForce. That way the physics engine will take care of accelleration and such, taking into account drag and friction. If you set velocity directly, you bypass all of this. It is about as smart as ignoring gravity in real life, so please don't unless bypassing physics is your explicit goal.

    Next up is to change the speed. If you make that speed multiplier I talked about a public property of the player, you can change it OnTriggerStay / OnTriggerExit. You'd have to check if the "other" collider actually IS the player, which you can do in many ways. The easiest might be to do a GetComponent<YouPlayerClass> call on the "other" object, and then do a null check to see if we indeed collided with a YouPlayerClass.

    And if we have, we can set the speed modifier and because you used AddForce instead of setting velocity directly, drag and friction are taken into account making this a whole lot smoother. You can go af far as you want with this, like... instead of setting the speed modifier to a fixed value, you could use a Lerp function to smooth that out as well. But I'd stick to getting the basics working first, and then iterating upon it further if your game turns out to require stacking speed boosts or something like that.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,514
    This is my go-to pattern for any smoothly-changing quantity, such as changing your speed to a new higher or lower speed:

    Smoothing movement between any two particular values:

    https://forum.unity.com/threads/beginner-need-help-with-smoothdamp.988959/#post-6430100

    You have currentQuantity and desiredQuantity.
    - only set desiredQuantity
    - the code always moves currentQuantity towards desiredQuantity
    - read currentQuantity for the smoothed value

    Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

    The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4