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

Accelerate object with slider problem

Discussion in 'Scripting' started by cruising, Dec 10, 2016.

  1. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    Hello!

    Im working on a slider movement for objects, the slider and movement works for the object, but when you drag the slider to 100% or what ever value, the object also instantly accelerate with the slider value.

    I have AccelRate in the FixedUpdate, but it is ignored of some reason, the thing is when you move the slider,
    the object shall accelerate slowly untill it reach the value of the slider + with the rate AccelRate ofc, not instantly.

    Just like a car when you put the pedal to the metall, the car gain speed to the "rate" of your pedal level after some time.


    CODE:
    Code (CSharp):
    1. public Slider Impulseslider;
    2.  
    3.     public void ImpulseSlider(string sliderID)
    4.     {
    5.         CurSpeed = Impulseslider.value;
    6.     }
    7.  
    8.     void FixedUpdate ()
    9.     {
    10.         Slidervalue = CurSpeed;
    11.  
    12.  
    13.         if (Impulseslider.value > 0)
    14.         {
    15.             Slidervalue = Mathf.Min(Slidervalue + AccelRate * Time.deltaTime, MaxSpeed);
    16.             GetComponent<Rigidbody>().velocity = transform.forward * CurSpeed;
    17.             impulse_active = true;
    18.         } else {        
    19.             Slidervalue = Mathf.Max(Slidervalue - DeAccel * Time.deltaTime * 1.5f, 0);
    20.             GetComponent<Rigidbody>().velocity = transform.forward * CurSpeed;
    21.             impulse_active = false;
    22.         }
    23.     }
    24. }
     
  2. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    First, you should get in the habit of caching the rigidbody, as GetComponent<RigidBody> is a somewhat expensive call.

    The reason it doesn't accelerate is that you are setting the speed to CurSpeed, which I assume is set by the slider in the ImpulseSlider method. All the math you use to update Slidervalue doesn't seem to affect CurSpeed, and so is not used to set the speed at all.

    Finally, I'd recommend you rather use AddForce instead of doing this calculation yourself, should be easier and probably more performant.
     
  3. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    I forgot to post this

    Code (CSharp):
    1.    
    2. public Component Ship;
    3. void Start()
    4.     {
    5.         Ship = GetComponent<Rigidbody>();
    6.     }
    The ship do accelerate from 0-100, its just that if you instantly drag the slider up to 50, the object also accelerate to 50 instead of accelerate slowly.
    Could you please post a example for AddForce?
     
  4. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    In your FixedUpdate, you'd do something like this

    Code (csharp):
    1. Ship.AddForce(transform.forward * AccelRate, ForceMode.Acceleration);
    You then also want to limit the speed, as you have in your code.

    Code (csharp):
    1. if (Ship.velocity.sqrMagnitude > maxSpeedSqr)
    2. {
    3.     Ship.velocity = Ship.velocity.normalized * maxSpeed;
    4. }
    maxSpeedSqr should here be the square of your wanted max speed. We use it together with sqrMagnitude in the if check, because computing square roots is a slow operation.
     
  5. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    To elaborate, I hope I'm not over-complicating things here, but while this task seems deceivingly simple it is actually part of a separate field of study in engineering called control systems engineering. To do this properly, what you need is something called a PID controller.

    Take a look at this forum thread for an implementation you could try to use.
     
  6. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    Ok this works as it should do, but having problem to slow down the ship, i know its the else that isnt correct. But im not sure about how i should do it

    Code (CSharp):
    1.     void FixedUpdate ()
    2.     {
    3.         Slidervalue = CurentSpeed;
    4.  
    5.         if (CurentSpeed > MaxSpeed)
    6.             CurentSpeed = MaxSpeed;
    7.        
    8.  
    9.         if (Impulseslider.value > 0)
    10.         {
    11.             Ship.AddForce(transform.forward * CurentSpeed * AccelerateRate, ForceMode.Acceleration);
    12.             impulse_active = true;
    13.  
    14.         } else {        
    15.  
    16.             Ship.AddForce(transform.forward * CurentSpeed * Deccelerate, ForceMode.Acceleration);
    17.             impulse_active = false;
    18.         }
    19.  
    20.         if (Input.GetAxis("Turn") > 0)
    21.         {
    22.             //GetComponent<Rigidbody>().MoveRotation = transform.forward * turnspeed;
    23.         }
    24.     }
    25. }
    26.  
     
  7. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Deccelerate needs to be a negative value in this case, or you can just put -Deccelerate.
     
  8. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    That didnt work, i tried both ways and it keeps the speed it had when i turn the slider to a lower level

    Code (CSharp):
    1. Ship.AddForce(transform.forward * CurentSpeed - Decacelerate, ForceMode.Acceleration);
    2.  
    3. Ship.AddForce(transform.forward * CurentSpeed * -Decacelerate, ForceMode.Acceleration);
     
  9. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    You probably need a much larger decelerate value then, as you need to overcome the forward momentum.
     
  10. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    Doesnt matter if i have value 10000, it still dont slow down or stop of some reason
     
  11. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Are you sure the slider actually goes negative?
    Code (CSharp):
    1. Debug.Log(Impulseslider.value);
     
  12. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    Yes i have the value of the slider shown in the inspector, it goes up and down with the on-screen slider + impulse_active =true; bool is also working.

     
  13. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    Take a look at the attached example that I threw together. It uses a simple PD controller to smooth out the forces, adjust the pk and pd variables to tune the controller.

    Hope this helps?
     

    Attached Files:

  14. cruising

    cruising

    Joined:
    Nov 22, 2013
    Posts:
    329
    Idk if im doing something wrong or if it is the script, if i change the max speed to 60 as i use as standard, the object goes instantly to the end of the universe and unity getting a error and pausing, also the slider goes from the left side screen all the way to the right side.
    ERROR
    Code (CSharp):
    1. rigidbody.force assign attempt for 'Romulan_BOP' is not valid. Input force is { -0.000000, -0.000000, -Infinity }.
    2. UnityEngine.Rigidbody:AddForce(Vector3, ForceMode)
    But i did this earlier today and this works as i want it to do, my next step is to make it turn in a curve with banking, and so far i have failed to do so.

    Code (CSharp):
    1.     void FixedUpdate ()
    2.     {
    3.         CurrentAccelerate = Ship.velocity.magnitude;
    4.         ImpulsSlidervalue = CurentSpeed;
    5.  
    6.  
    7.         if (CurentSpeed > MaxSpeed)
    8.             CurentSpeed = MaxSpeed;  
    9.  
    10.         if (Impulseslider.value > 0)
    11.         {
    12.             targetPosition += transform.forward * CurentSpeed * Time.deltaTime;
    13.             impulse_active = true;
    14.  
    15.         } else {
    16.             targetPosition += transform.forward * CurentSpeed * Time.deltaTime;
    17.             impulse_active = false;
    18.         }
    19.  
    20.         if (Input.GetAxis("Turn") != 0)
    21.         {
    22.             //targetPosition += transform.right * Input.GetAxisRaw("Horizontal") * CurentSpeed * Time.deltaTime;
    23.         }
    24.  
    25.         var currentPosition = SgtHelper.Dampen3(transform.position, targetPosition, AccelerateRate, Time.deltaTime, 0.1f);
    26.         SgtHelper.SetPosition(transform, currentPosition);
    27.         }
    28.     }
    29.