角色动画
This commit is contained in:
+17
-14
@@ -1,15 +1,13 @@
|
||||
extends CharacterBody3D
|
||||
## 第三人称控制器:只管「怎么动」—— 输入、移动物理、相机、血条、联机分叉。
|
||||
## 表现层(动画)在 Body/PlayerAnimator 里,本文件不认识任何片段名。
|
||||
## 表现层(动画)在 Body/AnimationPlayer 上(挂 player_animator.gd),本文件不认识任何片段名。
|
||||
##
|
||||
## 场景结构:
|
||||
## Player (CharacterBody3D) ← 只负责移动与碰撞,自身不旋转
|
||||
## ├─ Collision (CollisionShape3D, CapsuleShape3D)
|
||||
## ├─ Body (Node3D) ← 视觉层,朝移动方向转身;换角色模型时挂在它下面
|
||||
## │ ├─ PlayerAnimator (PlayerAnimator.gd) ← 动作状态机:只读运动、只写动画
|
||||
## │ └─ character-male-e2 (Node3D)
|
||||
## │ ├─ character-male-e/Skeleton3D ← 骨骼 + 蒙皮网格(character-male-e.glb)
|
||||
## │ └─ AnimationPlayer ← 动作库,由 PlayerAnimator 驱动
|
||||
## │ ├─ mouse (Node3D) ← 模型(mouse.glb):MouseRig/Skeleton3D + 各部位 MeshInstance3D
|
||||
## │ └─ AnimationPlayer ← 动作库 + 表现层(挂 player_animator.gd):只读运动、只写动画
|
||||
## ├─ CameraRig (Node3D) ← 承担偏航 yaw,独立于本体旋转
|
||||
## │ └─ SpringArm (SpringArm3D) ← 承担俯仰 pitch,自动避障
|
||||
## │ └─ Camera (Camera3D)
|
||||
@@ -20,7 +18,7 @@ extends CharacterBody3D
|
||||
## 滑索:走到缆下按 E 挂上,沿缆滑向低端,缆上按 S 刹车、空格跳离。
|
||||
## 手感参数(速度/刹车/吸附半径)全在 Zipline 组件上,本文件只读不定义 —— 见文件末尾。
|
||||
##
|
||||
## 操作:WASD/方向键移动,鼠标转视角,Shift 疾跑,空格跳跃,E 滑索,Esc 释放/锁定鼠标
|
||||
## 操作:WASD/方向键移动,鼠标转视角,Shift 疾跑,Ctrl 蹲下(蹲着走即潜行),空格跳跃,E 滑索,Esc 释放/锁定鼠标
|
||||
|
||||
## 跳跃输入缓冲帧数(输入事件在渲染帧到达,物理帧读取,避免漏跳)
|
||||
const JUMP_BUFFER_FRAMES: int = 6
|
||||
@@ -62,8 +60,8 @@ const JUMP_BUFFER_FRAMES: int = 6
|
||||
## 滑索操作提示,同样在 player.tscn 里配好,默认隐藏
|
||||
@onready var _hint: Label3D = $InteractHint
|
||||
|
||||
## 动画状态机(挂在 Body 下)。只把「运动结果」交给它,也只知道它会自己播动画。
|
||||
@onready var animator: PlayerAnimator = $Body/PlayerAnimator
|
||||
## 动画状态机(挂在 Body/AnimationPlayer 上)。只把「运动结果」交给它,也只知道它会自己播动画。
|
||||
@onready var animator: PlayerAnimator = $Body/AnimationPlayer
|
||||
|
||||
var _gravity: float = float(ProjectSettings.get_setting("physics/3d/default_gravity", 9.8))
|
||||
var _yaw: float = 0.0
|
||||
@@ -197,7 +195,12 @@ func _physics_process(delta: float) -> void:
|
||||
move_and_slide()
|
||||
|
||||
# 动画只读运动结果。控制器不认识任何片段名,动画器也不认识输入。
|
||||
animator.set_motion(velocity, is_on_floor(), Input.is_action_pressed("sprint"))
|
||||
animator.set_motion(
|
||||
velocity,
|
||||
is_on_floor(),
|
||||
Input.is_action_pressed("sprint"),
|
||||
Input.is_action_pressed("crouch"),
|
||||
)
|
||||
|
||||
|
||||
# ---------------- 滑索 ----------------
|
||||
@@ -256,10 +259,10 @@ func _detach_zipline(hop: bool = false) -> void:
|
||||
## 让物理引擎去推反而会和「贴着曲线走」这个硬约束打架。
|
||||
## velocity 仍然维护 —— 一是给动画器读,二是脱手后能带着惯性飞出去。
|
||||
func _ride_zipline(delta: float) -> void:
|
||||
var tan := _zipline.tangent(_zip_t) * float(_zip_dir)
|
||||
var tan_dir := _zipline.tangent(_zip_t) * float(_zip_dir)
|
||||
# 重力沿缆方向的分量:缆越陡加速越猛,平缆上几乎不加速。
|
||||
# 下坡时 tan.y 是负的,所以前面要加负号。
|
||||
_zip_speed += -_gravity * _zipline.gravity_scale * tan.y * delta
|
||||
# 下坡时 tan_dir.y 是负的,所以前面要加负号。
|
||||
_zip_speed += -_gravity * _zipline.gravity_scale * tan_dir.y * delta
|
||||
if Input.is_action_pressed("move_back"):
|
||||
_zip_speed -= _zipline.brake_accel * delta
|
||||
_zip_speed = clampf(_zip_speed, 0.0, _zipline.max_speed)
|
||||
@@ -276,8 +279,8 @@ func _ride_zipline(delta: float) -> void:
|
||||
_zip_t = next_t
|
||||
_zip_grab_offset = _zip_grab_offset.lerp(Vector3.ZERO, clampf(delta / 0.12, 0.0, 1.0))
|
||||
global_position = _zipline.ride_point(_zip_t) + _zip_grab_offset
|
||||
velocity = tan * _zip_speed
|
||||
var travel_yaw := atan2(-tan.x, -tan.z)
|
||||
velocity = tan_dir * _zip_speed
|
||||
var travel_yaw := atan2(-tan_dir.x, -tan_dir.z)
|
||||
body.rotation.y = lerp_angle(body.rotation.y, travel_yaw, clampf(turn_speed * delta, 0.0, 1.0))
|
||||
# 相机也跟着摆到行进方向背后 —— 否则人是横着飞的,看不见前面要去哪。
|
||||
# 速率刻意比转身慢:玩家用鼠标看的视角不会被立刻拽回去。
|
||||
|
||||
Reference in New Issue
Block a user