using UdonSharp; using UnityEngine; using VRC.SDKBase; [UdonBehaviourSyncMode(BehaviourSyncMode.None)] public class ViewTabletSpawner : UdonSharpBehaviour { [SerializeField] private Transform _ViewTabletHeadRoot; [SerializeField] private Transform _ViewTabletHeadOffset; [SerializeField] private Transform _ViewTablet; private bool _FollowPlayerHead = false; private float _PreviousHeadYRotation = 0.0f; void Update() { VRCPlayerApi LocalPlayer = Networking.LocalPlayer; _PreviousHeadYRotation = LocalPlayer.GetBoneRotation(HumanBodyBones.Head).eulerAngles.y; if (_FollowPlayerHead) { _ViewTabletHeadRoot.position = LocalPlayer.GetBonePosition(HumanBodyBones.Head); } else { _ViewTabletHeadRoot.localPosition = Vector3.zero; } } public override void OnPlayerRespawn(VRCPlayerApi Player) { if (Player.isLocal) { Vector3 HeadRotation = Networking.LocalPlayer.GetBoneRotation(HumanBodyBones.Head).eulerAngles; HeadRotation.x = HeadRotation.z = 0.0f; Debug.Log("[ViewTabletSpawner] Old rotation: " + _PreviousHeadYRotation); Debug.Log("[ViewTabletSpawner] New rotation: " + HeadRotation.y); Debug.Log("[ViewTabletSpawner] Delta: " + (HeadRotation.y - _PreviousHeadYRotation)); HeadRotation.y = _ViewTabletHeadRoot.rotation.y + (HeadRotation.y - _PreviousHeadYRotation); _ViewTabletHeadRoot.rotation = Quaternion.Euler(HeadRotation); } base.OnPlayerRespawn(Player); } public void SpawnAtLocalPlayerHead() { _ResetTabletPosition(); Vector3 HeadRotation = Networking.LocalPlayer.GetBoneRotation(HumanBodyBones.Head).eulerAngles; HeadRotation.x = HeadRotation.z = 0.0f; _ViewTabletHeadRoot.rotation = Quaternion.Euler(HeadRotation); _FollowPlayerHead = true; } public void Despawn() { _ResetTabletPosition(); _FollowPlayerHead = false; } private void _ResetTabletPosition() { _ViewTablet.localPosition = Vector3.zero; _ViewTablet.localRotation = Quaternion.identity; } }