using UnityEngine;
using System.Collections.Generic;
namespace Unity.Cinemachine.Samples
{
///
/// 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.
///
[ExecuteAlways]
public class AimCameraRig : CinemachineCameraManagerBase, 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 axes)
{
axes.Add(new () { DrivenAxis = () => ref AimMode, Name = "Aim" });
}
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(out var aim)
&& aim.NoiseCancellation)
{
AimCamera = cam;
var player = AimCamera.Follow;
if (player != null)
AimController = player.GetComponentInChildren();
}
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;
}
}
}