restructure
This commit is contained in:
@ -0,0 +1,94 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Manages the UI element's position and rotation in a XR environment
|
||||
/// so that it maintains a fixed position relative to the player camera.
|
||||
/// </summary>
|
||||
public class XRFixedUIPositionHandler : MonoBehaviour
|
||||
{
|
||||
// Offset from the camera's position
|
||||
[SerializeField] private Vector3 _offset;
|
||||
// Speed of the interpolation for smooth movement
|
||||
[SerializeField] private float lerpSpeed;
|
||||
// Whether the UI is allowed to move along the X axis
|
||||
[SerializeField] private bool allowXMovement = true;
|
||||
// Whether the UI is allowed to move along the Y axis
|
||||
[SerializeField] private bool allowYMovement = true;
|
||||
// Whether the UI is allowed to move along the Z axis
|
||||
[SerializeField] private bool allowZMovement = true;
|
||||
|
||||
// Reference to the main camera
|
||||
private Camera playerCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the reference to the main camera.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
playerCamera = Camera.main;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the UI's position and rotation each frame.
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateUIPosition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the target position for the UI element and smoothly moves it to that position.
|
||||
/// </summary>
|
||||
private void UpdateUIPosition()
|
||||
{
|
||||
Vector3 targetPosition = CalculateTargetPosition();
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * lerpSpeed);
|
||||
UpdateUIRotation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the target position of the UI element relative to the player's camera.
|
||||
/// </summary>
|
||||
/// <returns>The calculated target position.</returns>
|
||||
private Vector3 CalculateTargetPosition()
|
||||
{
|
||||
Vector3 targetOffset = CalculateTargetOffset();
|
||||
Vector3 targetPosition = playerCamera.transform.position + targetOffset;
|
||||
|
||||
// Apply fixed offsets if movement is not allowed
|
||||
if (!allowXMovement) targetPosition.x = _offset.x;
|
||||
if (!allowYMovement) targetPosition.y = _offset.y;
|
||||
if (!allowZMovement) targetPosition.z = _offset.z;
|
||||
|
||||
return targetPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the offset vector based on the allowed movement directions.
|
||||
/// </summary>
|
||||
/// <returns>The calculated offset vector.</returns>
|
||||
private Vector3 CalculateTargetOffset()
|
||||
{
|
||||
Vector3 targetOffset = Vector3.zero;
|
||||
|
||||
if (allowXMovement)
|
||||
targetOffset += _offset.x * playerCamera.transform.right;
|
||||
|
||||
if (allowYMovement)
|
||||
targetOffset += _offset.y * playerCamera.transform.up;
|
||||
|
||||
if (allowZMovement)
|
||||
targetOffset += _offset.z * playerCamera.transform.forward;
|
||||
|
||||
return targetOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the rotation of the UI element to face the camera.
|
||||
/// </summary>
|
||||
private void UpdateUIRotation()
|
||||
{
|
||||
Vector3 direction = transform.position - playerCamera.transform.position;
|
||||
transform.rotation = Quaternion.LookRotation(direction);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7aebe0f159ee70b4e9e663ceaf9934a8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
151
Unity/Assets/Convai/ConvaiXR/Scripts/XRNPCUIPositionHandler.cs
Normal file
151
Unity/Assets/Convai/ConvaiXR/Scripts/XRNPCUIPositionHandler.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using Convai.Scripts.Runtime.Core;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the UI transformation for XR interactions, adjusting the UI position based on the player's camera distance from an NPC.
|
||||
/// </summary>
|
||||
public class XRNPCUIPositionHandler : MonoBehaviour
|
||||
{
|
||||
// Speed at which the UI lerps to its new position.
|
||||
[SerializeField] private float _lerpSpeed;
|
||||
// Offset from the NPC position.
|
||||
[SerializeField] private Vector3 _offset;
|
||||
// Distance threshold for switching offsets.
|
||||
[SerializeField] private float _cameraDistanceThreshold;
|
||||
// Reference to the main camera in the scene.
|
||||
private Camera _playerCamera;
|
||||
// Reference to the currently active NPC.
|
||||
private ConvaiNPC _currentNPC;
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to the active NPC change event when the script is enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
if (ConvaiNPCManager.Instance != null)
|
||||
{
|
||||
ConvaiNPCManager.Instance.OnActiveNPCChanged += OnActiveNPCChanged;
|
||||
_currentNPC = ConvaiNPCManager.Instance.activeConvaiNPC;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsubscribes from the active NPC change event when the script is disabled.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
if (ConvaiNPCManager.Instance != null)
|
||||
{
|
||||
ConvaiNPCManager.Instance.OnActiveNPCChanged -= OnActiveNPCChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main camera reference.
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
_playerCamera = Camera.main;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current NPC and sets the UI position when the active NPC changes.
|
||||
/// </summary>
|
||||
/// <param name="newNPC">The new active NPC.</param>
|
||||
private void OnActiveNPCChanged(ConvaiNPC newNPC)
|
||||
{
|
||||
_currentNPC = newNPC;
|
||||
if (_currentNPC != null && _playerCamera != null)
|
||||
{
|
||||
SetUIPosition();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the UI position and rotation to face the camera in each frame.
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_currentNPC != null)
|
||||
{
|
||||
UpdateUIPosition();
|
||||
FaceCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UI position based on the distance from the player camera to the NPC.
|
||||
/// </summary>
|
||||
private void SetUIPosition()
|
||||
{
|
||||
Transform npcTransform = _currentNPC.transform;
|
||||
Vector3 targetPosition = CalculateTargetPosition(npcTransform);
|
||||
transform.position = targetPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Smoothly updates the UI position using linear interpolation (Lerp).
|
||||
/// </summary>
|
||||
private void UpdateUIPosition()
|
||||
{
|
||||
Transform npcTransform = _currentNPC.transform;
|
||||
Vector3 targetPosition = CalculateTargetPosition(npcTransform);
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * _lerpSpeed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the target position of the UI based on the NPC's position and the distance to the player camera.
|
||||
/// </summary>
|
||||
/// <param name="npcTransform">The transform of the NPC.</param>
|
||||
/// <returns>The target position for the UI.</returns>
|
||||
private Vector3 CalculateTargetPosition(Transform npcTransform)
|
||||
{
|
||||
Vector3 leftOffset = new Vector3(-_offset.x, _offset.y, _offset.z);
|
||||
Vector3 rightOffset = new Vector3(_offset.x, _offset.y, _offset.z);
|
||||
|
||||
Vector3 leftOffsetPosition = npcTransform.position + npcTransform.TransformDirection(leftOffset);
|
||||
Vector3 rightOffsetPosition = npcTransform.position + npcTransform.TransformDirection(rightOffset);
|
||||
|
||||
float distanceToLeftOffset = Vector3.Distance(leftOffsetPosition, _playerCamera.transform.position);
|
||||
float distanceToRightOffset = Vector3.Distance(rightOffsetPosition, _playerCamera.transform.position);
|
||||
|
||||
Vector3 dynamicOffset = DetermineDynamicOffset(distanceToLeftOffset, distanceToRightOffset);
|
||||
|
||||
return npcTransform.position + npcTransform.TransformDirection(dynamicOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the appropriate dynamic offset based on the distances from the camera to the left and right offsets.
|
||||
/// </summary>
|
||||
/// <param name="distanceToLeftOffset">Distance to the left offset position.</param>
|
||||
/// <param name="distanceToRightOffset">Distance to the right offset position.</param>
|
||||
/// <returns>The chosen offset vector.</returns>
|
||||
private Vector3 DetermineDynamicOffset(float distanceToLeftOffset, float distanceToRightOffset)
|
||||
{
|
||||
Vector3 leftOffset = new Vector3(-_offset.x, _offset.y, _offset.z);
|
||||
Vector3 rightOffset = new Vector3(_offset.x, _offset.y, _offset.z);
|
||||
|
||||
float threshold = 0.5f;
|
||||
|
||||
if (distanceToLeftOffset < _cameraDistanceThreshold && distanceToRightOffset < _cameraDistanceThreshold)
|
||||
{
|
||||
float difference = Mathf.Abs(distanceToLeftOffset - distanceToRightOffset);
|
||||
return difference > threshold
|
||||
? (distanceToLeftOffset > distanceToRightOffset ? leftOffset : rightOffset)
|
||||
: leftOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return distanceToLeftOffset >= _cameraDistanceThreshold ? leftOffset : rightOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the UI face the camera.
|
||||
/// </summary>
|
||||
private void FaceCamera()
|
||||
{
|
||||
Vector3 direction = transform.position - _playerCamera.transform.position;
|
||||
transform.rotation = Quaternion.LookRotation(direction);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 068e80eca13510841ba379fbcd57ff2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user