131 lines
3.6 KiB
C#
131 lines
3.6 KiB
C#
using System.IO;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace VelNet
|
|
{
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
[AddComponentMenu("VelNet/VelNet Sync Rigidbody")]
|
|
[RequireComponent(typeof(Rigidbody))]
|
|
public class SyncRigidbody : NetworkSerializedObjectStream
|
|
{
|
|
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<Rigidbody>();
|
|
if (useLocalTransform)
|
|
{
|
|
targetPosition = transform.localPosition;
|
|
targetRotation = transform.localRotation;
|
|
}
|
|
else
|
|
{
|
|
targetPosition = transform.position;
|
|
targetRotation = transform.rotation;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This gets called at serializationRateHz when the object is locally owned
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// This gets called whenever a message about the state of this object is received.
|
|
/// Usually at serializationRateHz.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
} |