Camera: Cinemachine-based rig with an anchor, a state director, point-of- interest framing, pan input, and dialogue framing volumes. Player: click-to-move over the NavMesh, a pointer input layer, and a motion arbiter that reconciles direct stick input with navigation-driven movement. The pure math is isolated in NightclubArcadia.Locomotion.Math with an EditMode suite, so the arbitration rules are testable without a scene. Interaction: IClickInteractable plus a bridge that routes pointer clicks to it. Supporting project settings: adds the Cinemachine package, the Interactable and Ground tags the raycasts depend on, and NavMesh agent dimensions matched to the player capsule (radius 0.3, height 1.8, climb 0.25). Co-Authored-By: Claude Opus 5 <[email protected]>
82 lines
2.0 KiB
C#
82 lines
2.0 KiB
C#
using Unity.Cinemachine;
|
|
using UnityEngine;
|
|
|
|
namespace NightclubArcadia.Cinematics
|
|
{
|
|
/// <summary>
|
|
/// Raises a reveal camera priority while the player is inside the volume.
|
|
/// </summary>
|
|
[RequireComponent(typeof(BoxCollider))]
|
|
public sealed class CameraFramingVolume : MonoBehaviour
|
|
{
|
|
[SerializeField] CinemachineCamera revealCamera;
|
|
[SerializeField] int activePriority = 20;
|
|
[SerializeField] float minDwell = 0.5f;
|
|
|
|
CameraStateDirector stateDirector;
|
|
int defaultPriority;
|
|
int occupants;
|
|
float exitTimer;
|
|
|
|
void Awake()
|
|
{
|
|
var box = GetComponent<BoxCollider>();
|
|
box.isTrigger = true;
|
|
|
|
if (revealCamera != null)
|
|
{
|
|
defaultPriority = revealCamera.Priority.Value;
|
|
}
|
|
|
|
stateDirector = FindFirstObjectByType<CameraStateDirector>();
|
|
}
|
|
|
|
void OnTriggerEnter(Collider other)
|
|
{
|
|
if (!other.CompareTag("Player") || revealCamera == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
occupants++;
|
|
exitTimer = 0f;
|
|
revealCamera.Priority.Value = activePriority;
|
|
stateDirector?.RegisterReveal();
|
|
}
|
|
|
|
void OnTriggerExit(Collider other)
|
|
{
|
|
if (!other.CompareTag("Player") || revealCamera == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
occupants = Mathf.Max(0, occupants - 1);
|
|
if (occupants == 0)
|
|
{
|
|
exitTimer = minDwell;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (occupants > 0 || revealCamera == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (exitTimer > 0f)
|
|
{
|
|
exitTimer -= Time.deltaTime;
|
|
return;
|
|
}
|
|
|
|
if (revealCamera.Priority.Value != defaultPriority)
|
|
{
|
|
revealCamera.Priority.Value = defaultPriority;
|
|
stateDirector?.UnregisterReveal();
|
|
}
|
|
}
|
|
}
|
|
}
|