2026-03-16 18:00 FPS 스타일의 정면 고정 이동 80% - 카메라Rig를 통한 aim카메라 전환 진행중
This commit is contained in:
BIN
Assets/01_Scenes/GameScene.unity
LFS
BIN
Assets/01_Scenes/GameScene.unity
LFS
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
public class CameraManager : MonoBehaviour
|
public class CameraManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private PlayerCameraRig _currentCameraRig; //현재 활성화된 플레이어의 카메라 묶음 조종객체
|
[SerializeField] private AimCameraRig _currentCameraRig; //현재 활성화된 플레이어의 카메라 묶음 조종객체
|
||||||
|
|
||||||
private float minFOV = 40f;
|
private float minFOV = 40f;
|
||||||
private float maxFOV = 100f;
|
private float maxFOV = 100f;
|
||||||
@@ -19,7 +19,7 @@ public void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCameraRig(PlayerCameraRig cameraRig)
|
public void SetCameraRig(AimCameraRig cameraRig)
|
||||||
{
|
{
|
||||||
_currentCameraRig = cameraRig;
|
_currentCameraRig = cameraRig;
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,11 @@ public void ZoomCamera(float offset)
|
|||||||
_currentCameraRig.CurrentFOV = Mathf.Clamp(_currentCameraRig.CurrentFOV - offset, minFOV,maxFOV);
|
_currentCameraRig.CurrentFOV = Mathf.Clamp(_currentCameraRig.CurrentFOV - offset, minFOV,maxFOV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RecenterPlayer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public Vector3 GetViewportPointToRayEndPoint(Vector3 vpPoint,float rayLength)
|
public Vector3 GetViewportPointToRayEndPoint(Vector3 vpPoint,float rayLength)
|
||||||
{
|
{
|
||||||
Ray ray = Camera.main.ViewportPointToRay(vpPoint);
|
Ray ray = Camera.main.ViewportPointToRay(vpPoint);
|
||||||
|
|||||||
90
Assets/02_Scripts/Player/Camera/AimCameraRig.cs
Normal file
90
Assets/02_Scripts/Player/Camera/AimCameraRig.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta
Normal file
2
Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f1cd586e3430dbf48bd8d70dfb1f72ca
|
||||||
48
Assets/02_Scripts/Player/Camera/CameraRigBase.cs
Normal file
48
Assets/02_Scripts/Player/Camera/CameraRigBase.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta
Normal file
2
Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 51fbeb2ecdc99ff44adde9730d800db0
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0c8edc71b2d7ec249bbdb4b23726bee0
|
|
||||||
@@ -41,9 +41,12 @@ public class PlayerCharacterController : MonoBehaviour
|
|||||||
private Vector3 _dodgeDir; // 대쉬 시작 시점의 방향 고정
|
private Vector3 _dodgeDir; // 대쉬 시작 시점의 방향 고정
|
||||||
|
|
||||||
//카메라 전환
|
//카메라 전환
|
||||||
[SerializeField] private PlayerCameraRig _playerCameraRig; //카메라 집합체
|
[SerializeField] private AimCameraRig _aimCameraRig; //조준 카메라 집합체
|
||||||
private CameraMode _cameraMode = CameraMode.FreeLook; //카메라 모드
|
private CameraMode _cameraMode = CameraMode.FreeLook; //카메라 모드
|
||||||
private CancellationTokenSource _cameraDelayChangeCts; //지연전환 취소 토큰
|
private CancellationTokenSource _cameraDelayChangeCts; //지연전환 취소 토큰
|
||||||
|
public enum PlayerRotationMode {CameraCoupled, CameraDecoupled}
|
||||||
|
public PlayerRotationMode RotationMode;
|
||||||
|
|
||||||
|
|
||||||
//캐릭터 관련
|
//캐릭터 관련
|
||||||
public CharacterIdentity PlayerCharacterIdentity { get; set; }
|
public CharacterIdentity PlayerCharacterIdentity { get; set; }
|
||||||
@@ -307,6 +310,14 @@ private void JumpAction()
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 카메라
|
||||||
|
public void RecenterPlayer()
|
||||||
|
{
|
||||||
|
if(GameManager.Instance.Camera != null)
|
||||||
|
GameManager.Instance.Camera.RecenterPlayer();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 타미어
|
#region 타미어
|
||||||
private void TickTimer()
|
private void TickTimer()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user