Initial Commit

This commit is contained in:
Sebastian Cabrera 2021-08-02 05:44:37 -04:00
parent 53eb92e9af
commit 270ab7d11f
15341 changed files with 700234 additions and 0 deletions

View file

@ -0,0 +1,308 @@
using System.Linq;
using System.Collections.Generic;
using MLAPI.Messaging;
using MLAPI.Serialization;
using UnityEngine;
namespace MLAPI.Prototyping
{
/// <summary>
/// A prototype component for syncing animations
/// </summary>
[AddComponentMenu("MLAPI/NetworkAnimator")]
public class NetworkAnimator : NetworkBehaviour
{
private struct AnimParams : INetworkSerializable
{
public Dictionary<int, (AnimatorControllerParameterType Type, object Boxed)> Parameters;
public void NetworkSerialize(NetworkSerializer serializer)
{
int paramCount = serializer.IsReading ? 0 : Parameters.Count;
serializer.Serialize(ref paramCount);
var paramArray = serializer.IsReading ? new KeyValuePair<int, (AnimatorControllerParameterType Type, object Boxed)>[paramCount] : Parameters.ToArray();
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++)
{
int paramId = serializer.IsReading ? 0 : paramArray[paramIndex].Key;
serializer.Serialize(ref paramId);
byte paramType = serializer.IsReading ? (byte)0 : (byte)paramArray[paramIndex].Value.Type;
serializer.Serialize(ref paramType);
object paramBoxed = null;
switch (paramType)
{
case (byte)AnimatorControllerParameterType.Float:
float paramFloat = serializer.IsReading ? 0 : (float)paramArray[paramIndex].Value.Boxed;
serializer.Serialize(ref paramFloat);
paramBoxed = paramFloat;
break;
case (byte)AnimatorControllerParameterType.Int:
int paramInt = serializer.IsReading ? 0 : (int)paramArray[paramIndex].Value.Boxed;
serializer.Serialize(ref paramInt);
paramBoxed = paramInt;
break;
case (byte)AnimatorControllerParameterType.Bool:
bool paramBool = serializer.IsReading ? false : (bool)paramArray[paramIndex].Value.Boxed;
serializer.Serialize(ref paramBool);
paramBoxed = paramBool;
break;
}
if (serializer.IsReading)
{
paramArray[paramIndex] = new KeyValuePair<int, (AnimatorControllerParameterType, object)>(paramId, ((AnimatorControllerParameterType)paramType, paramBoxed));
}
}
if (serializer.IsReading)
{
Parameters = paramArray.ToDictionary(pair => pair.Key, pair => pair.Value);
}
}
}
public float SendRate = 0.1f;
[SerializeField]
private Animator m_Animator;
public Animator Animator => m_Animator;
[HideInInspector]
[SerializeField]
private uint m_TrackedParamFlags = 0;
public void SetParamTracking(int paramIndex, bool isTracking)
{
if (paramIndex >= 32) return;
if (isTracking)
{
m_TrackedParamFlags |= (uint)(1 << paramIndex);
}
else
{
m_TrackedParamFlags &= (uint)~(1 << paramIndex);
}
}
public bool GetParamTracking(int paramIndex)
{
if (paramIndex >= 32) return false;
return (m_TrackedParamFlags & (uint)(1 << paramIndex)) != 0;
}
public void ResetTrackedParams()
{
m_TrackedParamFlags = 0;
}
private void FixedUpdate()
{
if (!IsOwner) return;
if (CheckSendRate())
{
SendTrackedParams();
}
if (CheckStateChange(out int animStateHash, out float animStateTime))
{
SendAllParamsAndState(animStateHash, animStateTime);
}
}
private float m_NextSendTime = 0.0f;
private bool CheckSendRate()
{
var networkTime = NetworkManager.Singleton.NetworkTime;
if (SendRate != 0 && m_NextSendTime < networkTime)
{
m_NextSendTime = networkTime + SendRate;
return true;
}
return false;
}
private int m_LastAnimStateHash = 0;
private bool CheckStateChange(out int outAnimStateHash, out float outAnimStateTime)
{
var animStateInfo = Animator.GetCurrentAnimatorStateInfo(0);
var animStateHash = animStateInfo.fullPathHash;
var animStateTime = animStateInfo.normalizedTime;
if (animStateHash != m_LastAnimStateHash)
{
m_LastAnimStateHash = animStateHash;
outAnimStateHash = animStateHash;
outAnimStateTime = animStateTime;
return true;
}
outAnimStateHash = 0;
outAnimStateTime = 0;
return false;
}
private AnimParams GetAnimParams(bool trackedOnly = false)
{
var animParams = new AnimParams();
animParams.Parameters = new Dictionary<int, (AnimatorControllerParameterType, object)>(32);
for (int paramIndex = 0; paramIndex < 32 && paramIndex < Animator.parameters.Length; paramIndex++)
{
if (trackedOnly && !GetParamTracking(paramIndex)) continue;
var animParam = Animator.parameters[paramIndex];
var animParamHash = animParam.nameHash;
var animParamType = animParam.type;
object animParamBoxed = null;
switch (animParamType)
{
case AnimatorControllerParameterType.Float:
animParamBoxed = Animator.GetFloat(animParamHash);
break;
case AnimatorControllerParameterType.Int:
animParamBoxed = Animator.GetInteger(animParamHash);
break;
case AnimatorControllerParameterType.Bool:
animParamBoxed = Animator.GetBool(animParamHash);
break;
}
animParams.Parameters.Add(animParamHash, (animParamType, animParamBoxed));
}
return animParams;
}
private void SetAnimParams(AnimParams animParams)
{
foreach (var animParam in animParams.Parameters)
{
switch (animParam.Value.Type)
{
case AnimatorControllerParameterType.Float:
Animator.SetFloat(animParam.Key, (float)animParam.Value.Boxed);
break;
case AnimatorControllerParameterType.Int:
Animator.SetInteger(animParam.Key, (int)animParam.Value.Boxed);
break;
case AnimatorControllerParameterType.Bool:
Animator.SetBool(animParam.Key, (bool)animParam.Value.Boxed);
break;
}
}
}
private void SendTrackedParams()
{
var animParams = GetAnimParams( /* trackedOnly = */ true);
if (IsServer)
{
var clientRpcParams = new ClientRpcParams
{
Send = new ClientRpcSendParams
{
TargetClientIds = NetworkManager.Singleton.ConnectedClientsList
.Where(c => c.ClientId != NetworkManager.Singleton.ServerClientId)
.Select(c => c.ClientId)
.ToArray()
}
};
UpdateTrackedParamsClientRpc(animParams, clientRpcParams);
}
else
{
UpdateTrackedParamsServerRpc(animParams);
}
}
private void SendAllParamsAndState(int animStateHash, float animStateTime)
{
var animParams = GetAnimParams();
if (IsServer)
{
var clientRpcParams = new ClientRpcParams
{
Send = new ClientRpcSendParams
{
TargetClientIds = NetworkManager.Singleton.ConnectedClientsList
.Where(c => c.ClientId != NetworkManager.Singleton.ServerClientId)
.Select(c => c.ClientId)
.ToArray()
}
};
UpdateAnimStateClientRpc(animStateHash, animStateTime, clientRpcParams);
UpdateTrackedParamsClientRpc(animParams, clientRpcParams);
}
else
{
UpdateAnimStateServerRpc(animStateHash, animStateTime);
UpdateTrackedParamsServerRpc(animParams);
}
}
[ServerRpc]
private void UpdateTrackedParamsServerRpc(AnimParams animParams, ServerRpcParams serverRpcParams = default)
{
if (IsOwner) return;
SetAnimParams(animParams);
var clientRpcParams = new ClientRpcParams
{
Send = new ClientRpcSendParams
{
TargetClientIds = NetworkManager.Singleton.ConnectedClientsList
.Where(c => c.ClientId != serverRpcParams.Receive.SenderClientId)
.Select(c => c.ClientId)
.ToArray()
}
};
UpdateTrackedParamsClientRpc(animParams, clientRpcParams);
}
[ClientRpc]
private void UpdateTrackedParamsClientRpc(AnimParams animParams, ClientRpcParams clientRpcParams = default)
{
if (IsOwner) return;
SetAnimParams(animParams);
}
[ServerRpc]
private void UpdateAnimStateServerRpc(int animStateHash, float animStateTime, ServerRpcParams serverRpcParams = default)
{
if (IsOwner) return;
Animator.Play(animStateHash, 0, animStateTime);
var clientRpcParams = new ClientRpcParams
{
Send = new ClientRpcSendParams
{
TargetClientIds = NetworkManager.Singleton.ConnectedClientsList
.Where(c => c.ClientId != serverRpcParams.Receive.SenderClientId)
.Select(c => c.ClientId)
.ToArray()
}
};
UpdateAnimStateClientRpc(animStateHash, animStateTime, clientRpcParams);
}
[ClientRpc]
private void UpdateAnimStateClientRpc(int animStateHash, float animStateTime, ClientRpcParams clientRpcParams = default)
{
if (IsOwner) return;
Animator.Play(animStateHash, 0, animStateTime);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e8d0727d5ae3244e3b569694d3912374
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,118 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using MLAPI.Connection;
using MLAPI.Messaging;
namespace MLAPI.Prototyping
{
/// <summary>
/// A prototype component for syncing NavMeshAgents
/// </summary>
[AddComponentMenu("MLAPI/NetworkNavMeshAgent")]
[RequireComponent(typeof(NavMeshAgent))]
public class NetworkNavMeshAgent : NetworkBehaviour
{
private NavMeshAgent m_Agent;
/// <summary>
/// Is proximity enabled
/// </summary>
public bool EnableProximity = false;
/// <summary>
/// The proximity range
/// </summary>
public float ProximityRange = 50f;
/// <summary>
/// The delay in seconds between corrections
/// </summary>
public float CorrectionDelay = 3f;
//TODO rephrase.
/// <summary>
/// The percentage to lerp on corrections
/// </summary>
[Tooltip("Everytime a correction packet is received. This is the percentage (between 0 & 1) that we will move towards the goal.")]
public float DriftCorrectionPercentage = 0.1f;
/// <summary>
/// Should we warp on destination change
/// </summary>
public bool WarpOnDestinationChange = false;
private void Awake()
{
m_Agent = GetComponent<NavMeshAgent>();
}
private Vector3 m_LastDestination = Vector3.zero;
private float m_LastCorrectionTime = 0f;
private void Update()
{
if (!IsOwner) return;
if (m_Agent.destination != m_LastDestination)
{
m_LastDestination = m_Agent.destination;
if (!EnableProximity)
{
OnNavMeshStateUpdateClientRpc(m_Agent.destination, m_Agent.velocity, transform.position);
}
else
{
var proximityClients = new List<ulong>();
foreach (KeyValuePair<ulong, NetworkClient> client in NetworkManager.Singleton.ConnectedClients)
{
if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange)
{
proximityClients.Add(client.Key);
}
}
OnNavMeshStateUpdateClientRpc(m_Agent.destination, m_Agent.velocity, transform.position, new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = proximityClients.ToArray() } });
}
}
if (NetworkManager.Singleton.NetworkTime - m_LastCorrectionTime >= CorrectionDelay)
{
if (!EnableProximity)
{
OnNavMeshCorrectionUpdateClientRpc(m_Agent.velocity, transform.position);
}
else
{
var proximityClients = new List<ulong>();
foreach (KeyValuePair<ulong, NetworkClient> client in NetworkManager.Singleton.ConnectedClients)
{
if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange)
{
proximityClients.Add(client.Key);
}
}
OnNavMeshCorrectionUpdateClientRpc(m_Agent.velocity, transform.position, new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = proximityClients.ToArray() } });
}
m_LastCorrectionTime = NetworkManager.Singleton.NetworkTime;
}
}
[ClientRpc]
private void OnNavMeshStateUpdateClientRpc(Vector3 destination, Vector3 velocity, Vector3 position, ClientRpcParams rpcParams = default)
{
m_Agent.Warp(WarpOnDestinationChange ? position : Vector3.Lerp(transform.position, position, DriftCorrectionPercentage));
m_Agent.SetDestination(destination);
m_Agent.velocity = velocity;
}
[ClientRpc]
private void OnNavMeshCorrectionUpdateClientRpc(Vector3 velocity, Vector3 position, ClientRpcParams rpcParams = default)
{
m_Agent.Warp(Vector3.Lerp(transform.position, position, DriftCorrectionPercentage));
m_Agent.velocity = velocity;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 43b86c65774f4494ba4e5878d5df9bcd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,351 @@
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using MLAPI.Messaging;
namespace MLAPI.Prototyping
{
/// <summary>
/// A prototype component for syncing transforms
/// </summary>
[AddComponentMenu("MLAPI/NetworkTransform")]
public class NetworkTransform : NetworkBehaviour
{
internal class ClientSendInfo
{
public float LastSent;
public Vector3? LastMissedPosition;
public Quaternion? LastMissedRotation;
}
/// <summary>
/// The base amount of sends per seconds to use when range is disabled
/// </summary>
[Range(0, 120)]
public float FixedSendsPerSecond = 20f;
/// <summary>
/// Is the sends per second assumed to be the same across all instances
/// </summary>
[Tooltip("This assumes that the SendsPerSecond is synced across clients")]
public bool AssumeSyncedSends = true;
/// <summary>
/// Enable interpolation
/// </summary>
[Tooltip("This requires AssumeSyncedSends to be true")]
public bool InterpolatePosition = true;
/// <summary>
/// The distance before snaping to the position
/// </summary>
[Tooltip("The transform will snap if the distance is greater than this distance")]
public float SnapDistance = 10f;
/// <summary>
/// Should the server interpolate
/// </summary>
public bool InterpolateServer = true;
/// <summary>
/// The min meters to move before a send is sent
/// </summary>
public float MinMeters = 0.15f;
/// <summary>
/// The min degrees to rotate before a send it sent
/// </summary>
public float MinDegrees = 1.5f;
/// <summary>
/// Enables extrapolation
/// </summary>
public bool ExtrapolatePosition = false;
/// <summary>
/// The maximum amount of expected send rates to extrapolate over when awaiting new packets.
/// A higher value will result in continued extrapolation after an object has stopped moving
/// </summary>
public float MaxSendsToExtrapolate = 5;
/// <summary>
/// The channel to send the data on
/// </summary>
[Tooltip("The channel to send the data on. Uses the default channel if left unspecified")]
public string Channel = null;
private float m_LerpTime;
private Vector3 m_LerpStartPos;
private Quaternion m_LerpStartRot;
private Vector3 m_LerpEndPos;
private Quaternion m_LerpEndRot;
private float m_LastSendTime;
private Vector3 m_LastSentPos;
private Quaternion m_LastSentRot;
private float m_LastReceiveTime;
/// <summary>
/// Enables range based send rate
/// </summary>
public bool EnableRange;
/// <summary>
/// Checks for missed sends without provocation. Provocation being a client inside it's normal SendRate
/// </summary>
public bool EnableNonProvokedResendChecks;
/// <summary>
/// The curve to use to calculate the send rate
/// </summary>
public AnimationCurve DistanceSendrate = AnimationCurve.Constant(0, 500, 20);
private readonly Dictionary<ulong, ClientSendInfo> m_ClientSendInfo = new Dictionary<ulong, ClientSendInfo>();
/// <summary>
/// The delegate used to check if a move is valid
/// </summary>
/// <param name="clientId">The client id the move is being validated for</param>
/// <param name="oldPos">The previous position</param>
/// <param name="newPos">The new requested position</param>
/// <returns>Returns Whether or not the move is valid</returns>
public delegate bool MoveValidationDelegate(ulong clientId, Vector3 oldPos, Vector3 newPos);
/// <summary>
/// If set, moves will only be accepted if the custom delegate returns true
/// </summary>
public MoveValidationDelegate IsMoveValidDelegate = null;
private void OnValidate()
{
if (!AssumeSyncedSends && InterpolatePosition)
InterpolatePosition = false;
if (InterpolateServer && !InterpolatePosition)
InterpolateServer = false;
if (MinDegrees < 0)
MinDegrees = 0;
if (MinMeters < 0)
MinMeters = 0;
if (EnableNonProvokedResendChecks && !EnableRange)
EnableNonProvokedResendChecks = false;
}
private float GetTimeForLerp(Vector3 pos1, Vector3 pos2)
{
return 1f / DistanceSendrate.Evaluate(Vector3.Distance(pos1, pos2));
}
/// <summary>
/// Registers message handlers
/// </summary>
public override void NetworkStart()
{
m_LastSentRot = transform.rotation;
m_LastSentPos = transform.position;
m_LerpStartPos = transform.position;
m_LerpStartRot = transform.rotation;
m_LerpEndPos = transform.position;
m_LerpEndRot = transform.rotation;
}
private void Update()
{
if (IsOwner)
{
if (NetworkManager.Singleton.NetworkTime - m_LastSendTime >= (1f / FixedSendsPerSecond) && (Vector3.Distance(transform.position, m_LastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, m_LastSentRot) > MinDegrees))
{
m_LastSendTime = NetworkManager.Singleton.NetworkTime;
m_LastSentPos = transform.position;
m_LastSentRot = transform.rotation;
if (IsServer)
{
ApplyTransformClientRpc(transform.position, transform.rotation.eulerAngles,
new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = NetworkManager.Singleton.ConnectedClientsList.Where(c => c.ClientId != OwnerClientId).Select(c => c.ClientId).ToArray() } });
}
else
{
SubmitTransformServerRpc(transform.position, transform.rotation.eulerAngles);
}
}
}
else
{
//If we are server and interpolation is turned on for server OR we are not server and interpolation is turned on
if ((IsServer && InterpolateServer && InterpolatePosition) || (!IsServer && InterpolatePosition))
{
if (Vector3.Distance(transform.position, m_LerpEndPos) > SnapDistance)
{
//Snap, set T to 1 (100% of the lerp)
m_LerpTime = 1f;
}
float sendDelay = (IsServer || !EnableRange || !AssumeSyncedSends || NetworkManager.Singleton.ConnectedClients[NetworkManager.Singleton.LocalClientId].PlayerObject == null) ? (1f / FixedSendsPerSecond) : GetTimeForLerp(transform.position, NetworkManager.Singleton.ConnectedClients[NetworkManager.Singleton.LocalClientId].PlayerObject.transform.position);
m_LerpTime += Time.unscaledDeltaTime / sendDelay;
if (ExtrapolatePosition && Time.unscaledTime - m_LastReceiveTime < sendDelay * MaxSendsToExtrapolate)
transform.position = Vector3.LerpUnclamped(m_LerpStartPos, m_LerpEndPos, m_LerpTime);
else
transform.position = Vector3.Lerp(m_LerpStartPos, m_LerpEndPos, m_LerpTime);
if (ExtrapolatePosition && Time.unscaledTime - m_LastReceiveTime < sendDelay * MaxSendsToExtrapolate)
transform.rotation = Quaternion.SlerpUnclamped(m_LerpStartRot, m_LerpEndRot, m_LerpTime);
else
transform.rotation = Quaternion.Slerp(m_LerpStartRot, m_LerpEndRot, m_LerpTime);
}
}
if (IsServer && EnableRange && EnableNonProvokedResendChecks)
CheckForMissedSends();
}
[ClientRpc]
private void ApplyTransformClientRpc(Vector3 position, Vector3 eulerAngles, ClientRpcParams rpcParams = default)
{
if (enabled)
{
ApplyTransformInternal(position, Quaternion.Euler(eulerAngles));
}
}
private void ApplyTransformInternal(Vector3 position, Quaternion rotation)
{
if (!enabled)
return;
if (InterpolatePosition && (!IsServer || InterpolateServer))
{
m_LastReceiveTime = Time.unscaledTime;
m_LerpStartPos = transform.position;
m_LerpStartRot = transform.rotation;
m_LerpEndPos = position;
m_LerpEndRot = rotation;
m_LerpTime = 0;
}
else
{
transform.position = position;
transform.rotation = rotation;
}
}
[ServerRpc]
private void SubmitTransformServerRpc(Vector3 position, Vector3 eulerAngles, ServerRpcParams rpcParams = default)
{
if (!enabled)
return;
if (IsMoveValidDelegate != null && !IsMoveValidDelegate(rpcParams.Receive.SenderClientId, m_LerpEndPos, position))
{
//Invalid move!
//TODO: Add rubber band (just a message telling them to go back)
return;
}
if (!IsClient)
{
// Dedicated server
ApplyTransformInternal(position, Quaternion.Euler(eulerAngles));
}
if (EnableRange)
{
for (int i = 0; i < NetworkManager.Singleton.ConnectedClientsList.Count; i++)
{
if (!m_ClientSendInfo.ContainsKey(NetworkManager.Singleton.ConnectedClientsList[i].ClientId))
{
m_ClientSendInfo.Add(NetworkManager.Singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo()
{
LastMissedPosition = null,
LastMissedRotation = null,
LastSent = 0
});
}
ClientSendInfo info = m_ClientSendInfo[NetworkManager.Singleton.ConnectedClientsList[i].ClientId];
Vector3? receiverPosition = NetworkManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position);
Vector3? senderPosition = NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position);
if ((receiverPosition == null || senderPosition == null && NetworkManager.Singleton.NetworkTime - info.LastSent >= (1f / FixedSendsPerSecond)) || NetworkManager.Singleton.NetworkTime - info.LastSent >= GetTimeForLerp(receiverPosition.Value, senderPosition.Value))
{
info.LastSent = NetworkManager.Singleton.NetworkTime;
info.LastMissedPosition = null;
info.LastMissedRotation = null;
ApplyTransformClientRpc(position, eulerAngles,
new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = new[] { NetworkManager.Singleton.ConnectedClientsList[i].ClientId } } });
}
else
{
info.LastMissedPosition = position;
info.LastMissedRotation = Quaternion.Euler(eulerAngles);
}
}
}
else
{
ApplyTransformClientRpc(position, eulerAngles,
new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = NetworkManager.Singleton.ConnectedClientsList.Where(c => c.ClientId != OwnerClientId).Select(c => c.ClientId).ToArray() } });
}
}
private void CheckForMissedSends()
{
for (int i = 0; i < NetworkManager.Singleton.ConnectedClientsList.Count; i++)
{
if (!m_ClientSendInfo.ContainsKey(NetworkManager.Singleton.ConnectedClientsList[i].ClientId))
{
m_ClientSendInfo.Add(NetworkManager.Singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo()
{
LastMissedPosition = null,
LastMissedRotation = null,
LastSent = 0
});
}
ClientSendInfo info = m_ClientSendInfo[NetworkManager.Singleton.ConnectedClientsList[i].ClientId];
Vector3? receiverPosition = NetworkManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position);
Vector3? senderPosition = NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position);
if ((receiverPosition == null || senderPosition == null && NetworkManager.Singleton.NetworkTime - info.LastSent >= (1f / FixedSendsPerSecond)) || NetworkManager.Singleton.NetworkTime - info.LastSent >= GetTimeForLerp(receiverPosition.Value, senderPosition.Value))
{
/* why is this??? ->*/
Vector3? pos = NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position);
/* why is this??? ->*/
Vector3? rot = NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject == null ? null : new Vector3?(NetworkManager.Singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.rotation.eulerAngles);
if (info.LastMissedPosition != null && info.LastMissedRotation != null)
{
info.LastSent = NetworkManager.Singleton.NetworkTime;
ApplyTransformClientRpc(info.LastMissedPosition.Value, info.LastMissedRotation.Value.eulerAngles,
new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = new[] { NetworkManager.Singleton.ConnectedClientsList[i].ClientId } } });
info.LastMissedPosition = null;
info.LastMissedRotation = null;
}
}
}
}
/// <summary>
/// Teleports the transform to the given position and rotation
/// </summary>
/// <param name="position">The position to teleport to</param>
/// <param name="rotation">The rotation to teleport to</param>
public void Teleport(Vector3 position, Quaternion rotation)
{
if (InterpolateServer && IsServer || IsClient)
{
m_LerpStartPos = position;
m_LerpStartRot = rotation;
m_LerpEndPos = position;
m_LerpEndRot = rotation;
m_LerpTime = 0;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e96cb6065543e43c4a752faaa1468eb1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
{
"name": "Unity.Multiplayer.MLAPI.Prototyping",
"rootNamespace": "MLAPI.Prototyping",
"references": [
"Unity.Multiplayer.MLAPI.Runtime"
],
"includePlatforms": [],
"excludePlatforms": []
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b8ed52f1b5c64994af4c4e0aa4b6c4b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: