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
:如果TickTimer
是default
、TickTimer.None
,或正在運行且目標刷新小於或等於當前模擬刷新,則傳回真。
重置TickTimer
TickTimer
到期後,每當模擬刷新大於它存儲的目標刷新 後,它都會傳回真。為了只得到一次,在這個條件被評估為真的第一個刷新後重置TickTimer
是有用的。這可以透過將TickTimer
設定為TickTimer.None
或default
來完成。
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