86 lines
3.6 KiB
C#
86 lines
3.6 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Unity.Cinemachine.Samples
|
|
{
|
|
/// <summary>
|
|
/// This is a custom camera manager that selects between an aiming camera child and a
|
|
/// non-aiming camera child, depending on the value of some user input.
|
|
///
|
|
/// The Aiming child is expected to have ThirdPersonFollow and ThirdPersonAim components,
|
|
/// and to have a player as its Follow target. The player is expected to have a
|
|
/// SimplePlayerAimController behaviour on one of its children, to decouple aiminag and
|
|
/// player rotation.
|
|
/// </summary>
|
|
[ExecuteAlways]
|
|
public class AimCameraRig : CinemachineCameraManagerBase, Unity.Cinemachine.IInputAxisOwner
|
|
{
|
|
public InputAxis AimMode = InputAxis.DefaultMomentary;
|
|
|
|
SimplePlayerAimController AimController;
|
|
CinemachineVirtualCameraBase AimCamera;
|
|
CinemachineVirtualCameraBase FreeCamera;
|
|
|
|
bool IsAiming => AimMode.Value > 0.5f;
|
|
|
|
/// Report the available input axes to the input axis controller.
|
|
/// We use the Input Axis Controller because it works with both the Input package
|
|
/// and the Legacy input system. This is sample code and we
|
|
/// want it to work everywhere.
|
|
void IInputAxisOwner.GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
|
|
{
|
|
axes.Add(new () { DrivenAxis = () => ref AimMode, Name = "Aim" });
|
|
}
|
|
|
|
void OnValidate() => AimMode.Validate();
|
|
|
|
protected override void Start()
|
|
{
|
|
base.Start();
|
|
|
|
// Find the player and the aiming camera.
|
|
// We expect to have one camera with a CinemachineThirdPersonAim component
|
|
// whose Follow target is a player with a SimplePlayerAimController child.
|
|
for (int i = 0; i < ChildCameras.Count; ++i)
|
|
{
|
|
var cam = ChildCameras[i];
|
|
if (!cam.isActiveAndEnabled)
|
|
continue;
|
|
if (AimCamera == null
|
|
&& cam.TryGetComponent<CinemachineThirdPersonAim>(out var aim)
|
|
&& aim.NoiseCancellation)
|
|
{
|
|
AimCamera = cam;
|
|
var player = AimCamera.Follow;
|
|
if (player != null)
|
|
AimController = player.GetComponentInChildren<SimplePlayerAimController>();
|
|
}
|
|
else if (FreeCamera == null)
|
|
FreeCamera = cam;
|
|
}
|
|
if (AimCamera == null)
|
|
Debug.LogError("AimCameraRig: no valid CinemachineThirdPersonAim camera found among children");
|
|
if (AimController == null)
|
|
Debug.LogError("AimCameraRig: no valid SimplePlayerAimController target found");
|
|
if (FreeCamera == null)
|
|
Debug.LogError("AimCameraRig: no valid non-aiming camera found among children");
|
|
}
|
|
|
|
protected override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worldUp, float deltaTime)
|
|
{
|
|
var oldCam = (CinemachineVirtualCameraBase)LiveChild;
|
|
var newCam = IsAiming ? AimCamera : FreeCamera;
|
|
if (AimController != null && oldCam != newCam)
|
|
{
|
|
// Set the mode of the player aim controller.
|
|
// We want the player rotation to be copuled to the camera when aiming, otherwise not.
|
|
AimController.PlayerRotation = IsAiming
|
|
? SimplePlayerAimController.CouplingMode.Coupled
|
|
: SimplePlayerAimController.CouplingMode.Decoupled;
|
|
AimController.RecenterPlayer();
|
|
}
|
|
return newCam;
|
|
}
|
|
}
|
|
}
|