[RelativeSync] attempt at fixing jitter (it did not work, it is very broken)

This commit is contained in:
NotAKidoS 2024-05-27 23:25:24 -05:00
parent c46bc61619
commit 85e3499615
6 changed files with 305 additions and 230 deletions

View file

@ -15,6 +15,7 @@ public class RelativeSyncMod : MelonMod
ModNetwork.Subscribe(); ModNetwork.Subscribe();
ApplyPatches(typeof(NetworkRootDataUpdatePatches)); ApplyPatches(typeof(NetworkRootDataUpdatePatches));
ApplyPatches(typeof(CVRSpawnablePatches));
ApplyPatches(typeof(PlayerSetupPatches)); ApplyPatches(typeof(PlayerSetupPatches));
ApplyPatches(typeof(PuppetMasterPatches)); ApplyPatches(typeof(PuppetMasterPatches));

View file

@ -3,24 +3,26 @@ using ABI_RC.Systems.ModNetwork;
using DarkRift; using DarkRift;
using UnityEngine; using UnityEngine;
namespace NAK.RelativeSync.Networking namespace NAK.RelativeSync.Networking;
public static class ModNetwork
{ {
public static class ModNetwork
{
public static bool Debug_NetworkInbound = false; public static bool Debug_NetworkInbound = false;
public static bool Debug_NetworkOutbound = false; public static bool Debug_NetworkOutbound = false;
private static bool _isSubscribedToModNetwork; private static bool _isSubscribedToModNetwork;
private struct RelativeSyncData private struct MovementParentSyncData
{ {
public bool HasSyncedThisData; public bool HasSyncedThisData;
public int MarkerHash; public int MarkerHash;
public Vector3 Position; public Vector3 RootPosition;
public Vector3 Rotation; public Vector3 RootRotation;
public Vector3 HipPosition;
public Vector3 HipRotation;
} }
private static RelativeSyncData _latestRelativeSyncData; private static MovementParentSyncData _latestMovementParentSyncData;
#region Constants #region Constants
@ -32,8 +34,9 @@ namespace NAK.RelativeSync.Networking
private enum MessageType : byte private enum MessageType : byte
{ {
SyncPosition = 0, MovementParentOrChair = 0
RelativeSyncStatus = 1 //RelativePickup = 1,
//RelativeAttachment = 2,
} }
#endregion #endregion
@ -49,34 +52,45 @@ namespace NAK.RelativeSync.Networking
Debug.LogError("Failed to subscribe to Mod Network!"); Debug.LogError("Failed to subscribe to Mod Network!");
} }
// Called right after NetworkRootDataUpdate.Submit()
internal static void SendRelativeSyncUpdate() internal static void SendRelativeSyncUpdate()
{ {
if (!_isSubscribedToModNetwork) if (!_isSubscribedToModNetwork)
return; return;
if (!_latestRelativeSyncData.HasSyncedThisData) if (_latestMovementParentSyncData.HasSyncedThisData)
{ return;
SendMessage(MessageType.SyncPosition, _latestRelativeSyncData.MarkerHash,
_latestRelativeSyncData.Position, _latestRelativeSyncData.Rotation); SendMessage(MessageType.MovementParentOrChair, _latestMovementParentSyncData.MarkerHash,
_latestRelativeSyncData.HasSyncedThisData = true; _latestMovementParentSyncData.RootPosition, _latestMovementParentSyncData.RootRotation,
} _latestMovementParentSyncData.HipPosition, _latestMovementParentSyncData.HipRotation);
_latestMovementParentSyncData.HasSyncedThisData = true;
} }
private static void SetLatestRelativeSync(int markerHash, Vector3 position, Vector3 rotation) public static void SetLatestRelativeSync(
int markerHash,
Vector3 position, Vector3 rotation,
Vector3 hipPosition, Vector3 hipRotation)
{ {
// check if the data has changed // check if the data has changed
if (_latestRelativeSyncData.MarkerHash == markerHash if (_latestMovementParentSyncData.MarkerHash == markerHash
&& _latestRelativeSyncData.Position == position && _latestMovementParentSyncData.RootPosition == position
&& _latestRelativeSyncData.Rotation == rotation) && _latestMovementParentSyncData.RootRotation == rotation
return; // no need to update && _latestMovementParentSyncData.HipPosition == hipPosition
&& _latestMovementParentSyncData.HipRotation == hipRotation)
return; // no need to update (shocking)
_latestRelativeSyncData.HasSyncedThisData = false; // reset _latestMovementParentSyncData.HasSyncedThisData = false; // reset
_latestRelativeSyncData.MarkerHash = markerHash; _latestMovementParentSyncData.MarkerHash = markerHash;
_latestRelativeSyncData.Position = position; _latestMovementParentSyncData.RootPosition = position;
_latestRelativeSyncData.Rotation = rotation; _latestMovementParentSyncData.RootRotation = rotation;
_latestMovementParentSyncData.HipPosition = hipPosition;
_latestMovementParentSyncData.HipRotation = hipRotation;
} }
private static void SendMessage(MessageType messageType, int markerHash, Vector3 position, Vector3 rotation) private static void SendMessage(MessageType messageType, int markerHash, Vector3 position, Vector3 rotation,
Vector3 hipPosition, Vector3 hipRotation)
{ {
if (!IsConnectedToGameNetwork()) if (!IsConnectedToGameNetwork())
return; return;
@ -86,7 +100,13 @@ namespace NAK.RelativeSync.Networking
modMsg.Write(markerHash); modMsg.Write(markerHash);
modMsg.Write(position); modMsg.Write(position);
modMsg.Write(rotation); modMsg.Write(rotation);
modMsg.Write(hipPosition);
modMsg.Write(hipRotation);
modMsg.Send(); modMsg.Send();
if (Debug_NetworkOutbound)
Debug.Log(
$"[Outbound] MessageType: {messageType}, MarkerHash: {markerHash}, Position: {position}, Rotation: {rotation}, HipPosition: {hipPosition}, HipRotation: {hipRotation}");
} }
private static void OnMessageReceived(ModNetworkMessage msg) private static void OnMessageReceived(ModNetworkMessage msg)
@ -98,18 +118,17 @@ namespace NAK.RelativeSync.Networking
switch ((MessageType)msgTypeRaw) switch ((MessageType)msgTypeRaw)
{ {
case MessageType.SyncPosition: case MessageType.MovementParentOrChair:
msg.Read(out int markerHash); msg.Read(out int markerHash);
msg.Read(out Vector3 receivedPosition); msg.Read(out Vector3 receivedPosition);
msg.Read(out Vector3 receivedRotation); msg.Read(out Vector3 receivedRotation);
OnNetworkPositionUpdateReceived(msg.Sender, markerHash, receivedPosition, receivedRotation); msg.Read(out Vector3 receivedHipPosition);
msg.Read(out Vector3 receivedHipRotation);
OnNetworkPositionUpdateReceived(msg.Sender, markerHash, receivedPosition, receivedRotation, receivedHipPosition, receivedHipRotation);
if (Debug_NetworkInbound)
Debug.Log($"[Inbound] Sender: {msg.Sender}, MarkerHash: {markerHash}, Position: {receivedPosition}, Rotation: {receivedRotation}, HipPosition: {receivedHipPosition}, HipRotation: {receivedHipRotation}");
break; break;
// case MessageType.RelativeSyncStatus:
// msg.Read(out string guidStr);
// msg.Read(out bool isRelativeSync);
// System.Guid guid = new System.Guid(guidStr);
// OnRelativeSyncStatusReceived(msg.Sender, guid, isRelativeSync);
// break;
default: default:
Debug.LogError($"Invalid message type received from: {msg.Sender}"); Debug.LogError($"Invalid message type received from: {msg.Sender}");
break; break;
@ -118,15 +137,6 @@ namespace NAK.RelativeSync.Networking
#endregion #endregion
#region Public Methods
public static void SendNetworkPosition(int markerHash, Vector3 newPosition, Vector3 newRotation)
{
SetLatestRelativeSync(markerHash, newPosition, newRotation);
}
#endregion
#region Private Methods #region Private Methods
private static bool IsConnectedToGameNetwork() private static bool IsConnectedToGameNetwork()
@ -136,16 +146,11 @@ namespace NAK.RelativeSync.Networking
&& NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected; && NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected;
} }
private static void OnNetworkPositionUpdateReceived(string sender, int markerHash, Vector3 position, Vector3 rotation) private static void OnNetworkPositionUpdateReceived(string sender, int markerHash, Vector3 position,
Vector3 rotation, Vector3 hipPosition, Vector3 hipRotation)
{ {
RelativeSyncManager.ApplyRelativeSync(sender, markerHash, position, rotation); RelativeSyncManager.ApplyRelativeSync(sender, markerHash, position, rotation, hipPosition, hipRotation);
}
private static void OnRelativeSyncStatusReceived(string sender, System.Guid guid, bool isRelativeSync)
{
// todo: implement
} }
#endregion #endregion
}
} }

View file

@ -59,3 +59,24 @@ internal static class NetworkRootDataUpdatePatches
ModNetwork.SendRelativeSyncUpdate(); // Send the relative sync update after the network root data update ModNetwork.SendRelativeSyncUpdate(); // Send the relative sync update after the network root data update
} }
} }
internal static class CVRSpawnablePatches
{
private static bool _allowUpdate;
[HarmonyPrefix]
[HarmonyPatch(typeof(CVRSpawnable), nameof(CVRSpawnable.Update))]
private static bool Prefix_CVRSpawnable_Update()
{
return _allowUpdate;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CVRSpawnable), nameof(CVRSpawnable.FixedUpdate))]
private static void Postfix_CVRSpawnable_FixedUpdate(ref CVRSpawnable __instance)
{
_allowUpdate = true;
__instance.Update();
_allowUpdate = false;
}
}

View file

@ -6,16 +6,13 @@ namespace NAK.RelativeSync.Components;
[DefaultExecutionOrder(int.MaxValue)] // make sure this runs after NetIKController [DefaultExecutionOrder(int.MaxValue)] // make sure this runs after NetIKController
public class RelativeSyncController : MonoBehaviour public class RelativeSyncController : MonoBehaviour
{ {
private static float MaxMagnitude = 750000000000f; private const float MaxMagnitude = 750000000000f;
private float _updateInterval = 0.05f; private float _updateInterval = 0.05f;
private float _lastUpdate; private float _lastUpdate;
private string _userId; private string _userId;
private PuppetMaster puppetMaster { get; set; } private PuppetMaster puppetMaster { get; set; }
private NetIKController netIkController { get; set; }
// private bool _syncMarkerChangedSinceLastSync;
private RelativeSyncMarker _relativeSyncMarker; private RelativeSyncMarker _relativeSyncMarker;
private RelativeSyncData _relativeSyncData; private RelativeSyncData _relativeSyncData;
@ -26,7 +23,6 @@ public class RelativeSyncController : MonoBehaviour
private void Start() private void Start()
{ {
puppetMaster = GetComponent<PuppetMaster>(); puppetMaster = GetComponent<PuppetMaster>();
netIkController = GetComponent<NetIKController>();
_userId = puppetMaster._playerDescriptor.ownerId; _userId = puppetMaster._playerDescriptor.ownerId;
RelativeSyncManager.RelativeSyncControllers.Add(_userId, this); RelativeSyncManager.RelativeSyncControllers.Add(_userId, this);
@ -50,66 +46,76 @@ public class RelativeSyncController : MonoBehaviour
return; return;
Transform avatarTransform = animator.transform; Transform avatarTransform = animator.transform;
Transform hipTrans = (animator.avatar != null && animator.isHuman)
? animator.GetBoneTransform(HumanBodyBones.Hips) : null;
Vector3 worldRootPos = avatarTransform.position; // TODO: handle the case where hip is not synced but is found on remote client
Quaternion worldRootRot = avatarTransform.rotation;
Vector3 relativeHipPos = default;
Quaternion relativeHipRot = default;
Transform hipTrans = animator.GetBoneTransform(HumanBodyBones.Hips);
if (hipTrans != null)
{
Vector3 hipPos = hipTrans.position;
Quaternion hipRot = hipTrans.rotation;
relativeHipPos = Quaternion.Inverse(worldRootRot) * (hipPos - worldRootPos);
relativeHipRot = Quaternion.Inverse(worldRootRot) * hipRot;
}
float lerp = Mathf.Min((Time.time - _lastUpdate) / _updateInterval, 1f); float lerp = Mathf.Min((Time.time - _lastUpdate) / _updateInterval, 1f);
Vector3 targetLocalPosition = _relativeSyncData.LocalRootPosition; ApplyRelativeRotation(avatarTransform, hipTrans, lerp);
Quaternion targetLocalRotation = Quaternion.Euler(_relativeSyncData.LocalRootRotation); ApplyRelativePosition(hipTrans, lerp);
Transform targetTransform = _relativeSyncMarker.transform;
if (_relativeSyncMarker.ApplyRelativeRotation && _relativeSyncData.LocalRootRotation.sqrMagnitude < MaxMagnitude) avatarTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); // idk if needed
}
private void ApplyRelativeRotation(Transform avatarTransform, Transform hipTransform, float lerp)
{ {
Quaternion rotation = targetTransform.rotation; if (!_relativeSyncMarker.ApplyRelativeRotation ||
Quaternion worldRotation = rotation * targetLocalRotation; !(_relativeSyncData.LocalRootRotation.sqrMagnitude < MaxMagnitude))
Quaternion lastRotation = rotation * Quaternion.Euler(_lastSyncData.LocalRootRotation); return; // not applying relative rotation or data is invalid
Quaternion markerRotation = _relativeSyncMarker.transform.rotation;
Quaternion lastWorldRotation = markerRotation * Quaternion.Euler(_lastSyncData.LocalRootRotation);
Quaternion worldRotation = markerRotation * Quaternion.Euler(_relativeSyncData.LocalRootRotation);
Quaternion lastWorldHipRotation = markerRotation * Quaternion.Euler(_lastSyncData.LocalHipRotation);
Quaternion worldHipRotation = markerRotation * Quaternion.Euler(_relativeSyncData.LocalHipRotation);
if (_relativeSyncMarker.OnlyApplyRelativeHeading) if (_relativeSyncMarker.OnlyApplyRelativeHeading)
{ {
Vector3 currentForward = lastRotation * Vector3.forward; Vector3 currentWorldUp = avatarTransform.up;
Vector3 targetForward = worldRotation * Vector3.forward;
Vector3 currentWorldUp = avatarTransform.up; // up direction of player before we touch it
// project forward vectors to the ground plane Vector3 currentForward = lastWorldRotation * Vector3.forward;
Vector3 targetForward = worldRotation * Vector3.forward;
currentForward = Vector3.ProjectOnPlane(currentForward, currentWorldUp).normalized; currentForward = Vector3.ProjectOnPlane(currentForward, currentWorldUp).normalized;
targetForward = Vector3.ProjectOnPlane(targetForward, currentWorldUp).normalized; targetForward = Vector3.ProjectOnPlane(targetForward, currentWorldUp).normalized;
lastWorldRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
lastRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
worldRotation = Quaternion.LookRotation(targetForward, currentWorldUp); worldRotation = Quaternion.LookRotation(targetForward, currentWorldUp);
}
transform.rotation = Quaternion.Slerp(lastRotation, worldRotation, lerp); if (hipTransform != null)
}
if (_relativeSyncMarker.ApplyRelativePosition && _relativeSyncData.LocalRootPosition.sqrMagnitude < MaxMagnitude)
{ {
Vector3 worldPosition = targetTransform.TransformPoint(targetLocalPosition); currentForward = lastWorldHipRotation * Vector3.forward;
transform.position = Vector3.Lerp(targetTransform.TransformPoint(_lastSyncData.LocalRootPosition), worldPosition, lerp); targetForward = worldHipRotation * Vector3.forward;
currentForward = Vector3.ProjectOnPlane(currentForward, currentWorldUp).normalized;
targetForward = Vector3.ProjectOnPlane(targetForward, currentWorldUp).normalized;
lastWorldHipRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
worldHipRotation = Quaternion.LookRotation(targetForward, currentWorldUp);
}
} }
// negate avatar transform movement transform.rotation = Quaternion.Slerp(lastWorldRotation, worldRotation, lerp);
avatarTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); if (hipTransform != null) hipTransform.rotation = Quaternion.Slerp(lastWorldHipRotation, worldHipRotation, lerp);
}
// fix hip syncing because it is not relative to root, it is synced in world space -_- private void ApplyRelativePosition(Transform hipTransform, float lerp)
if (hipTrans != null)
{ {
hipTrans.position = transform.position + transform.rotation * relativeHipPos; if (!_relativeSyncMarker.ApplyRelativePosition ||
hipTrans.rotation = transform.rotation * relativeHipRot; !(_relativeSyncData.LocalRootPosition.sqrMagnitude < MaxMagnitude))
} return; // not applying relative position or data is invalid
Transform targetTransform = _relativeSyncMarker.transform;
Vector3 lastWorldPosition = targetTransform.TransformPoint(_lastSyncData.LocalRootPosition);
Vector3 worldPosition = targetTransform.TransformPoint(_relativeSyncData.LocalRootPosition);
transform.position = Vector3.Lerp(lastWorldPosition, worldPosition, lerp);
if (hipTransform == null)
return;
Vector3 lastWorldHipPosition = targetTransform.TransformPoint(_lastSyncData.LocalHipPosition);
Vector3 worldHipPosition = targetTransform.TransformPoint(_relativeSyncData.LocalHipPosition);
hipTransform.position = Vector3.Lerp(lastWorldHipPosition, worldHipPosition, lerp);
} }
#endregion Unity Events #endregion Unity Events
@ -124,21 +130,28 @@ public class RelativeSyncController : MonoBehaviour
_relativeSyncMarker = target; _relativeSyncMarker = target;
// calculate relative position and rotation so lerp can smooth it out (hack) // calculate relative position and rotation so lerp can smooth it out (hack)
if (_relativeSyncMarker != null) if (_relativeSyncMarker == null)
{ return;
Transform avatarTransform = puppetMaster._animator.transform;
Transform markerTransform = _relativeSyncMarker.transform; Animator avatarAnimator = puppetMaster._animator;
Vector3 localPosition = markerTransform.InverseTransformPoint(avatarTransform.position); if (avatarAnimator == null)
Quaternion localRotation = Quaternion.Inverse(markerTransform.rotation) * avatarTransform.rotation; return; // i dont care to bother
RelativeSyncManager.GetRelativeAvatarPositionsFromMarker(
avatarAnimator, _relativeSyncMarker.transform,
out Vector3 relativePosition, out Vector3 relativeRotation,
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation);
// set last sync data to current position and rotation so we don't lerp from the last marker // set last sync data to current position and rotation so we don't lerp from the last marker
_lastSyncData.LocalRootPosition = localPosition; _lastSyncData.LocalRootPosition = relativePosition;
_lastSyncData.LocalRootRotation = localRotation.eulerAngles; _lastSyncData.LocalRootRotation = relativeRotation;
//Debug.Log($"SetRelativeSyncMarker: {_relativeSyncMarker.name}"); _lastSyncData.LocalHipPosition = relativeHipPosition;
} _lastSyncData.LocalHipRotation = relativeHipRotation;
} }
public void SetRelativePositions(Vector3 position, Vector3 rotation) public void SetRelativePositions(
Vector3 position, Vector3 rotation,
Vector3 hipPosition, Vector3 hipRotation)
{ {
// calculate update interval // calculate update interval
float prevUpdate = _lastUpdate; float prevUpdate = _lastUpdate;
@ -146,19 +159,22 @@ public class RelativeSyncController : MonoBehaviour
_updateInterval = _lastUpdate - prevUpdate; _updateInterval = _lastUpdate - prevUpdate;
// cycle last sync data // cycle last sync data
_lastSyncData.LocalRootPosition = _relativeSyncData.LocalRootPosition; _lastSyncData = _relativeSyncData;
_lastSyncData.LocalRootRotation = _relativeSyncData.LocalRootRotation;
// set new sync data // set new sync data
_relativeSyncData.LocalRootPosition = position; _relativeSyncData.LocalRootPosition = position;
_relativeSyncData.LocalRootRotation = rotation; _relativeSyncData.LocalRootRotation = rotation;
_relativeSyncData.LocalHipPosition = hipPosition;
_relativeSyncData.LocalHipRotation = hipRotation;
} }
#endregion Public Methods #endregion Public Methods
public struct RelativeSyncData private struct RelativeSyncData
{ {
public Vector3 LocalRootPosition; public Vector3 LocalRootPosition;
public Vector3 LocalRootRotation; public Vector3 LocalRootRotation;
public Vector3 LocalHipPosition;
public Vector3 LocalHipRotation;
} }
} }

View file

@ -38,7 +38,19 @@ public class RelativeSyncMonitor : MonoBehaviour
_lastRelativeSyncMarker = _relativeSyncMarker; _lastRelativeSyncMarker = _relativeSyncMarker;
SendCurrentPositionAndRotation(); Animator avatarAnimator = PlayerSetup.Instance._animator;
if (avatarAnimator == null)
return; // i dont care to bother
RelativeSyncManager.GetRelativeAvatarPositionsFromMarker(
avatarAnimator, _relativeSyncMarker.transform,
out Vector3 relativePosition, out Vector3 relativeRotation,
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation);
ModNetwork.SetLatestRelativeSync(
_relativeSyncMarker.pathHash,
relativePosition, relativeRotation,
relativeHipPosition, relativeHipRotation);
} }
private void CheckForRelativeSyncMarker() private void CheckForRelativeSyncMarker()
@ -61,22 +73,9 @@ public class RelativeSyncMonitor : MonoBehaviour
_relativeSyncMarker = null; _relativeSyncMarker = null;
} }
private void SendCurrentPositionAndRotation()
{
// because our syncing is retarded, we need to sync relative from the avatar root...
Transform avatarRoot = PlayerSetup.Instance._avatar.transform;
Vector3 avatarRootPosition = avatarRoot.position; // PlayerSetup.Instance.GetPlayerPosition()
Quaternion avatarRootRotation = avatarRoot.rotation; // PlayerSetup.Instance.GetPlayerRotation()
Transform markerTransform = _relativeSyncMarker.transform;
Vector3 localPosition = markerTransform.InverseTransformPoint(avatarRootPosition);
Quaternion localRotation = Quaternion.Inverse(markerTransform.rotation) * avatarRootRotation;
ModNetwork.SendNetworkPosition(_relativeSyncMarker.pathHash, localPosition, localRotation.eulerAngles);
}
private void SendEmptyPositionAndRotation() private void SendEmptyPositionAndRotation()
{ {
ModNetwork.SendNetworkPosition(RelativeSyncManager.NoTarget, Vector3.zero, Vector3.zero); ModNetwork.SetLatestRelativeSync(RelativeSyncManager.NoTarget,
Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero);
} }
} }

View file

@ -12,7 +12,10 @@ public static class RelativeSyncManager
public static readonly Dictionary<int, RelativeSyncMarker> RelativeSyncTransforms = new(); public static readonly Dictionary<int, RelativeSyncMarker> RelativeSyncTransforms = new();
public static readonly Dictionary<string, RelativeSyncController> RelativeSyncControllers = new(); public static readonly Dictionary<string, RelativeSyncController> RelativeSyncControllers = new();
public static void ApplyRelativeSync(string userId, int target, Vector3 position, Vector3 rotation) public static void ApplyRelativeSync(
string userId, int target,
Vector3 position, Vector3 rotation,
Vector3 hipPosition, Vector3 hipRotation)
{ {
if (!RelativeSyncControllers.TryGetValue(userId, out RelativeSyncController controller)) if (!RelativeSyncControllers.TryGetValue(userId, out RelativeSyncController controller))
if (CVRPlayerManager.Instance.GetPlayerPuppetMaster(userId, out PuppetMaster pm)) if (CVRPlayerManager.Instance.GetPlayerPuppetMaster(userId, out PuppetMaster pm))
@ -20,6 +23,7 @@ public static class RelativeSyncManager
if (controller == null) if (controller == null)
{ {
// TODO: if someone somehow constantly fails this, we should nuke them into orbit
RelativeSyncMod.Logger.Error($"Failed to apply relative sync for user {userId}"); RelativeSyncMod.Logger.Error($"Failed to apply relative sync for user {userId}");
return; return;
} }
@ -28,7 +32,36 @@ public static class RelativeSyncManager
RelativeSyncMarker syncMarker = null; RelativeSyncMarker syncMarker = null;
if (target != NoTarget) RelativeSyncTransforms.TryGetValue(target, out syncMarker); if (target != NoTarget) RelativeSyncTransforms.TryGetValue(target, out syncMarker);
controller.SetRelativePositions(position, rotation); controller.SetRelativePositions(position, rotation, hipPosition, hipRotation);
controller.SetRelativeSyncMarker(syncMarker); controller.SetRelativeSyncMarker(syncMarker);
} }
public static void GetRelativeAvatarPositionsFromMarker(
Animator avatarAnimator, Transform markerTransform,
out Vector3 relativePosition, out Vector3 relativeRotation,
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation)
{
Transform avatarTransform = avatarAnimator.transform;
// because our syncing is retarded, we need to sync relative from the avatar root...
Vector3 avatarRootPosition = avatarTransform.position; // PlayerSetup.Instance.GetPlayerPosition()
Quaternion avatarRootRotation = avatarTransform.rotation; // PlayerSetup.Instance.GetPlayerRotation()
relativePosition = markerTransform.InverseTransformPoint(avatarRootPosition);
relativeRotation = (Quaternion.Inverse(markerTransform.rotation) * avatarRootRotation).eulerAngles;
Transform hipTrans = (avatarAnimator.avatar != null && avatarAnimator.isHuman)
? avatarAnimator.GetBoneTransform(HumanBodyBones.Hips) : null;
if (hipTrans == null)
{
relativeHipPosition = Vector3.zero;
relativeHipRotation = Vector3.zero;
}
else
{
relativeHipPosition = markerTransform.InverseTransformPoint(hipTrans.position);
relativeHipRotation = (Quaternion.Inverse(markerTransform.rotation) * hipTrans.rotation).eulerAngles;
}
}
} }