55 lines
1.9 KiB
GDScript
55 lines
1.9 KiB
GDScript
class_name PlayerLook
|
|
extends Node
|
|
## 视角组件:把鼠标位移转成 CameraRig 的 yaw 与 Camera 的 pitch。
|
|
## 只管转摄像机 —— 不碰速度、不碰动画。
|
|
##
|
|
## 接法:Player 下挂一个普通 Node,脚本挂上去;由 Player._ready() 调 setup() 注入依赖。
|
|
|
|
@export_group("视角")
|
|
## 鼠标灵敏度(弧度/像素)
|
|
@export var mouse_sensitivity: float = 0.0025
|
|
## 最低俯角(向下看)
|
|
@export var pitch_min_deg: float = -89.0
|
|
## 最高仰角(向上看)
|
|
@export var pitch_max_deg: float = 89.0
|
|
|
|
## 眼睛分两层转:CameraRig 绕竖直轴转(yaw),Camera 原地抬头低头(pitch)。
|
|
## 分开是为了让 pitch 不掺进移动方向 —— 移动只用 rig 的 basis,低头看地也不会走歪。
|
|
var _yaw: float = 0.0
|
|
var _pitch: float = 0.0
|
|
|
|
var _rig: Node3D
|
|
var _camera: Camera3D
|
|
var _body: Node3D
|
|
|
|
|
|
## 由 Player 在 _ready() 注入依赖。组件不自己 get_node,才能脱离具体场景复用。
|
|
func setup(rig: Node3D, camera: Camera3D, body: Node3D) -> void:
|
|
_rig = rig
|
|
_camera = camera
|
|
_body = body
|
|
_yaw = rig.rotation.y
|
|
_pitch = clampf(camera.rotation.x, deg_to_rad(pitch_min_deg), deg_to_rad(pitch_max_deg))
|
|
_apply()
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
|
_yaw -= event.relative.x * mouse_sensitivity
|
|
_pitch = clampf(
|
|
_pitch - event.relative.y * mouse_sensitivity,
|
|
deg_to_rad(pitch_min_deg),
|
|
deg_to_rad(pitch_max_deg)
|
|
)
|
|
_apply()
|
|
|
|
|
|
## 把 _yaw / _pitch 落到节点上。鼠标一动就调一次(渲染帧),所以视角跟手、不等物理帧。
|
|
## 身体跟着一起转 —— 第一人称里「你看哪,身体就朝哪」,别人看你也是这个朝向。
|
|
func _apply() -> void:
|
|
if _rig == null:
|
|
return
|
|
_rig.rotation.y = _yaw
|
|
_camera.rotation.x = _pitch
|
|
_body.rotation.y = _yaw
|