This document is about: FUSION 2
SWITCH TO

TickTimer

概述

在觸發某些邏輯之前等待一段時間通常是有用的。TickTimer是Fusion中一種安全、方便、頻寬高效的方法。儘管它的名字是TickTimer,但它並不是一個真正的計時器,而是一個存儲目標刷新值並使用當前模擬刷新運行檢查的結構。

使用當前刷新(來自NetworkRunner)和目標刷新(在初始化TickTimer時儲存),TickTimer可以提供與任何其他計時器非常相似的資訊,並回答以下問題:

  • 計時器到期了嗎?
  • 計時器在運行嗎?
  • 還剩多少時間/多少刷新?

由於TickTimer使用目標刷新,而不是遞增或遞減浮點數或整數,因此當它作為[Networked]遊戲狀態的一部分被包含時,它使用的頻寬更少,因為它不會改變,且計時器邏輯是本機的。

注意TickTimer使用目標刷新,即使在用TickTimer.CreateFromSeconds()初始化它時也是如此。考慮到這一點和刷新率,計算出的目標刷新,可能會因經過的秒數而失去一些準確性,例如TickTimer.CreateFromSeconds(1.37f)

API

  • CreateFromSeconds:傳回一個新的TickTimer,其中包含使用提供的 數和當前模擬刷新所計算的目標刷新。
  • CreateFromTicks:傳回一個新的TickTimer,其中包含使用提供的 刷新 數和當前模擬刷新所計算的目標刷新。
  • RemainingTime:傳回TickTimer到期前的剩餘時間(以 為單位)。
  • RemainingTicks:傳回 刷新 中的剩餘時間,直到TickTimer到期。
  • IsRunning:如果TickTimer目標刷新大於當前模擬刷新,則傳回真。
  • Expired:如果TickTimer正在運行並且目標刷新小於或等於當前模擬刷新,則傳回真。
  • ExpiredOrNotRunning:如果TickTimerdefaultTickTimer.None,或正在運行且目標刷新小於或等於當前模擬刷新,則傳回真。

重置TickTimer

TickTimer到期後,每當模擬刷新大於它存儲的目標刷新 ,它都會傳回真。為了只得到一次,在這個條件被評估為真的第一個刷新後重置TickTimer是有用的。這可以透過將TickTimer設定為TickTimer.Nonedefault來完成。

C#

[Networked] TickTimer timer { get; set; }

void FixedUpdateNetwork()
{
  if (timer.Expired(Runner))
  {
    // Execute Logic

    // Reset timer
    timer = TickTimer.None;
    // alternatively: timer = default.

    Debug.Log("Timer Expired");
  }
}

建立自訂功能性

鑒於TickTimer的簡單性,很容易建立它的自訂版本並實作更多或不同的功能性。
以下兩個示例-計數和標準化時間-只需在建立計時器的那一刻新增初始刷新即可。

注意以下程式碼是原始TickTimer的自訂和簡化版本,用於展示可以在自訂版本中實作的功能。

C#

public struct CustomTickTimer : INetworkStruct
{
  private int _target;
  private int _initialTick;

  public bool Expired(NetworkRunner runner) => runner.IsRunning && _target > 0
    && (Tick) _target <= runner.Simulation.Tick;

  public bool IsRunning => _target > 0;

  public static CustomTickTimer CreateFromTicks(NetworkRunner runner, int ticks)
  {
    if (runner == false || runner.IsRunning == false)
      return new CustomTickTimer();

    CustomTickTimer fromTicks = new CustomTickTimer();
    fromTicks._target = (int) runner.Simulation.Tick + ticks;
    fromTicks._initialTick = runner.Simulation.Tick;
    return fromTicks;
  }

  public float NormalizedValue(NetworkRunner runner)
  {
    if (runner == null || runner.IsRunning == false || IsRunning == false)
      return 0;

    if (Expired(runner))
      return 1;

    return ElapsedTicks(runner) / (_target - (float)_initialTick);
  }

  public int ElapsedTicks(NetworkRunner runner)
  {
    if (runner == false || runner.IsRunning == false)
      return 0;

    if (IsRunning == false || Expired(runner))
      return 0;

    return runner.Simulation.Tick - _initialTick;
  }
}

計數

為了獲取自建立計時器以來經過的刷新數,請從NetworkRunner的當前刷新中減去初始刷新值。

C#

public int ElapsedTicks(NetworkRunner runner)
{
  if (runner == false || runner.IsRunning == false)
      return 0;

  if (IsRunning == false || Expired(runner))
    return 0;

  return runner.Simulation.Tick - _initialTick;
}

介於0和1之間的標準化值

為計時器的當前進度傳回介於0和1之間的標準化浮點數,請將經過的刷新數除以計時器正在計數的刷新總數。

C#

public float NormalizedValue(NetworkRunner runner)
{
  if (runner == null || runner.IsRunning == false || IsRunning == false)
    return 0;

  if (Expired(runner))
    return 1;

  return ElapsedTicks(runner) / (_target - (float)_initialTick);
}

現在,可以使用CustomTickTimer來顯示這些值。

C#

[Networked]
public CustomTickTimer MyTickTimer { get; set; }

public void StartTimer()
{
  if (Runner.IsServer)
  {
    MyTickTimer = CustomTickTimer.CreateFromTicks(Runner, 120);
  }
}

public override void FixedUpdateNetwork()
{
  Debug.Log($"Elapsed {MyTickTimer.ElapsedTicks(Runner)} ticks.");
  Debug.Log($"Normalized Value {MyTickTimer.NormalizedValue(Runner)}.");

  if (MyTickTimer.Expired(Runner))
  {
    // Execute Logic

    // Reset timer
    MyTickTimer = default;

    Debug.Log("Timer Finished on tick: " + Runner.Simulation.Tick);
  }
}
Back to top