Files
nightclub-arcadia/NightclubArcadia/Assets/Scripts/Camera/DialogueCameraFraming.cs
T
lennartandClaude Opus 5 932cd0582f add camera rig, click-to-move locomotion, and click interaction
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]>
2026-08-25 19:03:18 +02:00

73 lines
2.0 KiB
C#

using NightclubArcadia.UI;
using Unity.Cinemachine;
using UnityEngine;
namespace NightclubArcadia.Cinematics
{
/// <summary>
/// Shifts CinemachinePositionComposer.Composition.ScreenPosition so the
/// player is centred in the screen space left of the dialogue panel.
/// </summary>
public sealed class DialogueCameraFraming : MonoBehaviour
{
[SerializeField] CinemachinePositionComposer composer;
[SerializeField] float dialogueScreenX = -0.17f;
[SerializeField] bool suppressDeadZoneXInDialogue = true;
float defaultDeadZoneX = 0.2f;
void Start()
{
if (composer == null)
{
composer = FindFirstObjectByType<CinemachinePositionComposer>();
}
if (composer != null)
{
defaultDeadZoneX = composer.Composition.DeadZone.Size.x;
}
if (UIStateController.Instance != null)
{
UIStateController.Instance.StateChanged += OnStateChanged;
}
ApplyFraming();
}
void OnDestroy()
{
if (UIStateController.Instance != null)
{
UIStateController.Instance.StateChanged -= OnStateChanged;
}
}
void OnStateChanged() => ApplyFraming();
void ApplyFraming()
{
if (composer == null)
{
return;
}
var active = UIStateController.Instance != null && UIStateController.Instance.IsDialogueActive;
var target = active ? dialogueScreenX : 0f;
var composition = composer.Composition;
composition.ScreenPosition = new Vector2(target, composition.ScreenPosition.y);
if (suppressDeadZoneXInDialogue)
{
var size = composition.DeadZone.Size;
size.x = active ? 0f : defaultDeadZoneX;
composition.DeadZone.Size = size;
}
composer.Composition = composition;
}
}
}