Reworked NetworkedAnimator

This commit is contained in:
Albin Corén 2018-03-05 20:25:08 +01:00
parent f0c0616e70
commit 0f08318224

View File

@ -1,27 +1,36 @@
using System; using System.IO;
using System.IO;
using UnityEngine; using UnityEngine;
namespace MLAPI namespace MLAPI
{ {
[DisallowMultipleComponent]
[RequireComponent(typeof(Animator))]
public class NetworkedAnimator : NetworkedBehaviour public class NetworkedAnimator : NetworkedBehaviour
{ {
// configuration [SerializeField]
[SerializeField] Animator m_Animator; private Animator _animator;
[SerializeField] uint m_ParameterSendBits; [SerializeField]
[SerializeField] float m_SendRate = 0.1f; private uint parameterSendBits;
[SerializeField]
private float sendRate = 0.1f;
private AnimatorControllerParameter[] animatorParameters;
AnimatorControllerParameter[] m_AnimatorParameters; private int animationHash;
private int transitionHash;
private float sendTimer;
// tracking - these should probably move to a Preview component. -- Comment from HLAPI. Needs clarification
public string param0;
public string param1;
public string param2;
public string param3;
public string param4;
public string param5;
// properties
public Animator animator public Animator animator
{ {
get { return m_Animator; } get { return _animator; }
set set
{ {
m_Animator = value; _animator = value;
ResetParameterOptions(); ResetParameterOptions();
} }
} }
@ -30,32 +39,20 @@ namespace MLAPI
{ {
if (value) if (value)
{ {
m_ParameterSendBits |= (uint)(1 << index); parameterSendBits |= (uint)(1 << index);
} }
else else
{ {
m_ParameterSendBits &= (uint)(~(1 << index)); parameterSendBits &= (uint)(~(1 << index));
} }
} }
public bool GetParameterAutoSend(int index) public bool GetParameterAutoSend(int index)
{ {
return (m_ParameterSendBits & (uint)(1 << index)) != 0; return (parameterSendBits & (uint)(1 << index)) != 0;
} }
int m_AnimationHash; private bool sendMessagesAllowed
int m_TransitionHash;
float m_SendTimer;
// tracking - these should probably move to a Preview component.
public string param0;
public string param1;
public string param2;
public string param3;
public string param4;
public string param5;
bool sendMessagesAllowed
{ {
get get
{ {
@ -73,23 +70,22 @@ namespace MLAPI
public void ResetParameterOptions() public void ResetParameterOptions()
{ {
Debug.Log("ResetParameterOptions"); Debug.Log("ResetParameterOptions");
m_ParameterSendBits = 0; parameterSendBits = 0;
m_AnimatorParameters = null; animatorParameters = null;
} }
void FixedUpdate() private void FixedUpdate()
{ {
if (!sendMessagesAllowed) if (!sendMessagesAllowed)
return; return;
CheckSendRate(); CheckSendRate();
int stateHash; if (!CheckAnimStateChanged(out int stateHash, out float normalizedTime))
float normalizedTime;
if (!CheckAnimStateChanged(out stateHash, out normalizedTime))
{ {
return; return;
} }
using(MemoryStream stream = new MemoryStream()) using(MemoryStream stream = new MemoryStream())
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) using (BinaryWriter writer = new BinaryWriter(stream))
@ -109,46 +105,46 @@ namespace MLAPI
} }
} }
bool CheckAnimStateChanged(out int stateHash, out float normalizedTime) private bool CheckAnimStateChanged(out int stateHash, out float normalizedTime)
{ {
stateHash = 0; stateHash = 0;
normalizedTime = 0; normalizedTime = 0;
if (m_Animator.IsInTransition(0)) if (animator.IsInTransition(0))
{ {
AnimatorTransitionInfo tt = m_Animator.GetAnimatorTransitionInfo(0); AnimatorTransitionInfo animationTransitionInfo = animator.GetAnimatorTransitionInfo(0);
if (tt.fullPathHash != m_TransitionHash) if (animationTransitionInfo.fullPathHash != transitionHash)
{ {
// first time in this transition // first time in this transition
m_TransitionHash = tt.fullPathHash; transitionHash = animationTransitionInfo.fullPathHash;
m_AnimationHash = 0; animationHash = 0;
return true; return true;
} }
return false; return false;
} }
AnimatorStateInfo st = m_Animator.GetCurrentAnimatorStateInfo(0); AnimatorStateInfo animationSateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (st.fullPathHash != m_AnimationHash) if (animationSateInfo.fullPathHash != animationHash)
{ {
// first time in this animation state // first time in this animation state
if (m_AnimationHash != 0) if (animationHash != 0)
{ {
// came from another animation directly - from Play() // came from another animation directly - from Play()
stateHash = st.fullPathHash; stateHash = animationSateInfo.fullPathHash;
normalizedTime = st.normalizedTime; normalizedTime = animationSateInfo.normalizedTime;
} }
m_TransitionHash = 0; transitionHash = 0;
m_AnimationHash = st.fullPathHash; animationHash = animationSateInfo.fullPathHash;
return true; return true;
} }
return false; return false;
} }
void CheckSendRate() private void CheckSendRate()
{ {
if (sendMessagesAllowed && m_SendRate != 0 && m_SendTimer < Time.time) if (sendMessagesAllowed && sendRate != 0 && sendTimer < Time.time)
{ {
m_SendTimer = Time.time + m_SendRate; sendTimer = Time.time + sendRate;
using(MemoryStream stream = new MemoryStream()) using(MemoryStream stream = new MemoryStream())
{ {
@ -168,7 +164,7 @@ namespace MLAPI
} }
} }
void SetSendTrackingParam(string p, int i) private void SetSendTrackingParam(string p, int i)
{ {
p = "Sent Param: " + p; p = "Sent Param: " + p;
if (i == 0) param0 = p; if (i == 0) param0 = p;
@ -179,7 +175,7 @@ namespace MLAPI
if (i == 5) param5 = p; if (i == 5) param5 = p;
} }
void SetRecvTrackingParam(string p, int i) private void SetRecvTrackingParam(string p, int i)
{ {
p = "Recv Param: " + p; p = "Recv Param: " + p;
if (i == 0) param0 = p; if (i == 0) param0 = p;
@ -190,13 +186,12 @@ namespace MLAPI
if (i == 5) param5 = p; if (i == 5) param5 = p;
} }
internal void HandleAnimMsg(int clientId, byte[] data) private void HandleAnimMsg(int clientId, byte[] data)
{ {
// usually transitions will be triggered by parameters, if not, play anims directly. // usually transitions will be triggered by parameters, if not, play anims directly.
// NOTE: this plays "animations", not transitions, so any transitions will be skipped. // NOTE: this plays "animations", not transitions, so any transitions will be skipped.
// NOTE: there is no API to play a transition(?) // NOTE: there is no API to play a transition(?)
//isServer AND the message is not from ourselves. This prevents a stack overflow. Infinite call to itself.
if(isServer) if(isServer)
{ {
SendToNonLocalClientsTarget("MLAPI_HandleAnimationMessage", "MLAPI_ANIMATION_UPDATE", data, true); SendToNonLocalClientsTarget("MLAPI_HandleAnimationMessage", "MLAPI_ANIMATION_UPDATE", data, true);
@ -209,14 +204,14 @@ namespace MLAPI
float normalizedTime = reader.ReadSingle(); float normalizedTime = reader.ReadSingle();
if(stateHash != 0) if(stateHash != 0)
{ {
m_Animator.Play(stateHash, 0, normalizedTime); animator.Play(stateHash, 0, normalizedTime);
} }
ReadParameters(reader, false); ReadParameters(reader, false);
} }
} }
} }
internal void HandleAnimParamsMsg(int clientId, byte[] data) private void HandleAnimParamsMsg(int clientId, byte[] data)
{ {
if (isServer) if (isServer)
{ {
@ -231,7 +226,7 @@ namespace MLAPI
} }
} }
internal void HandleAnimTriggerMsg(int clientId, byte[] data) private void HandleAnimTriggerMsg(int clientId, byte[] data)
{ {
if (isServer) if (isServer)
{ {
@ -241,56 +236,60 @@ namespace MLAPI
{ {
using(BinaryReader reader = new BinaryReader(stream)) using(BinaryReader reader = new BinaryReader(stream))
{ {
m_Animator.SetTrigger(reader.ReadInt32()); animator.SetTrigger(reader.ReadInt32());
} }
} }
} }
void WriteParameters(BinaryWriter writer, bool autoSend) private void WriteParameters(BinaryWriter writer, bool autoSend)
{ {
if (m_AnimatorParameters == null) m_AnimatorParameters = m_Animator.parameters; if (animatorParameters == null)
for (int i = 0; i < m_AnimatorParameters.Length; i++) animatorParameters = animator.parameters;
for (int i = 0; i < animatorParameters.Length; i++)
{ {
if (autoSend && !GetParameterAutoSend(i)) if (autoSend && !GetParameterAutoSend(i))
continue; continue;
AnimatorControllerParameter par = m_AnimatorParameters[i]; AnimatorControllerParameter par = animatorParameters[i];
if (par.type == AnimatorControllerParameterType.Int) if (par.type == AnimatorControllerParameterType.Int)
{ {
writer.Write((uint)m_Animator.GetInteger(par.nameHash)); writer.Write((uint)animator.GetInteger(par.nameHash));
SetSendTrackingParam(par.name + ":" + m_Animator.GetInteger(par.nameHash), i); SetSendTrackingParam(par.name + ":" + animator.GetInteger(par.nameHash), i);
} }
if (par.type == AnimatorControllerParameterType.Float) if (par.type == AnimatorControllerParameterType.Float)
{ {
writer.Write(m_Animator.GetFloat(par.nameHash)); writer.Write(animator.GetFloat(par.nameHash));
SetSendTrackingParam(par.name + ":" + m_Animator.GetFloat(par.nameHash), i); SetSendTrackingParam(par.name + ":" + animator.GetFloat(par.nameHash), i);
} }
if (par.type == AnimatorControllerParameterType.Bool) if (par.type == AnimatorControllerParameterType.Bool)
{ {
writer.Write(m_Animator.GetBool(par.nameHash)); writer.Write(animator.GetBool(par.nameHash));
SetSendTrackingParam(par.name + ":" + m_Animator.GetBool(par.nameHash), i); SetSendTrackingParam(par.name + ":" + animator.GetBool(par.nameHash), i);
} }
} }
} }
void ReadParameters(BinaryReader reader, bool autoSend) private void ReadParameters(BinaryReader reader, bool autoSend)
{ {
if (m_AnimatorParameters == null) m_AnimatorParameters = m_Animator.parameters; if (animatorParameters == null)
for (int i = 0; i < m_AnimatorParameters.Length; i++) animatorParameters = animator.parameters;
for (int i = 0; i < animatorParameters.Length; i++)
{ {
if (autoSend && !GetParameterAutoSend(i)) if (autoSend && !GetParameterAutoSend(i))
continue; continue;
AnimatorControllerParameter par = m_AnimatorParameters[i]; AnimatorControllerParameter par = animatorParameters[i];
if (par.type == AnimatorControllerParameterType.Int) if (par.type == AnimatorControllerParameterType.Int)
{ {
int newValue = (int)reader.ReadUInt32(); int newValue = (int)reader.ReadUInt32();
m_Animator.SetInteger(par.nameHash, newValue); animator.SetInteger(par.nameHash, newValue);
SetRecvTrackingParam(par.name + ":" + newValue, i); SetRecvTrackingParam(par.name + ":" + newValue, i);
} }
@ -298,7 +297,7 @@ namespace MLAPI
if (par.type == AnimatorControllerParameterType.Float) if (par.type == AnimatorControllerParameterType.Float)
{ {
float newFloatValue = reader.ReadSingle(); float newFloatValue = reader.ReadSingle();
m_Animator.SetFloat(par.nameHash, newFloatValue); animator.SetFloat(par.nameHash, newFloatValue);
SetRecvTrackingParam(par.name + ":" + newFloatValue, i); SetRecvTrackingParam(par.name + ":" + newFloatValue, i);
} }
@ -306,7 +305,7 @@ namespace MLAPI
if (par.type == AnimatorControllerParameterType.Bool) if (par.type == AnimatorControllerParameterType.Bool)
{ {
bool newBoolValue = reader.ReadBoolean(); bool newBoolValue = reader.ReadBoolean();
m_Animator.SetBool(par.nameHash, newBoolValue); animator.SetBool(par.nameHash, newBoolValue);
SetRecvTrackingParam(par.name + ":" + newBoolValue, i); SetRecvTrackingParam(par.name + ":" + newBoolValue, i);
} }