Unit not turing all way around

Hi,

I cannot get my unit to turn around in a smooth way. If I go with the default rotationspeed of 10f my unit doesn’t make it around to face the enemy before that action is complete but only about half the way. If I instead increase the rotationspeed to 30f my unit faces the enemy but not with a turning motion it more or less jumps to the new position. We might cover this in a later lection (I haven’t made it further). But if not how can I make the turn smoother?

This post should be under “shoot action” can I change it to go there?

I did not have to use a high value. Here is my exact code, which rotates smoothly. It covers 180degree rotation in the 0.1f seconds allotted to the “Aiming” phase in my testing. I hope this helps!

Vector3 aimingDirection = (targetUnit.GetWorldPosition() - unit.GetWorldPosition()).normalized;
    float rotateSpeed = 6f;
    transform.forward = Vector3.Lerp(transform.forward, aimingDirection, Time.deltaTime * rotateSpeed);

Are you trying to do a 180º degree turn? If so yes that is the one negative side effect of the Lerp method, since it interpolates a vector if you do a 180º turn the vector becomes smaller and smaller before suddenly flipping to the other side.

You can fix it by replacing Vector3.Lerp with Vector3.Slerp(); or instead of the transform.forward method use the transform.rotation method with Quaternion.Lerp();

1 Like

Hi,

I think the problem is the speed itself. If I try a rotation speed of 10f the unit doesn’t make it all the way around and if I do 30f it does. I noticed when doing a screen recording that 10f makes it further around when the CPU is busy, so I guess the question is how do I make it so the shoot action does not finish until the animation is done.

This is the code is use

float rotationSpeed = 10f;
Quaternion rotation = Quaternion.LookRotation(aimDir);
Quaternion current = transform.localRotation;
transform.localRotation = Quaternion.Slerp(current, rotation, Time.deltaTime * rotationSpeed);

And this code gives the same result

Vector3 aimDir = (targetUnit.GetWorldPosition() - unit.GetWorldPosition()).normalized;
float rotationSpeed = 10f;
transform.forward = Vector3.Lerp(transform.forward, aimDir, Time.deltaTime * rotationSpeed);

Shooting_Speed_gif

From the gif you posted the unit isn’t rotating at all, where are you running that code? It should be running on an Update, not just once.
If you want to test if the rotation has completed you can do a Vector3.Angle(transform.forward, aimDir); and use that instead of the timer (or in conjunction with the timer)

1 Like

Hi,

I\m running the code inside of the Next State Method. I dife the rotatioSpeed as a SerializeField for debugging purposes

 private void NextState()
    {
        switch (state)
        {
            case State.Aiming:
                Vector3 aimDir = (targetUnit.GetWorldPosition() - unit.GetWorldPosition()).normalized;
                //float rotationSpeed = 10f;
                //transform.forward = Vector3.Lerp(transform.forward, aimDir, Time.deltaTime * rotationSpeed);
                Quaternion rotation = Quaternion.LookRotation(aimDir);
                Quaternion current = transform.localRotation;
                transform.localRotation = Quaternion.Slerp(current, rotation, Time.deltaTime * rotationSpeed);
                state = State.Shooting;
                float shootingStateTime = 0.1f;
                stateTimer = shootingStateTime;
                break;
            case State.Shooting:
                if (canShootBullet)
                {
                    Shoot();
                    canShootBullet = false;
                }
                state = State.Cooloff;
                float coolOffStateTime = 0.5f;
                stateTimer = coolOffStateTime;
                break;
            case State.Cooloff:
                ActionComplete();
                break;
        }
    }

And i call the method from update

private void Update()
    {
        if (!isActive)
        {
            return;
        }

        stateTimer -= Time.deltaTime;
        switch (state)
        {
            case State.Aiming:
                break;
            case State.Shooting:
                break;
            case State.Cooloff:
                break;
        }

        if (stateTimer <= 0f)
        {
            NextState();
        }

    }

NextState() is only called once when the stateTimer elapses
For rotating you want to place that logic on the Update, that code needs to be called constantly to rotate the unit slightly every frame instead of just once.
Watch how I did it in the lecture or look at the GitLab commit.

2 Likes

Hi,

Thanks! I moved the code to update and now it works!

Tanks for a great course so far

/Ola

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms