Files
Silly-Home/Packages/com.vrchat.worlds/Integrations/ClientSim/Runtime/Helpers/ClientSimPositionSyncedHelperBase.cs
2026-06-07 16:58:24 +01:00

151 lines
4.4 KiB
C#

using UnityEngine;
namespace VRC.SDK3.ClientSim
{
[AddComponentMenu("")]
public abstract class ClientSimPositionSyncedHelperBase :
ClientSimBehaviour,
IClientSimSyncable,
IClientSimPositionSyncable,
IClientSimRespawnHandler
{
private int _ownerID = 1;
private Vector3 _originalPosition;
private Quaternion _originalRotation;
private Rigidbody _rigidbody;
private bool _useGravity;
private bool _isKinematic;
private IClientSimSyncedObjectManager _syncedObjectManager;
public bool SyncPosition { get; protected set; }
protected override void Awake()
{
base.Awake();
_originalPosition = transform.position;
_originalRotation = transform.rotation;
_rigidbody = GetComponent<Rigidbody>();
if (_rigidbody != null)
{
_isKinematic = _rigidbody.isKinematic;
_useGravity = _rigidbody.useGravity;
}
}
public virtual void Initialize(IClientSimSyncedObjectManager syncedObjectManager)
{
_syncedObjectManager = syncedObjectManager;
_syncedObjectManager.AddSyncedObject(this);
}
protected virtual void OnDestroy()
{
// Nullable needed for uninitialized case.
_syncedObjectManager?.RemoveSyncedObject(this);
}
public void TeleportTo(Vector3 position, Quaternion rotation)
{
this.Log($"Teleporting Object {Tools.GetGameObjectPath(gameObject)} to {position} and rotation {rotation.eulerAngles}");
FlagDiscontinuity();
transform.SetPositionAndRotation(position, rotation);
}
public void FlagDiscontinuity()
{
// TODO As of right now, ClientSim doesn't handle any actual sync.
}
#region IClientSimSyncable
public int GetOwner()
{
return _ownerID;
}
public void SetOwner(int ownerID)
{
_ownerID = ownerID;
}
#endregion
#region IClientSimRespawnable
public void Respawn()
{
this.Log($"Respawning Object {Tools.GetGameObjectPath(gameObject)}");
TeleportTo(_originalPosition, _originalRotation);
if (_rigidbody != null)
{
_rigidbody.velocity = Vector3.zero;
}
}
#endregion
#region IClientSimPositionSyncable
public void SetIsKinematic(bool value)
{
_isKinematic = value;
if (_rigidbody)
{
_rigidbody.isKinematic = value;
}
}
public void SetUseGravity(bool value)
{
_useGravity = value;
if (_rigidbody)
{
_rigidbody.useGravity = value;
}
}
public bool GetIsKinematic()
{
return _rigidbody && _rigidbody.isKinematic;
}
public bool GetUseGravity()
{
return _rigidbody && _rigidbody.useGravity;
}
public void UpdatePositionSync()
{
if (_rigidbody != null)
{
// TODO if user is not the owner, set useGravity to false, isKinematic to true.
// This would better simulate ownership, but also make testing awkward.
if (_rigidbody.isKinematic != _isKinematic)
{
_rigidbody.isKinematic = _isKinematic;
this.LogWarning($"Rigidbody.isKinematic was set outside of VRCObjectSync.SetKinematic method! {Tools.GetGameObjectPath(gameObject)}");
}
if (_rigidbody.useGravity != _useGravity)
{
_rigidbody.useGravity = _useGravity;
this.LogWarning($"Rigidbody.useGravity was set outside of VRCObjectSync.SetGravity method! {Tools.GetGameObjectPath(gameObject)}");
}
// VRChatBug: Modifying a collider's "is Trigger" property is also restricted when VRCObjectSync is on
// the same object, but this check will not be added.
}
}
public Transform GetTransform() => transform;
#endregion
}
}