优化:设置还是减去?

Optimization: Set or Subtract?

这是一个非常简单的问题。

我正在用 XNA 编写一个多人游戏,什么是更好的选择 - 为什么?

(第 7 行是每个选项中唯一更改的行)

选项 1:

const float SyncFrequency = (1 / 30f);
float Sync;

void Sync(GameTime GT)
{
    Sync += (float)GT.ElapsedGameTime.TotalSeconds;
    if (Sync >= SyncFrequency) { Sync = 0; SyncAll(); }
}

void SyncAll() { /*Syncing Code Here*/ }

选项 2:

const float SyncFrequency = (1 / 30f);
float Sync;

void Sync(GameTime GT)
{
    Sync += (float)GT.ElapsedGameTime.TotalSeconds;
    if (Sync >= SyncFrequency) { Sync -= SyncFrequency; SyncAll(); }
}

void SyncAll() { /*Syncing Code Here*/ }

另外:

注意我使用了浮点数:

const float SyncFrequency = (1 / 30f);

是否需要使用超精度?例如:

const double SyncFrequency = (1 / 30d);

从数学上讲,减去而不是重置是有意义的。

示例:标准 60fps 表示大约每 16.666 毫秒更新一次。如果你有一个每 30 毫秒轮询一次的网络连接,在第二次更新时,经过的时间将为 33.333 毫秒,这意味着如果你重置,你将再次回到原点。而如果您从电流中减去 30 毫秒,则减少了 3.333 毫秒。因此,在几秒钟内,您将获得 运行 更准确的网络连接投票数量。

这完全取决于实际情况。在上面提到的实例中,您可能 运行 遇到应用程序将轮询网络连接 33 次的情况,而其他时候它可能会轮询 32 次或 34 次,这是由于之前的时间 运行s。这一切当然是可以计算出来的。

如果实际用于网络轮询,这可能会导致游戏玩法不平衡(可能不明显,但仍然存在)。

但是对于动画之类的事情来说,这是有道理的,因为您很可能总是希望硬件能够提供最流畅的动画效果。

特别是对于移动,因为有些 PC 不能每秒更新 60 次(由于硬件限制,或者软件仅支持 30 或 24fps)。这也会导致运动不均匀,如果你实际上没有使用经过的时间(60fps 中的 16.666ms)来计算运动等。

吐槽结束

为了进一步扩展 Bjarke 的精彩解释,我编写了这个供我使用,但请随意使用它:

public static class Timers
{
    private static Dictionary<string, Timer> Array;
    public static void Add(string Name, double Interval)
    {
        if (Array == null) Array = new Dictionary<string, Timer>();
        if (!Array.ContainsKey(Name)) Array.Add(Name, new Timer(Interval));
    }
    public static void Remove(string Name) { if ((Array != null) && Array.ContainsKey(Name)) Array.Remove(Name); }
    public static void Clear() { Array.Clear(); Array = null; }

    public static void Update(GameTime GameTime)
    {
        if (Array != null)
            foreach (Timer Timer in Array.Values)
            {
                if (Timer.Time >= Timer.Interval) Timer.Time -= Timer.Interval;
                Timer.Time += GameTime.ElapsedGameTime.TotalSeconds;
            }
    }
    public static bool Tick(string Name) { return ((Array != null) && Array.ContainsKey(Name) && (Array[Name].Time >= Array[Name].Interval)); }

    private class Timer
    {
        public double Interval, Time;

        public Timer(double Interval) { this.Interval = Interval; }
    }
}

添加计时器:

//Parameter 1: The name of the timer for your use.
//Parameter 2: The time (of interval) for each tick.
Timers.Add("Name of your timer!", (1 / 30d));
    // (1 / 30d) = 30 times a second

(在游戏的加载函数中添加计时器)


要使用您的计时器:

在您的游戏更新方法中(在开始时),调用:

Timers.Update(gameTime);

然后您可以像这样使用您添加的任何计时器:

if (Tick("Name of your timer!"))
{
    //Code here to execute on the tick of the timer
}