How can i slow down a moving gameobject from a specific distance ?

if (Physics.Raycast(transform.position, baseTarget.position, out hit, maxDistance))
            {
                transform.rotation = Quaternion.identity;
                _rigidbody.useGravity = false;
            }
            else
            {
                //transform.position += transform.forward * Time.deltaTime * movementspeed;
                float distance = Vector3.Distance(transform.position, baseTarget.position);
                var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
                var str = Mathf.Min(.5f * Time.deltaTime, 1);
                transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);

                if (distance <= 700)
                {
                    transform.position = Vector3.SmoothDamp(transform.position, baseTarget.position, )
                }
            }

What i want to do is when the gameobject distance is 700 from the targetBase start slow down.
And keep slowdown according to the distance don’t slow down at once from fro example from speed 100 to 10 but do it in some times according to the speed and distance. If distance is 700 and speed is 100 then slow down to 90 then at distance 600 to 80…something like that.

Then when it’s above the targetBase it will stop once the Raycast will detect the transform is above the targetBase.

Not sure how to make the slow down part.
Thought using Vector3.SmoothDamp for the slow down but not sure how to use it and if it’s the right way.

Not sure exactly what you’re doing there, i.e., who is controlling the object, but here are some thoughts:

So let’s say: (these are all floating point variables)

We have a minimum speed of MinSpeed (never go slower)
We have define a nominal speed of NormalSpeed
We have defined our “start slowing down” distance as Range
We have calculated distance to the base as Distance

  • set a temporary variable called Speed equal to NormalSpeed

  • if Distance > Range then go to the MOVE portion below

  • else: (you must be within range, so how much to slow down?)

float fractionWithinRange = Distance / Range;

The above variable will be 1.0f at the moment you come within range (Distance equals Range), and 0.0f when you reach the goal (Distance equals zero)

Now recalculate speed, and prevent getting too slow:

Speed = fractionWithinRange * NormalSpeed;
if (Speed < MinSpeed) Speed = MinSpeed;

Now onto the MOVE portion:

Vector3 ToGoal = goal.transform.position - you.transform.position;
transform.position += ToGoal.normalized * Speed * Time.deltaTime;

I’m controlling the spaceship but for the landing:

I’m trying to make automatic landing situation for my spaceship.
This is the complete script:

using UnityEngine;
using System.Collections;

public class ControlShip : MonoBehaviour {

    public int rotationSpeed = 75;
    public int movementspeed = 10;
    public int thrust = 10;
    public float RotationSpeed = 5;
    public float maxDistance = 100;

    private bool isPKeyDown = false;
    private float acceleration = .0f;
    private Vector3 previousPosition = Vector3.zero;
    private Rigidbody _rigidbody;
    private bool landing = false;
    private Vector3 originPosition;
    private Vector3 lastPosition;
    private const float minDistance = 0.2f;
    private Transform baseTarget;
    private RaycastHit hit;

    // Use this for initialization
    void Start () {
        baseTarget = GameObject.Find("Base").transform;
        originPosition = transform.position;
        _rigidbody = GetComponent<Rigidbody>();
        Debug.Log("Acc Speed: " + thrust);
    }

    // Update is called once per frame
    void Update()
    {
        if (landing == false)
        {
            var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
            transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
            transform.position += transform.forward * Time.deltaTime * movementspeed;

            if (Input.GetKey(KeyCode.Z))
                transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);

            if (Input.GetKey(KeyCode.R))
                transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);

            if (Input.GetKey(KeyCode.P))
            {
                isPKeyDown = Input.GetKey(KeyCode.P);
                float distance = Vector3.Distance(previousPosition, transform.position);
                acceleration = distance / Mathf.Pow(Time.deltaTime, 2);

                previousPosition = transform.position;
                _rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
            }
        }
        else
        {
            if (Physics.Raycast(transform.position, baseTarget.position, out hit, maxDistance))
            {
                transform.rotation = Quaternion.identity;
                _rigidbody.useGravity = false;
            }
            else
            {
                //transform.position += transform.forward * Time.deltaTime * movementspeed;
                float distance = Vector3.Distance(transform.position, baseTarget.position);
                var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
                var str = Mathf.Min(.5f * Time.deltaTime, 1);
                transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);

                if (distance <= 700)
                {
                    transform.position = Vector3.SmoothDamp(transform.position, baseTarget.position, )
                }
            }
        }

        if (landed == true)
            TakeOff();

        if (Input.GetKey(KeyCode.L))
        {
            // Automatic landing
            landing = true;
            lastPosition = transform.position;
        }
    }

    void OnTriggerEnter(Collider other)
    {
        if (landing == true && other.gameObject.name == "Base")
        {
            StartCoroutine(Landed());
        }
    }

    bool landed = false;
    IEnumerator Landed()
    {
        yield return new WaitForSeconds(5);
        Debug.Log("Landed");
        landed = true;
    }

    private void TakeOff()
    {
        if (transform.position != originPosition)
        {
            _rigidbody.AddForce(transform.up * 10);
        }

        if ((transform.position - originPosition).sqrMagnitude <= (1f * 1f))
        {
            landed = false;
            _rigidbody.useGravity = false;
        }
    }

    void OnGUI()
    {
        if (isPKeyDown)
        {
            GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
        }
    }
}

When i click the L key it should start landing automatic.
The automatic landing is where ever the ship is now it will rotate to the baseTarget direction move there and will start landing slowly.

The idea is to slow down while getting close to the baseTarget once the spaceship(transform) is above the baseTarget using Raycast start moving down the spaceship slowly vertical and land.

This is the landing part: Should be the landing part:

if (Physics.Raycast(transform.position, baseTarget.position, out hit, maxDistance))
            {
                transform.rotation = Quaternion.identity;
                _rigidbody.useGravity = false;
            }
            else
            {
                //transform.position += transform.forward * Time.deltaTime * movementspeed;
                float distance = Vector3.Distance(transform.position, baseTarget.position);
                var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
                var str = Mathf.Min(.5f * Time.deltaTime, 1);
                transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);

                if (distance <= 700)
                {
                    transform.position = Vector3.SmoothDamp(transform.position, baseTarget.position, )
                }
            }

I’m trying to use Vector3SmoothDamp for the slow down but not sure if it’s right and how to use it.
Before that i used this line:

transform.position += transform.forward * Time.deltaTime * movementspeed;

And then it was moving the spaceship facing the baseTarget and when above it the spaceship was getting ready for landing but it’s not working good yet.

It just takes some math in order to get speed based on distance.

Here is the script I put together. Granted your script is doing alot more at once, but you can integrate this into the rest of your code.

public class moveSlowDown : MonoBehaviour {

    public float minSpeed;
    public float maxSpeed;
    public Transform target;
    public float speed;
    public float slowDownDistance;
    // Use this for initialization
    void Start () {
        speed = maxSpeed;
    }
   
    // Update is called once per frame
    void Update () {

        transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);

        float distance = Vector3.Distance(transform.position, target.position);

        if(distance < slowDownDistance)
        {
            float percentageOfMax = Vector3.Distance(transform.position, target.position) / slowDownDistance;

            speed = Mathf.MoveTowards(minSpeed, maxSpeed, percentageOfMax * maxSpeed);

           

        }

    }
}

Google has alot of answers under “unity 3d slower when closer”

I found this answer to be the simplest and how I got the idea for my script.

1 Like