This repository has been archived on 2025-04-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
com.unity.netcode.gameobjects/Runtime/Timing/NetworkTime.cs
Unity Technologies add668dfd2 com.unity.netcode.gameobjects@1.0.0-pre.8
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).

## [1.0.0-pre.8] - 2022-04-27

### Changed

- `unmanaged` structs are no longer universally accepted as RPC parameters because some structs (i.e., structs with pointers in them, such as `NativeList<T>`) can't be supported by the default memcpy struct serializer. Structs that are intended to be serialized across the network must add `INetworkSerializeByMemcpy` to the interface list (i.e., `struct Foo : INetworkSerializeByMemcpy`). This interface is empty and just serves to mark the struct as compatible with memcpy serialization. For external structs you can't edit, you can pass them to RPCs by wrapping them in `ForceNetworkSerializeByMemcpy<T>`. (#1901)

### Removed
- Removed `SIPTransport` (#1870)

- Removed `ClientNetworkTransform` from the package samples and moved to Boss Room's Utilities package which can be found [here](https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop/blob/main/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/ClientAuthority/ClientNetworkTransform.cs).

### Fixed

- Fixed `NetworkTransform` generating false positive rotation delta checks when rolling over between 0 and 360 degrees. (#1890)
- Fixed client throwing an exception if it has messages in the outbound queue when processing the `NetworkEvent.Disconnect` event and is using UTP. (#1884)
- Fixed issue during client synchronization if 'ValidateSceneBeforeLoading' returned false it would halt the client synchronization process resulting in a client that was approved but not synchronized or fully connected with the server. (#1883)
- Fixed an issue where UNetTransport.StartServer would return success even if the underlying transport failed to start (#854)
- Passing generic types to RPCs no longer causes a native crash (#1901)
- Fixed an issue where calling `Shutdown` on a `NetworkManager` that was already shut down would cause an immediate shutdown the next time it was started (basically the fix makes `Shutdown` idempotent). (#1877)
2022-04-27 00:00:00 +00:00

158 lines
5.5 KiB
C#

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.fixedTime"/>
/// </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.fixedDeltaTime"/> 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);
}
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;
}
}
public static NetworkTime operator -(NetworkTime a, NetworkTime b)
{
return new NetworkTime(a.TickRate, a.Time - b.Time);
}
public static NetworkTime operator +(NetworkTime a, NetworkTime b)
{
return new NetworkTime(a.TickRate, a.Time + b.Time);
}
public static NetworkTime operator +(NetworkTime a, double b)
{
a.m_TimeSec += b;
a.UpdateCache();
return a;
}
public static NetworkTime operator -(NetworkTime a, double b)
{
return a + -b;
}
}
}