0
\$\begingroup\$

At the top of script:

public Quaternion _lookRotation;

In Update:

void Update()
{
 transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, 
 Time.deltaTime * RotationSpeed);
}

I want to know when the transform rotation ended and is at _lookRotation Maybe using some flag ?

This is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;

public class FadeScript : MonoBehaviour
{
    public UnityStandardAssets.ImageEffects.Blur blur;
    public UnityStandardAssets.ImageEffects.BlurOptimized blurOptimized;
    public FirstPersonController fpc;
    public float fadeDuration = 5;
    public float startAcceleration = 0.6f;
    public float endAcceleration = 0.6f;
    public float maxSpeed = 1.0f;
    public float rotationSpeed = 0.6f;

    private Material material;
    private float targetAlpha = 0;
    private float lerpParam;
    private float startAlpha = 1;
    private bool rotated = false;
    private Quaternion clampedTargetRotation;

    void Start()
    {
        material = GetComponent<Renderer>().material;
        SetMaterialAlpha(1);

        fpc.enabled = false;
    }

    void Update()
    {
        lerpParam += Time.deltaTime;

        float alpha = Mathf.Lerp(startAlpha, targetAlpha, lerpParam / fadeDuration);
        SetMaterialAlpha(alpha);

        if (alpha == 0)
        {
            fpc.enabled = true;

            if (rotated == false)
            {
                fpc.GetComponent<FirstPersonController>().enabled = false;
                rotationSpeed += Mathf.Clamp(rotationSpeed + startAcceleration * Time.deltaTime, 0, maxSpeed);
            }

            if (fpc.transform.localRotation == Quaternion.Euler(0,0,0))
            {
                fpc.GetComponent<FirstPersonController>().enabled = true;
                rotationSpeed = Mathf.Clamp(rotationSpeed - endAcceleration * Time.deltaTime, 0, maxSpeed);
                blur.enabled = false;
                blurOptimized.enabled = false;

                rotated = true;
            }

            clampedTargetRotation = Quaternion.RotateTowards(fpc.transform.localRotation, Quaternion.Euler(0, 0, 0), rotationSpeed * Time.deltaTime);
            fpc.transform.localRotation = clampedTargetRotation;
        }
    }

    public void FadeTo(float alpha, float duration)
    {
        startAlpha = material.color.a;
        targetAlpha = alpha;
        fadeDuration = duration;
        lerpParam = 0;
    }

    private void SetMaterialAlpha(float alpha)
    {
        Color color = material.color;
        color.a = alpha;
        material.color = color;
    }
}

What i want in the rotation part is to start the rotation slowly and then accelerate a bit and then in the end when it's getting "close enough" to 0,0,0 so start accelerate down until complete stop. Complete stop not must be at 0,0,0 but close to it. Th way i'm doing it now is wrong i'm not using the t 0/1 solution and not courtine.

The rotation now in my script is almost working as i want. It start slowly and accelerate but in the end it stop at once without smoothly accelerate down.

\$\endgroup\$
2
  • \$\begingroup\$ There are two common ways to use Lerp / Slerp. One is linear, and completes when the interpolation weight hits 1. The other, the one you're using here, is an exponential ease-in, and if you had infinite-precision numbers it would never actually reach its destination, just get closer and closer and closer down to infinitesimal scales. Would saying the rotation is "complete" once it gets "close enough" be suitable for your case? Or do you need the rotation to finish exactly in some set amount of time? \$\endgroup\$
    – DMGregory
    Nov 7, 2017 at 17:24
  • \$\begingroup\$ @DMGregory "close enough" is fine. I updated my question trying to explain what i need. \$\endgroup\$
    – Daniel Lip
    Nov 7, 2017 at 19:15

1 Answer 1

1
\$\begingroup\$

All Lerp functions (Mathf, Vector3, Quaternion) utilize the same base formula:

P = P0 + (t * (P1 - P0)), 0 < t < 1

Which means that the interpolation depends on t, a normalized value between 0 and 1. So, what you can do, is interpolate your rotation with a t variable as reference, and "End" your rotation once t reaches 1.

Quick example:

    [SerializeField] Quaternion targetRotation;    /// <summary>Rotation you want to achieve.</summary>
    [SerializeField] private float s;       /// <summary>Rotation duration.</summary>
    private Quaternion initialRotation;     /// <summary>Your GameObject's initial rotation.</summary>
    private float t;                        /// <summary>Your 't' reference.</summary>

    void Awake()
    {
        initialRotation = transform.rotation;
    }

    void Update()
    {
        if(t < 1.0f)
        {
            transform.rotation = Quaternion.Lerp(initialRotation, targetRotation, t);
            t += (Time.deltaTime / s); /// Each 60 frames [optimally] t reaches 1, divided by your duration, it will reach 1 on 'x' seconds.
        }
        else /// Your rotation ends here:
        { /// reset 't' [if you please], and reset 'initialRotation' 
            initialRotation = transform.rotation;
        }

    }

Hope it gives you a foundation basis to solve your problem.

\$\endgroup\$
5
  • \$\begingroup\$ One question you didnn't rest the t at the else only the initialRotation. Should i reset also the t ? I didn't understand the [if you please] part. \$\endgroup\$
    – Daniel Lip
    Nov 7, 2017 at 17:20
  • \$\begingroup\$ Sure, I didn't reset 't' there, because your issue was to stop the rotation, so you don't need 't' anymore, if I reseted it, it would Lerp again until 't' reaches 1 again. I mean, that must be something that depends on your goals. \$\endgroup\$ Nov 7, 2017 at 17:29
  • 2
    \$\begingroup\$ Since this Update eventually hits a point where it does no further work, it might as well be a coroutine that can just end rather than continuing to re-check each frame. \$\endgroup\$
    – DMGregory
    Nov 7, 2017 at 17:43
  • \$\begingroup\$ Of course, and I actually use coroutines to handle such things. But it was for the sake of the quick example. \$\endgroup\$ Nov 7, 2017 at 17:51
  • 1
    \$\begingroup\$ You may want to have the targetRotation be a Vector3 and convert it to an Euler Quaternion in Awake so that the inspector can be simplified to just show the same sort of rotation assignment as in the Transform component. \$\endgroup\$
    – Ed Marty
    Nov 7, 2017 at 18:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .