2026-03-16 18:00 FPS 스타일의 정면 고정 이동 80% - 카메라Rig를 통한 aim카메라 전환 진행중

This commit is contained in:
2026-03-16 18:04:25 +09:00
parent 9171033db8
commit e52c17f322
9 changed files with 163 additions and 32 deletions

View File

@@ -0,0 +1,90 @@
using System.Collections.Generic;
using Unity.Cinemachine;
using UnityEngine;
using UnityEngine.Rendering;
public class AimCameraRig : CameraRigBase
{
public InputAxis AimMode = InputAxis.DefaultMomentary; //누르는 동안만 유지
[SerializeField] private CinemachineCamera _aimCamera;
[SerializeField] private CinemachineCamera _freeCamera;
//CameraRigBase에 전달용
private List<CinemachineVirtualCameraBase> _myCameras = new List<CinemachineVirtualCameraBase>();
protected override IReadOnlyList<CinemachineVirtualCameraBase> CameraCandidates => _myCameras;
public CinemachineCamera ActiveCmCamera => LiveChild as CinemachineCamera;
private bool _isAiming => AimMode.Value > 0.5f;
private float _lastKnownFOV = 60f;
protected override void Awake()
{
base.Awake();
_myCameras.Clear();
if (_aimCamera != null) _myCameras.Add(_aimCamera);
if (_freeCamera != null) _myCameras.Add(_freeCamera);
}
protected override void Start()
{
base.Start();
if (_aimCamera == null || _freeCamera == null)
{
Debug.LogError($"{gameObject.name}: 프리팹 인스펙터에서 카메라 할당이 되지 않았습니다.");
return;
}
CinemachineCamera topPriorityCam = GetHighestPriorityCamera() as CinemachineCamera;
CinemachineCamera currentTargetCam = (LiveChild as CinemachineCamera) ?? topPriorityCam;
if (currentTargetCam != null && currentTargetCam.Follow != null)
{
_controller = currentTargetCam.Follow.GetComponentInChildren<PlayerCharacterController>();
}
if (_controller == null)
{
Debug.LogWarning($"현재 카메라의 Follow 대상을 찾을 수 없습니다.");
}
}
public override void GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
{
base.GetInputAxes(axes);
axes.Add(new() { DrivenAxis = () => ref AimMode, Name = "Aim" });
}
protected override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worldUp, float deltaTime)
{
var oldCam = (CinemachineVirtualCameraBase)LiveChild;
var newCam = _isAiming ? _aimCamera : _freeCamera;
if (_controller != null && oldCam != newCam)
{
_controller.RotationMode = _isAiming
? PlayerCharacterController.PlayerRotationMode.CameraCoupled
: PlayerCharacterController.PlayerRotationMode.CameraDecoupled;
_controller.RecenterPlayer();
}
return newCam;
}
public float CurrentFOV
{
get
{
if (ActiveCmCamera != null)
_lastKnownFOV = ActiveCmCamera.Lens.FieldOfView;
return _lastKnownFOV;
}
set
{
if (ActiveCmCamera != null)
ActiveCmCamera.Lens.FieldOfView = value;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f1cd586e3430dbf48bd8d70dfb1f72ca

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using Unity.Cinemachine;
using UnityEngine;
public abstract class CameraRigBase : CinemachineCameraManagerBase, IInputAxisOwner
{
protected PlayerCharacterController _controller;
protected abstract IReadOnlyList<CinemachineVirtualCameraBase> CameraCandidates { get; }
protected virtual void Awake()
{
}
protected override void Start()
{
base.Start();
}
protected abstract override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worldUp, float deltaTime);
public virtual void GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
{
}
//우선순위 제일 높은 카메라를 가져옴
protected CinemachineVirtualCameraBase GetHighestPriorityCamera()
{
// 자식에서 할당한 카메라들
IReadOnlyList<CinemachineVirtualCameraBase> candidates = CameraCandidates;
if (candidates == null) return null;
CinemachineVirtualCameraBase highest = null;
float maxPrio = float.MinValue;
foreach (CinemachineVirtualCameraBase cam in candidates)
{
if (cam != null && cam.Priority.Value > maxPrio)
{
maxPrio = cam.Priority.Value;
highest = cam;
}
}
return highest;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 51fbeb2ecdc99ff44adde9730d800db0

View File

@@ -1,25 +0,0 @@
using UnityEngine;
using Unity.Cinemachine;
public class PlayerCameraRig : MonoBehaviour
{
[SerializeField] private CinemachineCamera _previewCam;
[SerializeField] private CinemachineCamera _aimCam;
private CinemachineCamera _currentCam;
private void Awake()
{
_currentCam = _previewCam;
}
public float CurrentFOV
{
get { return _currentCam.Lens.FieldOfView; }
set
{
if(_currentCam == _previewCam)
_currentCam.Lens.FieldOfView = value;
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 0c8edc71b2d7ec249bbdb4b23726bee0