๐Ÿ“”Utils - FreeLookCamera

BamgasiJMยท2026๋…„ 4์›” 21์ผ

Unity GenArt

๋ชฉ๋ก ๋ณด๊ธฐ
7/41
post-thumbnail

MainCamera์— ๋ถ€์ฐฉํ•ด์„œ ์‚ฌ์šฉ

FreeLookCamera.cs

using UnityEngine;
using UnityEngine.InputSystem;

// MainCamera์— ๋ถ€์ฐฉํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
// WASD: ์ˆ˜ํ‰ ์ด๋™ / QยทE: ์ˆ˜์ง ์ด๋™ / ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ ๋“œ๋ž˜๊ทธ: ์‹œ์„  ํšŒ์ „ / F: ์ดˆ๊ธฐ ์œ„์น˜ยท๊ฐ๋„ ๋ฆฌ์…‹

public class FreeLookCamera : MonoBehaviour
{
  // ===================================================================
  // Inspector ์„ค์ •
  // ===================================================================

  [Header("์ดˆ๊ธฐ Transform")]
  public Vector3 initialPosition = new Vector3(0f, 5f, -12f);
  public Vector3 initialRotation = new Vector3(15f, 0f, 0f); // Euler ๊ฐ๋„

  [Header("์ด๋™ ์„ค์ •")]
  public float moveSpeed = 10f;  // ๊ธฐ๋ณธ ์ด๋™ ์†๋„
  public float moveSpeedBoost = 20f;  // Shift ๋ˆ„๋ฅผ ๋•Œ ์ด๋™ ์†๋„
  public float moveSmoothing = 12f;  // ์ด๋™ ๋ณด๊ฐ„ ๊ฐ•๋„

  [Header("์‹œ์„  ํšŒ์ „ ์„ค์ •")]
  public float lookSensitivity = 0.3f; // ๋งˆ์šฐ์Šค ๊ฐ๋„
  public float lookSmoothing = 16f;   // ํšŒ์ „ ๋ณด๊ฐ„ ๊ฐ•๋„
  public float pitchMin = -80f;
  public float pitchMax = 80f;

  // ===================================================================
  // ๋‚ด๋ถ€ ์ƒํƒœ
  // ===================================================================

  float _yaw;          // ํ˜„์žฌ ์ขŒ์šฐ ๊ฐ๋„
  float _pitch;        // ํ˜„์žฌ ์ƒํ•˜ ๊ฐ๋„
  float _targetYaw;
  float _targetPitch;

  Vector3 _velocity;         // ํ˜„์žฌ ์ด๋™ ์†๋„ ๋ฒกํ„ฐ (๋ณด๊ฐ„์šฉ)
  Vector3 _targetVelocity;   // ๋ชฉํ‘œ ์ด๋™ ์†๋„ ๋ฒกํ„ฐ

  bool _isDragging;       // ์šฐํด๋ฆญ ๋“œ๋ž˜๊ทธ ์ค‘ ์—ฌ๋ถ€

  Mouse _mouse;
  Keyboard _keyboard;

  // ===================================================================
  // Unity ์ด๋ฒคํŠธ
  // ===================================================================

  void Start()
  {
    transform.position = initialPosition;
    transform.eulerAngles = initialRotation;

    _yaw = _targetYaw = initialRotation.y;
    _pitch = _targetPitch = initialRotation.x;

    _mouse = Mouse.current;
    _keyboard = Keyboard.current;
  }

  void Update()
  {
    // ์žฅ์น˜ ์žฌ์—ฐ๊ฒฐ ๋Œ€๋น„: ๋งค ํ”„๋ ˆ์ž„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค
    _mouse = Mouse.current;
    _keyboard = Keyboard.current;

    HandleLookInput();
    HandleMoveInput();
    HandleResetInput();

    ApplySmoothing();
  }

  // ===================================================================
  // ์ž…๋ ฅ ์ฒ˜๋ฆฌ
  // ===================================================================

  // ์šฐํด๋ฆญ ๋“œ๋ž˜๊ทธ๋กœ ์‹œ์„ (YawยทPitch)์„ ์กฐ์ž‘ํ•ฉ๋‹ˆ๋‹ค
  void HandleLookInput()
  {
    if (_mouse == null) return;

    if (_mouse.leftButton.wasPressedThisFrame) _isDragging = true;
    if (_mouse.leftButton.wasReleasedThisFrame) _isDragging = false;

    if (!_isDragging) return;

    Vector2 delta = _mouse.delta.ReadValue();

    _targetYaw += delta.x * lookSensitivity;
    _targetPitch -= delta.y * lookSensitivity;
    _targetPitch = Mathf.Clamp(_targetPitch, pitchMin, pitchMax);
  }

  // WASDยทQยทE ํ‚ค๋กœ ์ด๋™ ๋ฐฉํ–ฅ ๋ฒกํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค
  void HandleMoveInput()
  {
    if (_keyboard == null) return;

    // ์ž…๋ ฅ ์ถ• ์ˆ˜์ง‘: -1 ~ 1 ๋ฒ”์œ„๋กœ ์ •๊ทœํ™”ํ•ฉ๋‹ˆ๋‹ค
    float h = (_keyboard.dKey.isPressed ? 1f : 0f) - (_keyboard.aKey.isPressed ? 1f : 0f);
    float v = (_keyboard.wKey.isPressed ? 1f : 0f) - (_keyboard.sKey.isPressed ? 1f : 0f);
    float u = (_keyboard.qKey.isPressed ? 1f : 0f) - (_keyboard.eKey.isPressed ? 1f : 0f);

    // ์นด๋ฉ”๋ผ ๋กœ์ปฌ ๊ธฐ์ค€์œผ๋กœ ์ด๋™ ๋ฐฉํ–ฅ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค
    // ์ˆ˜์ง ์ด๋™(QยทE)์€ ์›”๋“œ Y์ถ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
    Vector3 dir = transform.right * h
                + transform.forward * v
                + Vector3.up * u;

    // ๋ฐฉํ–ฅ ๋ฒกํ„ฐ ํฌ๊ธฐ๊ฐ€ 1์„ ์ดˆ๊ณผํ•˜๋ฉด ์ •๊ทœํ™”ํ•ด์„œ ๋Œ€๊ฐ ์ด๋™ ์‹œ ์†๋„ ์ฆํญ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค
    if (dir.sqrMagnitude > 1f) dir.Normalize();

    // Shift ํ‚ค: ๊ณ ์† ์ด๋™
    float speed = _keyboard.leftShiftKey.isPressed ? moveSpeedBoost : moveSpeed;

    _targetVelocity = dir * speed;
  }

  // F ํ‚ค: ์ดˆ๊ธฐ ์œ„์น˜ยท๊ฐ๋„๋กœ ์ฆ‰์‹œ ๋ฆฌ์…‹ํ•ฉ๋‹ˆ๋‹ค
  void HandleResetInput()
  {
    if (_keyboard == null) return;
    if (!_keyboard.fKey.wasPressedThisFrame) return;

    transform.position = initialPosition;
    transform.eulerAngles = initialRotation;

    _yaw = _targetYaw = initialRotation.y;
    _pitch = _targetPitch = initialRotation.x;

    // ์ž”๋ฅ˜ ์†๋„ ์ œ๊ฑฐ
    _velocity = Vector3.zero;
    _targetVelocity = Vector3.zero;
  }

  // ===================================================================
  // ๋ณด๊ฐ„ ์ ์šฉ
  // ===================================================================

  void ApplySmoothing()
  {
    // ํšŒ์ „ ๋ณด๊ฐ„
    _yaw = Mathf.LerpAngle(_yaw, _targetYaw, Time.deltaTime * lookSmoothing);
    _pitch = Mathf.LerpAngle(_pitch, _targetPitch, Time.deltaTime * lookSmoothing);
    transform.rotation = Quaternion.Euler(_pitch, _yaw, 0f);

    // ์ด๋™ ๋ณด๊ฐ„ ํ›„ ์œ„์น˜์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค
    _velocity = Vector3.Lerp(_velocity, _targetVelocity, Time.deltaTime * moveSmoothing);
    transform.position += _velocity * Time.deltaTime;
  }

  // ===================================================================
  // ๊ธฐ์ฆˆ๋ชจ
  // ===================================================================
#if UNITY_EDITOR
  void OnDrawGizmosSelected()
  {
    // ์ดˆ๊ธฐ ์œ„์น˜๋ฅผ ์—๋””ํ„ฐ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
    Gizmos.color = new Color(1f, 0.8f, 0f, 0.8f);
    Gizmos.DrawWireSphere(initialPosition, 0.3f);

    Gizmos.color = new Color(0.3f, 0.8f, 1f, 0.5f);
    Gizmos.DrawRay(initialPosition, Quaternion.Euler(initialRotation) * Vector3.forward * 2f);
  }
#endif
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€