using UnityEngine;
namespace Fusion.Addons.Physics {
using Physics = UnityEngine.Physics;
///
/// Fusion synchronization component for Unity Rigidbody.
///
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody))]
[NetworkBehaviourWeaved(NetworkRBData.WORDS)]
public class NetworkRigidbody3D : NetworkRigidbody {
///
public override Vector3 RBPosition {
get => _rigidbody.position;
set => _rigidbody.position = value;
}
///
public override Quaternion RBRotation {
get =>_rigidbody.rotation;
set => _rigidbody.rotation = value;
}
///
public override bool RBIsKinematic {
get => _rigidbody.isKinematic;
set => _rigidbody.isKinematic = value;
}
///
protected override void Awake() {
base.Awake();
#if UNITY_2022_3_OR_NEWER
AutoSimulateIsEnabled = Physics.simulationMode != SimulationMode.Script;
#else
AutoSimulateIsEnabled = Physics.autoSimulation;
#endif
}
///
protected override bool GetRBIsKinematic(Rigidbody rb) {
return rb.isKinematic;
}
///
protected override void SetRBIsKinematic(Rigidbody rb, bool kinematic) {
if (rb.isKinematic != kinematic) {
rb.isKinematic = kinematic;
}
}
///
protected override void CaptureRBPositionRotation(Rigidbody rb, ref NetworkRBData data) {
data.TRSPData.Position = rb.position;
if (UsePreciseRotation) {
data.FullPrecisionRotation = rb.rotation;
} else {
data.TRSPData.Rotation = rb.rotation;
}
}
///
protected override void ApplyRBPositionRotation(Rigidbody rb, Vector3 pos, Quaternion rot) {
rb.position = pos;
rb.rotation = rot;
}
///
protected override NetworkRigidbodyFlags GetRBFlags(Rigidbody rb) {
var flags = default(NetworkRigidbodyFlags);
if (rb.isKinematic) { flags |= NetworkRigidbodyFlags.IsKinematic; }
if (rb.IsSleeping()) { flags |= NetworkRigidbodyFlags.IsSleeping; }
if (rb.useGravity) { flags |= NetworkRigidbodyFlags.UseGravity; }
return flags;
}
///
protected override int GetRBConstraints(Rigidbody rb) {
return (int)rb.constraints;
}
///
protected override void SetRBConstraints(Rigidbody rb, int constraints) {
rb.constraints = (RigidbodyConstraints)constraints;
}
///
protected override void CaptureExtras(Rigidbody rb, ref NetworkRBData data) {
data.Mass = rb.mass;
data.Drag = rb.linearDamping;
data.AngularDrag = rb.angularDamping;
data.LinearVelocity = rb.linearVelocity;
data.AngularVelocity = rb.angularVelocity;
}
///
protected override void ApplyExtras(Rigidbody rb, ref NetworkRBData data) {
rb.mass = data.Mass;
rb.linearDamping = data.Drag;
rb.angularDamping = data.AngularDrag;
rb.linearVelocity = data.LinearVelocity;
rb.angularVelocity = data.AngularVelocity;
}
///
public override void ResetRigidbody() {
base.ResetRigidbody();
var rb = _rigidbody;
if (!rb.isKinematic) {
rb.linearVelocity = default;
rb.angularVelocity = default;
}
}
///
protected override bool IsRBSleeping(Rigidbody rb) => rb.IsSleeping();
///
protected override void ForceRBSleep(Rigidbody rb) => rb.Sleep();
///
protected override void ForceRBWake( Rigidbody rb) => rb.WakeUp();
///
protected override bool IsRigidbodyBelowSleepingThresholds(Rigidbody rb) {
var energy = rb.mass * rb.linearVelocity.sqrMagnitude;
var angVel = rb.angularVelocity;
var inertia = rb.inertiaTensor;
energy += inertia.x * (angVel.x * angVel.x);
energy += inertia.y * (angVel.y * angVel.y);
energy += inertia.z * (angVel.z * angVel.z);
// Mass-normalized
energy /= 2.0f * rb.mass;
return energy <= Physics.sleepThreshold;
}
///
protected override bool IsStateBelowSleepingThresholds(NetworkRBData data) {
var energy = data.Mass * ((Vector3)data.LinearVelocity).sqrMagnitude;
var angVel = ((Vector3)data.AngularVelocity);
var inertia = _rigidbody.inertiaTensor;
energy += inertia.x * (angVel.x * angVel.x);
energy += inertia.y * (angVel.y * angVel.y);
energy += inertia.z * (angVel.z * angVel.z);
// Mass-normalized
energy /= 2.0f * data.Mass;
return energy <= Physics.sleepThreshold;
}
}
}