您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

186 行
6.8 KiB

using System;
using UnityEngine;
using UnityEngine.Assertions;
namespace Unity.Netcode
{
/// <summary>
/// A struct to represent a point of time in a networked game.
/// Time is stored as a combination of amount of passed ticks + a duration offset.
/// This struct is meant to replace the Unity <see cref="Time"/> API for multiplayer gameplay.
/// </summary>
public struct NetworkTime
{
private double m_TimeSec;
private uint m_TickRate;
private double m_TickInterval;
private int m_CachedTick;
private double m_CachedTickOffset;
/// <summary>
/// Gets the amount of time which has passed since the last network tick.
/// </summary>
public double TickOffset => m_CachedTickOffset;
/// <summary>
/// Gets the current time. This is a non fixed time value and similar to <see cref="Time.time"/>.
/// </summary>
public double Time => m_TimeSec;
/// <summary>
/// Gets the current time as a float.
/// </summary>
public float TimeAsFloat => (float)m_TimeSec;
/// <summary>
/// Gets he current fixed network time. This is the time value of the last network tick. Similar to <see cref="Time.fixedUnscaledTime"/>.
/// </summary>
public double FixedTime => m_CachedTick * m_TickInterval;
/// <summary>
/// Gets the fixed delta time. This value is based on the <see cref="TickRate"/> and stays constant.
/// Similar to <see cref="Time.fixedUnscaledTime"/> There is no equivalent to <see cref="Time.deltaTime"/>.
/// </summary>
public float FixedDeltaTime => (float)m_TickInterval;
/// <summary>
/// Gets the amount of network ticks which have passed until reaching the current time value.
/// </summary>
public int Tick => m_CachedTick;
/// <summary>
/// Gets the tickrate of the system of this <see cref="NetworkTime"/>.
/// Ticks per second.
/// </summary>
public uint TickRate => m_TickRate;
/// <summary>
/// Creates a new instance of the <see cref="NetworkTime"/> struct.
/// </summary>
/// <param name="tickRate">The tickrate.</param>
public NetworkTime(uint tickRate)
{
Assert.IsTrue(tickRate > 0, "Tickrate must be a positive value.");
m_TickRate = tickRate;
m_TickInterval = 1f / m_TickRate; // potential floating point precision issue, could result in different interval on different machines
m_CachedTickOffset = 0;
m_CachedTick = 0;
m_TimeSec = 0;
}
/// <summary>
/// Creates a new instance of the <see cref="NetworkTime"/> struct.
/// </summary>
/// <param name="tickRate">The tickrate.</param>
/// <param name="tick">The time will be created with a value where this many tick have already passed.</param>
/// <param name="tickOffset">Can be used to create a <see cref="NetworkTime"/> with a non fixed time value by adding an offset to the given tick value.</param>
public NetworkTime(uint tickRate, int tick, double tickOffset = 0d)
: this(tickRate)
{
Assert.IsTrue(tickOffset < 1d / tickRate);
m_CachedTickOffset = tickOffset;
m_CachedTick = tick;
m_TimeSec = tick * m_TickInterval + tickOffset;
}
/// <summary>
/// Creates a new instance of the <see cref="NetworkTime"/> struct.
/// </summary>
/// <param name="tickRate">The tickrate.</param>
/// <param name="timeSec">The time value as a float.</param>
public NetworkTime(uint tickRate, double timeSec)
: this(tickRate)
{
this += timeSec;
}
/// <summary>
/// Converts the network time into a fixed time value.
/// </summary>
/// <returns>A <see cref="NetworkTime"/> where Time is the FixedTime value of this instance.</returns>
public NetworkTime ToFixedTime()
{
return new NetworkTime(m_TickRate, m_CachedTick);
}
/// <summary>
/// Returns the time a number of ticks in the past.
/// </summary>
/// <param name="ticks">The number of ticks ago we're querying the time</param>
/// <returns></returns>
public NetworkTime TimeTicksAgo(int ticks)
{
return this - new NetworkTime(TickRate, ticks);
}
private void UpdateCache()
{
double d = m_TimeSec / m_TickInterval;
m_CachedTick = (int)d;
// This check is needed due to double division imprecision of large numbers
if ((d - m_CachedTick) >= 0.999999999999)
{
m_CachedTick++;
}
m_CachedTickOffset = ((d - Math.Truncate(d)) * m_TickInterval);
// This handles negative time, decreases tick by 1 and makes offset positive.
if (m_CachedTick < 0 && m_CachedTickOffset != 0d)
{
m_CachedTick--;
m_CachedTickOffset = m_TickInterval + m_CachedTickOffset;
}
}
/// <summary>
/// Computes the time difference between two ticks
/// </summary>
/// <param name="a">End time</param>
/// <param name="b">Start time</param>
/// <returns>The time difference between start and end</returns>
public static NetworkTime operator -(NetworkTime a, NetworkTime b)
{
return new NetworkTime(a.TickRate, a.Time - b.Time);
}
/// <summary>
/// Computes the sum of two times
/// </summary>
/// <param name="a">First time</param>
/// <param name="b">Second time</param>
/// <returns>The sum of the two times passed in</returns>
public static NetworkTime operator +(NetworkTime a, NetworkTime b)
{
return new NetworkTime(a.TickRate, a.Time + b.Time);
}
/// <summary>
/// Computes the time a number of seconds later
/// </summary>
/// <param name="a">The start time</param>
/// <param name="b">The number of seconds to add</param>
/// <returns>The resulting time</returns>
public static NetworkTime operator +(NetworkTime a, double b)
{
a.m_TimeSec += b;
a.UpdateCache();
return a;
}
/// <summary>
/// Computes the time a number of seconds before
/// </summary>
/// <param name="a">The start time</param>
/// <param name="b">The number of seconds to remove</param>
/// <returns>The resulting time</returns>
public static NetworkTime operator -(NetworkTime a, double b)
{
return a + -b;
}
}
}