Unity3D/Script

timeScale Lerp for Unity 3D: Custom Time Manager

blueasa 2015. 3. 9. 23:24

timeScale Lerp – Custom Time Manager

By now I need a timeScale Lerp and this need to be Time.deltaTime independent so, for anyone who needs this too, here’s what I’ve got (C#). You can also use it to create slow motion effects and control the play /pause of your game (assuming that you are using a Time.timeScale dependent approach):

You cal also get this code at GitHub

/// <summary>
/// Time Manager.
/// Time.deltaTime independent Time.timeScale Lerp.
/// Author: Fabio Paes Pedro
/// </summary>
///
/// 

using UnityEngine;
using System.Collections;

public class CustomTimeManager : MonoBehaviour
{
    /// <summary>
    /// CustomTimeManager is Paused or not
    /// </summary>
    [SerializeField]
    private bool _isPaused = false;
    /// <summary>
    /// CustomTimeManager is Fading (from _minScale to _scale or vice-versa)
    /// </summary>
    [SerializeField]
    private bool _isFading = false;
    /// <summary>
    /// CustomTimeManager will pause after fading (is going from _scale to _minScale)
    /// </summary>
    [SerializeField]
    private bool _willPause = false;

    [SerializeField]
    private float _scale = 1f;
    private float _fadeToScaleDifference = 0f;
    private float _scaleToFade = 0f;
    [SerializeField]
    private float _deltaTime = 0f;
    private float _lastTime = 0f;
    private float _maxScale = 3f;
    private float _minScale = 0f;
    private bool _fadeToScaleIsGreater = false;



    #region PseudoSingleton
    private static CustomTimeManager _instance;
    public static CustomTimeManager Instance
    {
        get
        {
            return _instance;
        }
    }
    void Awake()
    {
        if (_instance != null) Debug.LogError("There's another instance of " + this + " already");
        _instance = this;
    }
    void OnDestroy()
    {
        _instance = null;
    }
    #endregion


    void Start()
    {
        Scale = Time.timeScale;
        StartCoroutine("UpdateDeltaTime");
    }

    public bool WillPause
    {
        get
        {
            return _willPause;
        }
    }

    public bool IsFading
    {
        get
        {
            return _isFading;
        }
    }

    public bool IsPaused
    {
        get
        {
            return _isPaused;
        }
    }


    /// <summary>
    /// Time.timeScale independent deltaTime
    /// </summary>
    /// <value>
    /// time.timeScale independent Delta Time
    /// </value>
    public float DeltaTime
    {
        get
        {
            return _deltaTime;
        }
    }

    /// <summary>
    /// Getter and Setter for the CustomTimeManager Scale (time.timeScale). This will set IsPaused to true automatically if the scale == 0f
    /// </summary>
    /// <value>
    /// Scale (Time.timeScale)
    /// </value>
    public float Scale
    {
        get
        {
            return _scale;
        }
        set
        {
            _scale = value;
            _scale = _scale < _minScale ? _minScale : _scale > _maxScale ? _maxScale : _scale;
            Time.timeScale = _scale;
            _isPaused = _scale <= 0.001f;
            if (_isPaused)
            {
                _scale = 0f;
                _willPause = false;
            }
        }
    }

    /// <summary>
    /// Pause toggle (Changes the "IsPaused" flag from true to false and vice-versa)
    /// </summary>
    /// </param>
    /// <param name='time'>
    /// Time until Pause or Play
    /// </param>
    /// <param name='playScale'>
    /// Play scale.
    /// </param>
    public void TogglePause(float time = 0f, float playScale = -1f)
    {
        StopStepper();
        // WillPause == true means that a "Pause" was already called: this will make "WillPause" change to false and call "Play" function. 
        // Else just toggle.
        _willPause = _willPause == true ? false : !_isPaused;
        if (_willPause)
        {
            Pause(time);
        }
        else
        {
            Play(time, playScale);
        }
    }

    void StopStepper()
    {
        _instance.StopCoroutine("FadeStepper");
    }

    /// <summary>
    /// CustomTimeManager Pause
    /// </summary>
    /// <param name='time'>Fading time until Time.timeScale == 0f</param>
    public void Pause(float time = 0f)
    {
        if (Mathf.Approximately(time, 0f))
        {
            _willPause = false;
            _instance.StopCoroutine("FadeStepper");
            Scale = 0f;
        }
        else
        {
            _willPause = true;
            FadeTo(0f, time);
        }
    }

    /// <summary>
    /// CustomTimeManager Play 
    /// </summary>
    /// <param name='time'>
    /// Fading time until Time.timeScale == scale param
    /// </param>
    /// <param name='scale'>
    /// Final scale for Time.timeScale
    /// </param>
    public void Play(float time = 0f, float scale = 1f)
    {
        if (Mathf.Approximately(time, 0f))
        {
            _instance.StopCoroutine("FadeStepper");
            Scale = scale;
        }
        else
        {
            FadeTo(scale, time);
        }
    }

    /// <summary>
    /// CustomTimeManager Scale Fading.
    /// </summary>
    /// <param name='scale'>
    /// The final Time.timeScale
    /// </param>
    /// <param name='time'>
    /// The transition time to reach the desired scale
    /// </param>
    public void FadeTo(float scale, float time)
    {
        _instance.StopCoroutine("FadeStepper");
        _scaleToFade = scale;
        _fadeToScaleDifference = scale - _scale;
        _fadeToScaleIsGreater = _fadeToScaleDifference > 0f;
        float scalePerFrame = _fadeToScaleDifference / time;
        _instance.StartCoroutine("FadeStepper", scalePerFrame);
    }

    /// <summary>
    /// Coroutine to fade the Unity's timeScale
    /// </summary>
    IEnumerator FadeStepper(float scalePerFrame)
    {
        bool achieved = false;
        _isFading = true;
        while (achieved == false)
        {
            Scale += scalePerFrame * _deltaTime;
            if (_fadeToScaleIsGreater)
            {
                achieved = _scale >= _scaleToFade;
            }
            else
            {
                achieved = _scale <= _scaleToFade;
            }
            yield return null;
        }
        Scale = _scaleToFade;
        _isFading = false;
        _willPause = false;
    }

    /// <summary>
    /// Updating our internal _deltaTime
    /// </summary>
    IEnumerator UpdateDeltaTime()
    {
        while (true)
        {
            float timeSinceStartup = Time.realtimeSinceStartup;
            _deltaTime = timeSinceStartup - _lastTime;
            _lastTime = timeSinceStartup;
            yield return null;
        }
    }

}



출처 : http://fliperamma.com/timescale-lerp-custom-time-manager/

반응형