feat: Add NetworkRigidbody extension (#35)

* Added NetworkRigidbody component

* Added readme

* docs: Include NetworkRigidbody in readme

Co-authored-by: Luke Stampfli <43687322+LukeStampfli@users.noreply.github.com>
This commit is contained in:
becksebenius-unity 2021-04-08 01:48:10 -07:00 коммит произвёл GitHub
Родитель ea6c2d8db0
Коммит 891c9889a2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 193 добавлений и 0 удалений

Просмотреть файл

@ -38,6 +38,7 @@ Check our [contribution guidelines](CONTRIBUTING.md) for information on how to c
|:------------:|:-------------:|:-------:|:---:|
|**[NetworkObjectPool](/com.mlapi.contrib.extensions/Runtime/NetworkObjectPool)**| | :heavy_check_mark: | |
|**[NetworkManagerHud](/com.mlapi.contrib.extensions/Runtime/NetworkManagerHud)**| | :heavy_check_mark: | |
|**[NetworkRigidBody](/com.mlapi.contrib.extensions/Runtime/NetworkRigidbody)**| | :heavy_check_mark: | |
### Releases

Просмотреть файл

@ -0,0 +1,174 @@
using System;
using MLAPI;
using MLAPI.NetworkVariable;
using UnityEngine;
public class NetworkRigidbody : NetworkBehaviour
{
public NetworkVariableVector3 netVelocity = new NetworkVariableVector3(NetworkVariableSettingsUtility.OwnerWrite);
public NetworkVariableVector3 netAngularVelocity = new NetworkVariableVector3(NetworkVariableSettingsUtility.OwnerWrite);
public NetworkVariableVector3 netPosition = new NetworkVariableVector3(NetworkVariableSettingsUtility.OwnerWrite);
public NetworkVariableQuaternion netRotation = new NetworkVariableQuaternion(NetworkVariableSettingsUtility.OwnerWrite);
public NetworkVariableUInt netUpdateId = new NetworkVariableUInt(NetworkVariableSettingsUtility.OwnerWrite);
[SerializeField]
bool m_SyncVelocity = true;
[SerializeField]
bool m_SyncAngularVelocity = true;
[SerializeField]
bool m_SyncPosition = true;
[SerializeField]
bool m_SyncRotation = true;
[SerializeField]
float m_InterpolationTime;
[Serializable]
struct InterpolationState
{
public Vector3 PositionDelta;
public Quaternion RotationDelta;
public Vector3 VelocityDelta;
public Vector3 AngularVelocityDelta;
public float TimeRemaining;
public float TotalTime;
}
uint m_InterpolationChangeId;
InterpolationState m_InterpolationState;
Rigidbody m_Rigidbody;
void Awake()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
void BeginInterpolation()
{
m_InterpolationState = new InterpolationState()
{
PositionDelta = netPosition.Value - m_Rigidbody.position,
RotationDelta = Quaternion.Inverse(m_Rigidbody.rotation) * netRotation.Value,
VelocityDelta = netVelocity.Value - m_Rigidbody.velocity,
AngularVelocityDelta = netAngularVelocity.Value - m_Rigidbody.angularVelocity,
TimeRemaining = m_InterpolationTime,
TotalTime = m_InterpolationTime
};
}
void FixedUpdate()
{
if (!NetworkVariablesInitialized())
{
return;
}
if (IsOwner)
{
bool changed = false;
if (m_SyncPosition)
{
changed |= TryUpdate(netPosition, m_Rigidbody.position);
}
if (m_SyncRotation)
{
changed |= TryUpdate(netRotation, m_Rigidbody.rotation);
}
if (m_SyncVelocity)
{
changed |= TryUpdate(netVelocity, m_Rigidbody.velocity);
}
if (m_SyncAngularVelocity)
{
changed |= TryUpdate(netAngularVelocity, m_Rigidbody.angularVelocity);
}
if (changed)
{
netUpdateId.Value++;
}
}
else
{
if (m_InterpolationChangeId != netUpdateId.Value)
{
BeginInterpolation();
m_InterpolationChangeId = netUpdateId.Value;
}
float deltaTime = Time.fixedDeltaTime;
if (0 < m_InterpolationState.TimeRemaining)
{
deltaTime = Mathf.Min(deltaTime, m_InterpolationState.TimeRemaining);
m_InterpolationState.TimeRemaining -= deltaTime;
deltaTime /= m_InterpolationState.TotalTime;
if (m_SyncPosition)
{
m_Rigidbody.position +=
m_InterpolationState.PositionDelta * deltaTime;
}
if (m_SyncRotation)
{
m_Rigidbody.rotation =
m_Rigidbody.rotation * Quaternion.Slerp(Quaternion.identity, m_InterpolationState.RotationDelta, deltaTime);
}
if (m_SyncVelocity)
{
m_Rigidbody.velocity +=
m_InterpolationState.VelocityDelta * deltaTime;
}
if (m_SyncAngularVelocity)
{
m_Rigidbody.angularVelocity +=
m_InterpolationState.AngularVelocityDelta * deltaTime;
}
}
}
}
bool NetworkVariablesInitialized()
{
return netVelocity.Settings.WritePermission == NetworkVariablePermission.OwnerOnly;
}
static bool TryUpdate(NetworkVariableVector3 variable, Vector3 value)
{
var current = variable.Value;
if (Mathf.Approximately(current.x, value.x)
&& Mathf.Approximately(current.y, value.y)
&& Mathf.Approximately(current.z, value.z))
{
return false;
}
variable.Value = value;
return true;
}
static bool TryUpdate(NetworkVariableQuaternion variable, Quaternion value)
{
var current = variable.Value;
if (Mathf.Approximately(current.x, value.x)
&& Mathf.Approximately(current.y, value.y)
&& Mathf.Approximately(current.z, value.z)
&& Mathf.Approximately(current.w, value.w))
{
return false;
}
variable.Value = value;
return true;
}
}

Просмотреть файл

@ -0,0 +1,18 @@
# NetworkRigidbody
Provides a component that replicates a rigidbody's properties over the network. Supports client authority via NetworkObject Ownership. You can also select which properties you want to sync.
Synced properties:
- `Rigidbody.position`
- `Rigidbody.rotation`
- `Rigidbody.velocity`
- `Rigidbody.angularVelocity`
## Interpolation
NetworkRigidbody is linearly interpolated. The interpolation time can be set as a serialized property on the component. Interpolation resets each time network variables are updated.
## Prediction
NetworkRigidbody does not suppress local physics. NetworkObjects not under ownership by the local client will continue to simulate so that movement appears smooth. Rubber banding will be most obvious in scenarios of volatile latency or mixed-ownership collisions.