컴사양은 좋음
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(Camera))]
public class CameraMove : MonoBehaviour
{
[Header("Frame Rate")]
[SerializeField, Min(1)] private int targetFrameRate = 120;
[SerializeField] private bool syncFixedTimeStep = true;
[Header("Movement")]
[SerializeField] private float moveSpeed = 10f;
[Header("View Toggle")]
[SerializeField] private Vector3 frontViewEulerAngles = Vector3.zero;
[SerializeField] private float rotationSmoothSpeed = 12f;
[SerializeField] private float doubleClickInterval = 0.3f;
[SerializeField] private float groundPlaneZ = 0f;
[SerializeField] private float viewTransitionDuration = 0.35f;
[Header("Zoom")]
[SerializeField] private float zoomSpeed = 3f;
[SerializeField] private float minFieldOfView = 20f;
[SerializeField] private float maxFieldOfView = 80f;
[SerializeField] private float minOrthographicSize = 2f;
[SerializeField] private float maxOrthographicSize = 20f;
private Camera controlledCamera;
private float pendingScroll;
private int inputSystemScrollFrame = -1;
private Quaternion tiltedRotation;
private Quaternion targetRotation;
private float lastLeftClickTime = float.NegativeInfinity;
private bool isFrontView;
private bool isViewTransitioning;
private Vector3 viewPivot;
private float viewPivotDistance;
private Quaternion transitionStartRotation;
private Quaternion transitionEndRotation;
private float viewTransitionProgress;
private void Awake()
{
controlledCamera = GetComponent<Camera>();
tiltedRotation = transform.rotation;
targetRotation = tiltedRotation;
}
private void Start()
{
Application.targetFrameRate = targetFrameRate;
if (syncFixedTimeStep)
Time.fixedDeltaTime = 1f / targetFrameRate;
}
private void Update()
{
Move();
Zoom();
HandleViewToggle();
}
private void FixedUpdate()
{
if (isViewTransitioning)
{
UpdateViewTransition();
return;
}
float rotationStep = 1f - Mathf.Exp(-rotationSmoothSpeed * Time.fixedDeltaTime);
transform.rotation = Quaternion.Slerp(
transform.rotation,
targetRotation,
rotationStep
);
}
private void Move()
{
if (isViewTransitioning)
return;
if (Keyboard.current == null)
return;
float horizontal = 0f;
float vertical = 0f;
if (Keyboard.current.aKey.isPressed)
horizontal -= 1f;
if (Keyboard.current.dKey.isPressed)
horizontal += 1f;
if (Keyboard.current.sKey.isPressed)
vertical -= 1f;
if (Keyboard.current.wKey.isPressed)
vertical += 1f;
Vector3 direction =
(Vector3.right * horizontal + Vector3.up * vertical).normalized;
transform.position += direction * moveSpeed * Time.deltaTime;
}
private void HandleViewToggle()
{
if (Mouse.current == null || !Mouse.current.leftButton.wasPressedThisFrame)
return;
float clickTime = Time.unscaledTime;
if (clickTime - lastLeftClickTime <= doubleClickInterval)
{
isFrontView = !isFrontView;
Quaternion nextRotation = isFrontView
? Quaternion.Euler(frontViewEulerAngles)
: tiltedRotation;
StartViewTransition(nextRotation);
lastLeftClickTime = float.NegativeInfinity;
return;
}
lastLeftClickTime = clickTime;
}
private void StartViewTransition(Quaternion nextRotation)
{
Ray centerRay = controlledCamera.ViewportPointToRay(
new Vector3(0.5f, 0.5f, 0f)
);
Plane groundPlane = new Plane(Vector3.forward, new Vector3(0f, 0f, groundPlaneZ));
if (!groundPlane.Raycast(centerRay, out float hitDistance))
return;
viewPivot = centerRay.GetPoint(hitDistance);
viewPivotDistance = Vector3.Distance(transform.position, viewPivot);
transitionStartRotation = transform.rotation;
transitionEndRotation = nextRotation;
targetRotation = nextRotation;
viewTransitionProgress = 0f;
isViewTransitioning = true;
}
private void UpdateViewTransition()
{
float duration = Mathf.Max(0.01f, viewTransitionDuration);
viewTransitionProgress += Time.fixedDeltaTime / duration;
float t = Mathf.SmoothStep(0f, 1f, viewTransitionProgress);
Quaternion newRotation = Quaternion.Slerp(
transitionStartRotation,
transitionEndRotation,
t
);
transform.SetPositionAndRotation(
viewPivot - newRotation * Vector3.forward * viewPivotDistance,
newRotation
);
if (viewTransitionProgress < 1f)
return;
isViewTransitioning = false;
}
private void Zoom()
{
float scrollY = pendingScroll;
pendingScroll = 0f;
if (Mouse.current != null)
{
float inputSystemScroll = Mouse.current.scroll.y.ReadValue();
if (Mathf.Abs(inputSystemScroll) >= 0.01f)
{
scrollY = inputSystemScroll;
inputSystemScrollFrame = Time.frameCount;
}
}
if (Mathf.Abs(scrollY) < 0.01f)
return;
float zoomAmount = Mathf.Sign(scrollY) * zoomSpeed;
ApplyZoom(zoomAmount);
}
private void OnGUI()
{
if (Event.current.type != EventType.ScrollWheel)
return;
// OnGUI is a fallback for devices whose wheel is not reported by Mouse.current.
if (inputSystemScrollFrame != Time.frameCount)
pendingScroll = -Event.current.delta.y;
}
private void ApplyZoom(float zoomAmount)
{
if (controlledCamera.orthographic)
{
controlledCamera.orthographicSize = Mathf.Clamp(
controlledCamera.orthographicSize - zoomAmount,
minOrthographicSize,
maxOrthographicSize
);
return;
}
controlledCamera.fieldOfView = Mathf.Clamp(
controlledCamera.fieldOfView - zoomAmount,
minFieldOfView,
maxFieldOfView
);
}
}
뭔가 스내핑 되는 느낌인데 흠
카메라 이동 스트립트 올리면 해결될듯
밑 댓글처럼 업데이트 옮겨보고 이미지의 ppu도 맞추고 카메라에 픽셀퍼펙트 붙어 있으면 쓰면 껐다 켰다 해봐
FixedUpdate()에 있는 로직을 Update()로 옮겨야 하지 않을까?
근데 요건 움직이는로직이 아니라 각도바꿀때라 다른거같은디 - dc App
@ㅇㅇ fixedUpdate는 리지드 바디 같은 물리 처리 아니면 쓸 필요 없을것 같은데 일단 Update()로 옮겨서 보고 안고쳐지면 다시 옮기는 방식으로 해봐~
걍 wasd 난잡하게 누르다보니 반대키를 동시에 눌리는 시점에 해당 축 속도가 0이되면서 끊기는 것처럼 느끼는 것 아님?
프로젝트 세팅 -> 버스트 AOT 세팅 -> 퍼포먼스로 바꿔보셈
다들 고마웡 - dc App
카메라 움직이는거를 lateupdate로 움직이면 부드럽던데 이것도 시도 해보시는게..