首页 > 解决方案 > 在计时器上运行 lerp

问题描述

首先,我没有使用任何类型的游戏引擎,我正在用 C# 修改游戏并且我没有使用 UnityEngine API,所以我没有任何 Update() 函数。

所以我想弄清楚如何创建一个计时器,一些开箱即用的标准 C# 计时器,它会在设定的速度上增加 lerp 距离。

model.rotationM = Vector3.Lerp(model.rotation, model.rotationM, (float)0.016);
NAPI.Entity.SetEntityRotation(model.handle, model.rotationM);

我想将它包装在一个计时器中,每 100 毫秒它会在一段时间内将 lerp 末尾的浮点数增加一些设定的量,所以说我设置了float speed = 5f; 我想每 100 毫秒增加 lerp 距离 5 秒直到达到它的目标。

这可能吗?

标签: c#.netlerp

解决方案


我创建了一个示例计时器类,它将缓慢增加一个给定数量的值,直到达到 100% (1.0):

public class LerpTimer : IDisposable
{
    private readonly Timer _timer;
    private readonly float _incrementPercentage = 0;
    public event EventHandler<float> DoLerp;
    public event EventHandler Complete;
    private bool _isDisposed = false;
    private float _current;

    public LerpTimer(double frequencyMs, float incrementPercentage)
    {
        if (frequencyMs <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(frequencyMs), "Frequency must be greater than 1ms.");
        }

        if (incrementPercentage < 0 || incrementPercentage > 1)
        {
            throw new ArgumentOutOfRangeException(nameof(incrementPercentage), "Increment percentage must be a value between 0 and 1");
        }
        _timer = new Timer(frequencyMs);
        _timer.Elapsed += _timer_Elapsed;
        _incrementPercentage = incrementPercentage;
    }

    private void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (_isDisposed)
        {
            return;
        }

        if (this.Current < 1)
        {
            this.Current = Math.Min(1, this.Current + _incrementPercentage);
            this.DoLerp?.Invoke(this, this.Current);
        }

        if (this.Current >= 1)
        {
            this._timer.Stop();
            this.Complete?.Invoke(this, EventArgs.Empty);
        }
    }

    public float Current
    {
        get
        { 
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(LerpTimer));
            }
            return _current;
        }
        set => _current = value;
    }

    public void Start()
    {
        if (_isDisposed)
        {
            throw new ObjectDisposedException(nameof(LerpTimer));
        }

        if (_timer.Enabled)
        {
            throw new InvalidOperationException("Timer already running.");
        }
        this.Current = 0;
        _timer.Start();
    }

    public void Stop()
    {
        if (_isDisposed)
        {
            throw new ObjectDisposedException(nameof(LerpTimer));
        }

        if (!_timer.Enabled)
        {
            throw new InvalidOperationException("Timer not running.");
        }
        _timer.Stop();
    }

    public void Dispose()
    {
        _isDisposed = true;
        _timer?.Dispose();
    }
}

示例用法:

var lerpTimer = new LerpTimer(100, 0.016f);
lerpTimer.DoLerp += (sender, value) => {
    model.rotationM = Vector3.Lerp(startRotation, endRotation, value);
    NAPI.Entity.SetEntityRotation(model.handle, model.rotationM);
};
lerpTimer.Start();

所以你会调用一次,然后它会继续运行,直到达到 100% (endRotation)。

它不一定是您应该使用的代码,但它应该说明如何使用计时器来随着时间的推移增加值。


编辑以使 lerp 函数的作用更加清晰:

double lerp(double start, double end, double percentage)
{
    return start + ((end - start) * percentage);
}

想象一下,我们从 4 到 125 每 10% 调用一次。我们会得到以下结果:

0%    4
10%   16.1
20%   28.2
30%   40.3
40%   52.4
50%   64.5
60%   76.6
70%   88.7
80%   100.8
90%   112.9
100%  125

在线尝试


推荐阅读