Search Unity

Smoothly decrease/increase speed when on trigger object

Discussion in 'Physics' started by fronzu, Nov 10, 2016.

  1. fronzu

    fronzu

    Joined:
    Nov 1, 2016
    Posts:
    24
    Hi everybody,
    what I want to do is gradually decrease the speed of my Player (a moving disc) as it moves on a Path, and gradually increase it when the Player exits the Path.
    This is a mobile app and I'm using the acceleremeter to move the Player.

    I tried using the Math.Smoothstep function but the result is that the speed decrease or increase without smoothing.

    Here is the script of my Player object:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MovePlayer : MonoBehaviour {
    5.  
    6.     // Speed multiplier
    7.     public float speed;
    8.  
    9.     // FixedUpdate for physical objects
    10.     void FixedUpdate () {
    11.         transform.Translate (
    12.             Input.acceleration.x * Time.deltaTime * speed,
    13.             Input.acceleration.y * Time.deltaTime * speed,
    14.             0);
    15.     }
    16.  
    17.     // Collision control (requires RigidBody)
    18.     void OnCollisionEnter2D(Collision2D obj){
    19.         if (obj.gameObject.CompareTag ("Wall")) {
    20.             Debug.Log ("Collision: Wall");
    21.         }
    22.     }
    23.  
    24.     // Player enters path
    25.     void OnTriggerEnter2D(Collider2D obj){
    26.         if (obj.gameObject.CompareTag ("Path")) {
    27.             Debug.Log ("Trigger Enter: Path");
    28.             speed = Mathf.SmoothStep (speed, speed / 2, 2);
    29.         }
    30.     }
    31.  
    32.     // Player exits path
    33.     void OnTriggerExit2D(Collider2D obj){
    34.         if (obj.gameObject.CompareTag ("Path")) {
    35.             Debug.Log ("Trigger Exit: Path");
    36.             speed = Mathf.SmoothStep (speed, speed * 2, 2);
    37.         }
    38.     }
    39. }
    40.  
    Thanks in advance and have a good day!
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    That's because you're using SmoothStep erroneously. The calculation is done a single time on the trigger events and it doesn't consider the time, thus the instant change.

    The correct usage is at FixedUpdate, and it should be something like this:

    Code (CSharp):
    1. currentSpeed = Mathf.SmoothStep(currentStep, targetSpeed, 2 * Time.deltaTime);
    Thus, you would set targetSpeed at the triggers, then calculate and apply the new currentSpeed value. The "2" value defines how fast the transition is. You may want to expose it as public property as well for experimenting with the value.
     
  3. fronzu

    fronzu

    Joined:
    Nov 1, 2016
    Posts:
    24
    Thank you very much for the answer, now it works!

    If can be helpful, here is the working code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MovePlayer : MonoBehaviour {
    5.  
    6.     public float maxSpeed; // Maximum speed reachable
    7.     public float minSpeed; // Minimum speed reachable
    8.     public float duration; // Duration of the speed transition
    9.  
    10.     private float targetSpeed;
    11.     private float currentSpeed;
    12.  
    13.     void Start(){
    14.         // Setting the starting speed parameters
    15.         currentSpeed = targetSpeed = maxSpeed;
    16.     }
    17.      
    18.     void FixedUpdate () {
    19.         transform.Translate (
    20.             Input.acceleration.x * Time.deltaTime * currentSpeed,
    21.             Input.acceleration.y * Time.deltaTime * currentSpeed,
    22.             0);
    23.  
    24.         // Smooting the currentSpeed to the targetSpeed
    25.         currentSpeed = Mathf.SmoothStep (currentSpeed, targetSpeed, duration * Time.deltaTime);
    26.         Debug.Log ("Speed: " + currentSpeed);
    27.     }
    28.  
    29.     // Player enters path
    30.     void OnTriggerEnter2D(Collider2D other) {
    31.         if (other.gameObject.CompareTag ("Path")) {
    32.             Debug.Log ("Trigger Enter: Path");
    33.             targetSpeed = minSpeed; // Setting the new speed to the minimum
    34.         }
    35.     }
    36.  
    37.     // Player exits path
    38.     void OnTriggerExit2D(Collider2D other){
    39.         if (other.gameObject.CompareTag ("Path")) {
    40.             Debug.Log ("Trigger Exit: Path");
    41.             targetSpeed = maxSpeed; // Setting the new speed to the maximum
    42.         }
    43.     }
    44.  
    45.     // Collision control (requires RigidBody)
    46.     void OnCollisionEnter2D(Collision2D obj){
    47.         if (obj.gameObject.CompareTag ("Wall")) {
    48.             Debug.Log ("Collision: Wall");
    49.         }
    50.     }
    51. }
    It is not the most efficient way to do that because the Mathf.SmoothStep function is called even when it is not needed, but I think a simple check could solve the problem.
     
    Last edited: Nov 10, 2016
    DonPuno, WhiteGfx and Edy like this.