using System.IO; using UnityEngine; using UnityEngine.Serialization; namespace VelNet { /// /// A simple class that will sync the position and rotation of a network object with a rigidbody /// This only uses the rigidbody for interpolation - it doesn't do any interpolatin itself /// [AddComponentMenu("VelNet/VelNet Sync Rigidbody")] [RequireComponent(typeof(Rigidbody))] public class SyncRigidbody : SyncState { public bool useLocalTransform; public float minPosDelta = .01f; public float minAngleDelta = .1f; public float minVelDelta = .01f; public float minAngVelDelta = .1f; public bool syncKinematic = true; public bool syncGravity = true; public bool syncVelocity = true; public bool syncAngularVelocity = true; private Vector3 targetPosition; private Quaternion targetRotation; private Vector3 targetVel; private Vector3 targetAngVel; private float distanceAtReceiveTime; private float angleAtReceiveTime; private Rigidbody rb; private void Start() { rb = GetComponent(); if (useLocalTransform) { targetPosition = transform.localPosition; targetRotation = transform.localRotation; } else { targetPosition = transform.position; targetRotation = transform.rotation; } } /// /// This gets called at serializationRateHz when the object is locally owned /// protected override void SendState(BinaryWriter writer) { if (useLocalTransform) { writer.Write(transform.localPosition); writer.Write(transform.localRotation); } else { writer.Write(transform.position); writer.Write(transform.rotation); } if (syncVelocity) writer.Write(rb.velocity); if (syncAngularVelocity) writer.Write(rb.angularVelocity); // writer.Write((new bool[] {rb.isKinematic, rb.useGravity}).GetBitmasks()); if (syncKinematic) writer.Write(rb.isKinematic); if (syncGravity) writer.Write(rb.useGravity); } /// /// This gets called whenever a message about the state of this object is received. /// Usually at serializationRateHz. /// protected override void ReceiveState(BinaryReader reader) { targetPosition = reader.ReadVector3(); targetRotation = reader.ReadQuaternion(); if (syncVelocity) targetVel = reader.ReadVector3(); if (syncAngularVelocity) targetAngVel = reader.ReadVector3(); if (syncKinematic) rb.isKinematic = reader.ReadBoolean(); if (syncGravity) rb.useGravity = reader.ReadBoolean(); // record the distance from the target for interpolation if (useLocalTransform) { distanceAtReceiveTime = Vector3.Distance(targetPosition, transform.localPosition); angleAtReceiveTime = Quaternion.Angle(targetRotation, transform.localRotation); if (minPosDelta < distanceAtReceiveTime) { transform.localPosition = targetPosition; } if (minAngleDelta < angleAtReceiveTime) { transform.localRotation = targetRotation; } } else { distanceAtReceiveTime = Vector3.Distance(targetPosition, transform.position); angleAtReceiveTime = Quaternion.Angle(targetRotation, transform.rotation); if (minPosDelta < distanceAtReceiveTime) { transform.position = targetPosition; } if (minAngleDelta < angleAtReceiveTime) { transform.rotation = targetRotation; } } float velDelta = Vector3.Distance(targetVel, rb.velocity); float angVelDelta = Vector3.Distance(targetAngVel, rb.angularVelocity); if (velDelta > minVelDelta) { rb.velocity = targetVel; } if (angVelDelta > minAngVelDelta) { rb.angularVelocity = targetAngVel; } } } }