【问题标题】:Run lerp over timer在计时器上运行 lerp
【发布时间】:2018-10-04 06:51:44
【问题描述】:

首先,我没有使用任何类型的游戏引擎,我正在使用 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 秒,直到达到目标。

这可能吗?

【问题讨论】:

  • 将(float)0.016替换为定时器外的变量,每次定时器触发时添加0.016?
  • @John 好的,但是你能举一个我可以使用的计时器的例子吗?我对可以为此工作的计时器感到很困惑。
  • 我不知道是否有一个特定的计时器可以为您提供总经过时间。
  • 当,这就是这里提出的问题,如何为此创建计时器。它太疯狂了,就像它在 Unity 之外不存在一样。
  • 嗯好吧,我试一试,我会告诉你的。谢谢。

标签: c# .net lerp


【解决方案1】:

我创建了一个示例计时器类,它会缓慢地将一个值递增给定数量,直到达到 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

Try it online

【讨论】:

  • @Kevin 抱歉,这是我的错字。应该是+= 而不是=。
  • 此解决方案将项目移动到 endPos 的一小部分,然后立即将其移回 startPos。我不知道为什么
  • 您是否传入startRotation 和endRotation(即开始 = 对象开始移动之前的位置,结束 = 对象停止移动时的位置)?
  • 是的,从上面看是一样的。 model.rotation 是开始,model.rotationM 是结束。我将它们更改为您示例中的那些。
  • model.rotationM = Vector3.Lerp(model.rotation, model.rotationM, lerpFactor) 100% 错误。考虑一下: Lerp(s, e, 0.1) ... Lerp(0, 10, 0.1) -> 你得到 1。现在变量 (e) 之前保持 10,你重新分配它保持 1。然后你调用 Lerp (s, e, 0.2) ... Lerp(0, 1, 0.2) -> 你得到 0.2 然后你重新分配它来保持 0.2。你调用 Lerp(s, e, 0.3) ... Lerp(0, 0.2, 0.3) -> 你得到 0.06。原因是您不断地将结束位置移近开始位置,这意味着第三个参数所代表的总体百分比越来越小。
猜你喜欢
  • 1970-01-01
  • 2018-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多