处理 Time.timeScale onChange 事件

Handle Time.timeScale onChange event

我刚开始使用 Unity,我需要(在游戏暂停之前)触发 avent。当 Time.timeScale 更改为 0 时,有什么方法可以触发任何事件吗?类似于:Time.timeScale.onBeforeChange()...

非常感谢。

将更改时间刻度的东西设为控制器,然后让该控制器引发事件。

[System.Serializable]
public class BeforeTimeChangedData
{
    public bool canceled;
    public float oldValue;
    public float newValue;
}


[System.Serializable]
public class BeforeTimeChangedEvent : UnityEvent<BeforeTimeChangedData>
{
}

//Attach this to a game object that gets loaded in your pre-load scene with the tag "Singletons"
public class TimeController : MonoBehaviour 
{   
    void Awake()
    {
        DontDestroyOnLoad(gameObject);

        if(BeforeTimeChanged == null)
            BeforeTimeChanged = new BeforeTimeChangedEvent();
    }

    public BeforeTimeChangedEvent BeforeTimeChanged;

    public bool ChangeTimeScale(float newValue)
    {
        var args = new BeforeTimeChangedData();
        args.oldValue = Time.timeScale;
        args.newValue = Time.timeScale;
        BeforeTimeChanged.Invoke(args);
        if(!args.canceled)
        {
            Time.timeScale = newValue;
        }
        return args.canceled;
    }
}

在其他地方,您可以通过

更改时间刻度
public class TimeSlower : MonoBehaviour 
{
    private TimeController _timeController;
    public Text TimeChanged;

    void Start()
    {
        var singletons = GameObject.FindWithTag("Singletons");
        _timeController = singletons.GetComponent<TimeController>();
        if(_timeController == null)
            throw new System.ArgumentNullException("Could not find a TimeController on the Singletons object");
    }

    void Update()
    {
        if(Input.GetButton("SlowTime"))
        {
            var changed = _timeController.ChangeTimeScale(0.5f);
            if(changed)
            {
                TimeChanged.text = "Time Changed!";
            }
        }
    }
}

这是另一个组件,它侦听更改并在最近发生更改时取消更改;

public class TimeChangeLimiter : MonoBehaviour 
{
    private float lastTimeChange = 0;
    private TimeController _timeController;
    public Text TimeChanged;

    [Range(0, float.MaxValue)]
    public float Cooldown;

    void Start()
    {
        var singletons = GameObject.FindWithTag("Singletons");
        _timeController = singletons.GetComponent<TimeController>();
        if(_timeController == null)
            throw new System.ArgumentNullException("Could not find a TimeController on the Singletons object");

        _timeController.BeforeTimeChanged.AddListener(OnBeforeTimeChanged);
    }

    void OnDestroy()
    {
        _timeController.BeforeTimeChanged.RemoveListener(OnBeforeTimeChanged);
    }


    void OnBeforeTimeChanged(BeforeTimeChangedData args)
    {
        if(Time.time - lastTimeChange < Cooldown)
        {
            args.canceled = true;
            return;
        }
        lastTimeChange = Time.time;
    }
}