| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- using UdonSharp;
- using UnityEngine;
- using VRC.SDKBase;
- [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)]
- [DisallowMultipleComponent]
- [AddComponentMenu("Artyom Scripting System/Bone Look At Player")]
- public class BoneLookAtPlayer : UdonSharpBehaviour
- {
- public GameObject objectToRotate; // The object to rotate
- public float rotationSpeed = 90.0f; // Maximum rotation speed in degrees per second
- public Vector3 rotationOffset; // Rotation offset for each axis
- private Transform objectTransform;
- private VRCPlayerApi[] players = new VRCPlayerApi[0]; // Reused every frame, grown when more players join
- void Start()
- {
- if (objectToRotate == null)
- {
- Debug.LogError("[AUMSS] Bone Look At Player: Object To Rotate isn't assigned, so nothing will turn.");
- enabled = false; // Stops Update, which would otherwise throw and halt the script
- return;
- }
- objectTransform = objectToRotate.transform;
- }
- void Update()
- {
- if (objectTransform == null) return; // Not set up (enabled = false only takes effect next frame)
- VRCPlayerApi nearestPlayer = GetNearestPlayer();
- if (nearestPlayer == null) return;
- Vector3 playerHeadPosition = nearestPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position;
- // Calculate the direction to look
- Vector3 directionToLook = playerHeadPosition - objectTransform.position;
- if (directionToLook != Vector3.zero)
- {
- Quaternion targetRotation = Quaternion.LookRotation(directionToLook);
- // Apply the rotation offset
- targetRotation *= Quaternion.Euler(rotationOffset);
- objectTransform.rotation = Quaternion.RotateTowards(objectTransform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
- }
- }
- VRCPlayerApi GetNearestPlayer()
- {
- int count = VRCPlayerApi.GetPlayerCount();
- if (players.Length < count) players = new VRCPlayerApi[count];
- VRCPlayerApi.GetPlayers(players);
- VRCPlayerApi nearestPlayer = null;
- float closestDistance = float.MaxValue;
- Vector3 currentPosition = transform.position;
- for (int i = 0; i < count; i++)
- {
- VRCPlayerApi player = players[i];
- if (!Utilities.IsValid(player)) continue; // The local player counts too
- float distance = Vector3.Distance(currentPosition, player.GetPosition());
- if (distance < closestDistance)
- {
- closestDistance = distance;
- nearestPlayer = player;
- }
- }
- return nearestPlayer;
- }
- }
|