From e52c17f322b923054f9ece6efdf27a1b4c25ea64 Mon Sep 17 00:00:00 2001 From: sharedacc520k Date: Mon, 16 Mar 2026 18:04:25 +0900 Subject: [PATCH] =?UTF-8?q?2026-03-16=2018:00=20FPS=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=EC=9D=98=20=EC=A0=95=EB=A9=B4=20=EA=B3=A0=EC=A0=95=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=2080%=20-=20=EC=B9=B4=EB=A9=94=EB=9D=BCRig?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=9C=20aim=EC=B9=B4=EB=A9=94=EB=9D=BC?= =?UTF-8?q?=20=EC=A0=84=ED=99=98=20=EC=A7=84=ED=96=89=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/01_Scenes/GameScene.unity | 4 +- .../Managers/Local/CameraManager.cs | 9 +- .../02_Scripts/Player/Camera/AimCameraRig.cs | 90 +++++++++++++++++++ .../Player/Camera/AimCameraRig.cs.meta | 2 + .../02_Scripts/Player/Camera/CameraRigBase.cs | 48 ++++++++++ .../Player/Camera/CameraRigBase.cs.meta | 2 + .../Player/Camera/PlayerCameraRig.cs | 25 ------ .../Player/Camera/PlayerCameraRig.cs.meta | 2 - .../Controllers/PlayerCharacterController.cs | 13 ++- 9 files changed, 163 insertions(+), 32 deletions(-) create mode 100644 Assets/02_Scripts/Player/Camera/AimCameraRig.cs create mode 100644 Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta create mode 100644 Assets/02_Scripts/Player/Camera/CameraRigBase.cs create mode 100644 Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta delete mode 100644 Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs delete mode 100644 Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs.meta diff --git a/Assets/01_Scenes/GameScene.unity b/Assets/01_Scenes/GameScene.unity index 5232736..5bae5eb 100644 --- a/Assets/01_Scenes/GameScene.unity +++ b/Assets/01_Scenes/GameScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f46f198c29478f1a66ef5ec728d6e75f11f7bd85b41321a3f10eb81cf0ca9910 -size 113363 +oid sha256:0613910f6920e68c309c098ceed1eea30400d020bdff6071b40c0c5725b976c9 +size 121864 diff --git a/Assets/02_Scripts/Managers/Local/CameraManager.cs b/Assets/02_Scripts/Managers/Local/CameraManager.cs index 21d2a5a..bc3019e 100644 --- a/Assets/02_Scripts/Managers/Local/CameraManager.cs +++ b/Assets/02_Scripts/Managers/Local/CameraManager.cs @@ -4,7 +4,7 @@ public class CameraManager : MonoBehaviour { - [SerializeField] private PlayerCameraRig _currentCameraRig; //현재 활성화된 플레이어의 카메라 묶음 조종객체 + [SerializeField] private AimCameraRig _currentCameraRig; //현재 활성화된 플레이어의 카메라 묶음 조종객체 private float minFOV = 40f; 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; } @@ -29,6 +29,11 @@ public void ZoomCamera(float offset) _currentCameraRig.CurrentFOV = Mathf.Clamp(_currentCameraRig.CurrentFOV - offset, minFOV,maxFOV); } + public void RecenterPlayer() + { + + } + public Vector3 GetViewportPointToRayEndPoint(Vector3 vpPoint,float rayLength) { Ray ray = Camera.main.ViewportPointToRay(vpPoint); diff --git a/Assets/02_Scripts/Player/Camera/AimCameraRig.cs b/Assets/02_Scripts/Player/Camera/AimCameraRig.cs new file mode 100644 index 0000000..2124d06 --- /dev/null +++ b/Assets/02_Scripts/Player/Camera/AimCameraRig.cs @@ -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 _myCameras = new List(); + protected override IReadOnlyList 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(); + } + + if (_controller == null) + { + Debug.LogWarning($"현재 카메라의 Follow 대상을 찾을 수 없습니다."); + } + } + + public override void GetInputAxes(List 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; + } + } +} diff --git a/Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta b/Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta new file mode 100644 index 0000000..56b0b74 --- /dev/null +++ b/Assets/02_Scripts/Player/Camera/AimCameraRig.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f1cd586e3430dbf48bd8d70dfb1f72ca \ No newline at end of file diff --git a/Assets/02_Scripts/Player/Camera/CameraRigBase.cs b/Assets/02_Scripts/Player/Camera/CameraRigBase.cs new file mode 100644 index 0000000..adf6d3d --- /dev/null +++ b/Assets/02_Scripts/Player/Camera/CameraRigBase.cs @@ -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 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 axes) + { + + } + + //우선순위 제일 높은 카메라를 가져옴 + protected CinemachineVirtualCameraBase GetHighestPriorityCamera() + { + // 자식에서 할당한 카메라들 + IReadOnlyList 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; + } +} diff --git a/Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta b/Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta new file mode 100644 index 0000000..05836e8 --- /dev/null +++ b/Assets/02_Scripts/Player/Camera/CameraRigBase.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 51fbeb2ecdc99ff44adde9730d800db0 \ No newline at end of file diff --git a/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs b/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs deleted file mode 100644 index 6bf1c6d..0000000 --- a/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs +++ /dev/null @@ -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; - } - } -} diff --git a/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs.meta b/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs.meta deleted file mode 100644 index 785f540..0000000 --- a/Assets/02_Scripts/Player/Camera/PlayerCameraRig.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 0c8edc71b2d7ec249bbdb4b23726bee0 \ No newline at end of file diff --git a/Assets/02_Scripts/Player/Controllers/PlayerCharacterController.cs b/Assets/02_Scripts/Player/Controllers/PlayerCharacterController.cs index d7e4b52..923c4e4 100644 --- a/Assets/02_Scripts/Player/Controllers/PlayerCharacterController.cs +++ b/Assets/02_Scripts/Player/Controllers/PlayerCharacterController.cs @@ -41,9 +41,12 @@ public class PlayerCharacterController : MonoBehaviour private Vector3 _dodgeDir; // 대쉬 시작 시점의 방향 고정 //카메라 전환 - [SerializeField] private PlayerCameraRig _playerCameraRig; //카메라 집합체 + [SerializeField] private AimCameraRig _aimCameraRig; //조준 카메라 집합체 private CameraMode _cameraMode = CameraMode.FreeLook; //카메라 모드 private CancellationTokenSource _cameraDelayChangeCts; //지연전환 취소 토큰 + public enum PlayerRotationMode {CameraCoupled, CameraDecoupled} + public PlayerRotationMode RotationMode; + //캐릭터 관련 public CharacterIdentity PlayerCharacterIdentity { get; set; } @@ -307,6 +310,14 @@ private void JumpAction() } #endregion + #region 카메라 + public void RecenterPlayer() + { + if(GameManager.Instance.Camera != null) + GameManager.Instance.Camera.RecenterPlayer(); + } + #endregion + #region 타미어 private void TickTimer() {