using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class PlayerController : MonoBehaviour,ISceneInitializable { [Header("점프 설정")] [SerializeField] private float _jumpForce = 5f; // 점프 세기(임펄스) [SerializeField] private float _groundCheckDistance = 0.2f; // 바닥 판정 레이 길이 [SerializeField] private LayerMask _groundLayer = ~0; // 바닥으로 인정할 레이어 private Rigidbody _rb; private void Awake() { _rb = GetComponent(); } public void OnSceneLoaded() { // 중복 구독 방지 후 등록 (씬이 다시 로드돼도 한 번만 구독되도록) InputManager.Instance.OnJump_Event -= this.OnJump; InputManager.Instance.OnJump_Event += this.OnJump; } public void OnJump() { if (_rb == null) { Debug.LogWarning("[PlayerController] Rigidbody가 없어 점프할 수 없습니다.", this); return; } // 바닥에 닿아 있을 때만 점프 (공중 연속 점프 방지) if (!IsGrounded()) return; // 수직 속도를 초기화한 뒤 위로 임펄스를 줘서 항상 같은 높이로 점프 Vector3 v = _rb.linearVelocity; v.y = 0f; _rb.linearVelocity = v; _rb.AddForce(Vector3.up * _jumpForce, ForceMode.Impulse); } // 발밑으로 짧은 레이를 쏴서 바닥 접촉 여부 확인 private bool IsGrounded() { Vector3 origin = transform.position + Vector3.up * 0.05f; return Physics.Raycast(origin, Vector3.down, _groundCheckDistance + 0.05f, _groundLayer, QueryTriggerInteraction.Ignore); } }