3D 角色控制器不是 move_and_slide 的包装
Godot 的 CharacterBody3D 提供了很好的基础:速度向量、地面检测、move_and_slide()、坡面参数。原型里写几十行就能让角色跑起来。但商业客户端里的角色控制器要面对更多细节:加速度、减速度、空中控制、坡面滑动、台阶、相机方向、根运动、输入缓冲、技能打断、网络校正。
角色移动手感是玩家每天都能感受到的基础体验。它不像技能特效那样显眼,却决定游戏是否“跟手”。Godot 给了底层能力,项目仍要建立自己的 movement model。
flowchart TD
A[输入向量] --> B[相机相对方向转换]
B --> C[移动意图]
C --> D[状态机: 地面/空中/冲刺/受击]
D --> E[速度曲线和约束]
E --> F[CharacterBody3D move_and_slide]
F --> G[地面/坡面/碰撞结果]
G --> D
G --> H[动画与相机反馈]
输入要先变成世界意图
3D 游戏通常使用相机相对移动。玩家按 W,不是世界 Z 正方向,而是相机面向方向的前方。控制器应把输入向量转换为世界空间移动意图,并投影到水平面。相机俯仰不能让角色向地里或天上跑。
这个转换应在输入层和移动层之间完成。输入层只知道玩家按了什么,移动层只接收意图方向和强度。这样键鼠、手柄、移动端虚拟摇杆都能共用移动逻辑。
手柄摇杆还有死区和曲线。轻推慢走、重推奔跑,需要稳定映射。不要直接把摇杆原始值当速度,否则低质量手柄会导致角色漂移。死区和曲线应可配置,并能在调试面板里看到。
速度曲线比最高速度更重要
玩家感受到的是加速、转向和刹车,不只是最大速度。一个角色最高速度 6m/s,如果瞬间达到,会像滑块;另一个最高速度同样 6m/s,但有合理加速度和转向惯性,会更自然。
控制器通常需要地面加速度、地面减速度、空中加速度、空中最大控制、冲刺加速度、受击外力衰减。不同状态使用不同参数。不要把 velocity = input * speed 当成最终方案。
转向也要考虑。角色视觉朝向可以比移动方向稍慢,动画有转身过渡。战斗锁定状态下,角色可能面向敌人但向侧面移动。移动方向、朝向、相机方向是三个不同概念。
坡面和台阶要专项处理
3D 控制器最容易在坡面和小台阶出问题。坡度太小也滑,坡度太大却能爬,角色卡在楼梯边,或者下坡时一跳一跳。Godot 的 floor 参数能解决一部分,但关卡碰撞和控制器逻辑也要配合。
坡面规则要明确:最大可行走角度、超过角度是否滑落、下坡是否贴地、跳跃时是否继承地面速度。地面检测不要只依赖一次碰撞结果,可以结合 RayCast 或 ShapeCast 做稳定判断。
台阶处理需要平衡。真实物理里角色会撞到每一级台阶,但游戏通常希望小台阶自动上去。可以用阶梯检测或关卡碰撞简化:视觉楼梯用斜坡碰撞,细节台阶只做装饰。客户端和关卡制作规范要一起定。
动画和根运动
有些项目使用动画根运动,有些使用代码驱动位移。Godot 两种都可以,但要统一。代码驱动更容易做网络和精确控制,根运动更容易让动作自然。动作游戏常用代码驱动基础移动,特殊技能或处决演出使用根运动片段。
如果使用根运动,控制器要知道何时由动画接管位移,何时恢复输入控制。不要让动画和 CharacterBody 同时推动角色,否则会漂移或穿墙。根运动仍要经过碰撞校正,不能无视地形。
动画参数来自移动状态:速度、方向、是否在空中、转向角、坡度。动画不要反过来决定基础移动规则,除非当前状态明确是动画驱动。
网络和回放边界
联网游戏里,角色控制器可能需要预测和校正。本地玩家输入先驱动 CharacterBody,服务器返回权威位置后平滑修正。控制器参数必须和服务器或权威模拟一致,否则误差会持续积累。
如果只是合作或弱联网,也至少要记录输入和状态,方便回放或问题复现。角色“偶尔卡住”如果没有移动日志,很难查。日志可以记录位置、速度、地面状态、碰撞 normal、当前 movement state。
小结
Godot CharacterBody3D 控制器的质量来自细节:相机相对输入、速度曲线、坡面台阶、状态机、动画协同和调试记录。move_and_slide() 是底层工具,不是完整手感方案。把移动模型设计清楚,角色才会在各种地形和设备上都稳定跟手。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
我会给 3D 控制器做一张 movement gym:平地、斜坡、楼梯、窄桥、移动平台、低矮障碍、连续跳跃。每次改参数都跑这张场景,手感问题会比在正式关卡里随机出现更容易收敛。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。