0

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.

Daniel Lip
  • 1,747
  • 3
  • 34
  • 75
  • 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? – DMGregory Nov 07 '17 at 17:24
  • @DMGregory "close enough" is fine. I updated my question trying to explain what i need. – Daniel Lip Nov 07 '17 at 19:15

1 Answers1

1

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.

LifGwaethrakindo
  • 1,421
  • 2
  • 14
  • 26
  • 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. – Daniel Lip Nov 07 '17 at 17:20
  • 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. – LifGwaethrakindo Nov 07 '17 at 17:29
  • 2
    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. – DMGregory Nov 07 '17 at 17:43
  • Of course, and I actually use coroutines to handle such things. But it was for the sake of the quick example. – LifGwaethrakindo Nov 07 '17 at 17:51
  • 1
    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. – Ed Marty Nov 07 '17 at 18:58