新闻详情

新闻详情

首页 / 资讯中心 / 详情

用 Godot 数学库实现角色移动、朝向判断与相机跟随:从 2D 到 3D 的完整指南

发布时间:2026/9/28 12:58:33来源:尧图网络
用 Godot 数学库实现角色移动、朝向判断与相机跟随:从 2D 到 3D 的完整指南
用 Godot 数学库实现角色移动、朝向判断与相机跟随从 2D 到 3D 的完整指南【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs如果你刚接触 GDScript第一次写让角色动起来的需求时可能只需要一行position velocity * delta就能跑起来。但接下来每个需求都会撞上数学斜向移动为什么比单方向快角色什么时候算面向了敌人相机怎么平滑地追着目标转这篇 Godot 数学库完整指南从这些真实任务出发带你认识 Godot 4.x 里最常用的一组数学工具Vector2/Vector3 向量、Transform2D/Transform3D 变换矩阵、点积/叉积以及 3D 里的四元数。不需要线性代数基础每节都给你一段能直接跑的最小示例。2D 任务一让角色平滑移动斜着走不加速要解决的问题读方向键或摇杆让角色以恒定速度移动但按下两个键时比如上右角色不能变成 √2 倍速。extends Node2D export var speed : 200.0 func _physics_process(delta: float) - void: # 从输入构建 0~1 范围的方向向量Vector2 向量运算入门 var input_vec : Vector2( Input.get_action_strength(move_right) - Input.get_action_strength(move_left), Input.get_action_strength(move_down) - Input.get_action_strength(move_up) ) if input_vec.length_squared() 0.0: # normalized() 把向量压到长度 1斜向和直走速度一致 var direction : input_vec.normalized() position direction * speed * delta用到的 Godot 数学库核心就三件事Vector2(x, y)用两个数表示方向大小。注意 Godot 的 2D 屏幕坐标里Y 轴向下Vector2(0, 1)是朝下不是朝上。.length()/.length_squared()向量的模长。只判断远不远时用length_squared()可以省掉一次开方。.normalized()得到单位向量即只保留方向、长度归一。官方参考classes/class_vector2.rst 里列出了全部方法dot()、angle_to()、lerp()都在同一页。顺手解决转身平滑转向目标角色移动了贴图却还朝着旧方向。2D 里旋转就是一个角度用lerp_angle做平滑转向# 在上一段代码后面加 if input_vec.length_squared() 0.0: var direction : input_vec.normalized() position direction * speed * delta # 目标朝向Vector2 的 angle_to 给出到目标的角度 var target_angle : direction.angle() # lerp_angle 会自动走角度里短的那条路不会出现原地打转 rotation lerp_angle(rotation, target_angle, 12.0 * delta)angle_to、lerp_angle这两个方法专门为角色转向这类需求准备写法比手写角度差值简洁得多。任务二判断角色是否面向目标点积就够了要解决的问题敌人 AI 想看到玩家才发起攻击。你手里有角色当前位置、朝向和玩家位置。直觉做法是算出到玩家的向量和朝向的夹角再比较但那要先acos。Godot 数学库里有个更便宜的判断——点积dot productfunc can_see_player(player_pos: Vector2) - bool: var to_player : (player_pos - global_position).normalized() # 点积范围 -1 ~ 11 表示同向0 垂直-1 反向 return to_player.dot(direction) cos(PI * 0.35) # 约 63° 的视锥内a.dot(b)在两个单位向量之间等于夹角的余弦所以点积大于某个阈值就等价于夹角小于某个角度全程不用acos。需要法线或左右侧时用叉积3D 里更常见的是已知碰撞的两个边求表面的法线方向。这时用叉积cross product# vertex1/2/3 是三角面三个顶点Vector3 var edge_a : vertex2 - vertex1 var edge_b : vertex3 - vertex1 var normal : edge_a.cross(edge_b).normalized()叉积的结果垂直于两个输入向量所在平面是算表面法线的标准套路。2D 版本a.cross(b)返回的是标量正负值可以直接告诉你 b 在 a 的顺时针还是逆时针一侧常用于判定目标在我左手边还是右手边。更多细节见 classes/class_vector3.rst。任务三搞懂 GDScript 变换矩阵子节点跟着父节点走要解决的问题把旋转 30° 放大 1.5 倍 移到 (100, 50)这类描述组合起来并让子节点的transform自动跟着父节点传递。Godot 4.x 中2D 节点用Transform2D3D 节点用Transform3D两者都由两部分组成# 组合一个 2D 变换先旋转再缩放最后给位置 var t : Transform2D() t t.rotated(PI / 6) # 旋转 30° t t.scaled(Vector2.ONE * 1.5) # 整体放大 1.5 倍 t.origin Vector2(100, 50) # 放到指定位置 $Sprite2D.transform t3D 里Transform3D的basis就是三根轴向量X/Y/Z单位矩阵下它们正好对应世界三轴局部变换如何变成全局变换节点树里每个节点只存局部变换相对于父节点。引擎沿节点树把各级transform连乘起来才得到全局变换。你自己组合时同理用*号即可# 把局部变换换算到世界空间父级变换 * 局部变换 var local : Transform2D() local.origin Vector2(50, 0) # 局部向右 50 var world : get_parent().transform * local # 乘上父节点变换 # 反方向把世界坐标换算回某节点局部坐标 var world_pos : Vector3(10, 0, -5) var local_pos : get_node(Enemy).transform.affine_inverse() * world_pos3D 的写法完全一致只是换成Transform3D。affine_inverse()给你一个反向变换是坐标换算最常用的技巧。这两个类型的完整方法表在 classes/class_transform2d.rst 和 classes/class_transform3d.rst。任务四进入 3D用四元数做旋转和相机跟随要解决的问题相机要始终看着玩家、旋转平滑如果直接用欧拉角三个独立角度连续转会撞上万向节锁出现相机抽搐。Godot 4.x 内部就是用四元数Quaternion存旋转的API 也把它暴露给你# 从欧拉角创建四元数绕 Y 轴转 90° var q : Quaternion.from_euler(Vector3(0, PI / 2, 0)) # slerp两个旋转之间的平滑插值球面线性插值 var from : Quaternion.IDENTITY var to : q var mid : from.slerp(to, 0.5) # 走到一半的旋转四元数和Basis可以互转接进Transform3D就能用# 四元数 → 3D 变换 var transform : Transform3D(Basis(Quaternion.from_euler(Vector3(0, deg_to_rad(45), 0))), Vector3.ZERO) # 变换 → 四元数注意basis 需正交归一 var q_back : transform.basis.get_rotation_quaternion()最小可用的 3D 相机跟随extends Camera3D export var target: Node3D export var offset : Vector3(0, 2, -5) export var follow_speed : 5.0 func _process(delta: float) - void: # lerp 让相机平滑地趋近期望位置向量插值 global_position global_position.lerp( target.global_position offset, follow_speed * delta) # look_at 内部用四元数算朝向避免欧拉角抖动 look_at(target.global_position, Vector3.UP)lerp负责位置过渡look_at负责朝向两者配合就是最常见的第三人称跟随相机。Quaternion的完整方法包括spherical_cubic_interpolate之类见 classes/class_quaternion.rst。收尾性能小贴士、实战路线和速查表写热点代码时的三个习惯比较距离用平方只判断是否进入范围时用position.distance_squared_to(target) range * range省掉开方。循环里别反复求逆transform.affine_inverse()结果不变的话先算一次存变量。批量转换用 Basis一组同向旋转下的向量用同一个basis连乘比逐个transform * v更直观也更省。建议的动手路线用任务一的脚本做一个摇杆/键盘控制的 2D 角色加lerp_angle转身。加一个敌人用点积视锥检测玩家用Vector2.angle_to平滑转向触发攻击。搭一个 3D 场景给相机套上任务四的跟随脚本再把offset改成可用键盘调整体会四元数视角。做完这三个小项目上表里 80% 的方法你都实际敲过一遍了。核心方法速查表需求2D 方法3D 方法说明单位化取方向v.normalized()v.normalized()移动方向、视锥检测距离比较a.distance_squared_to(b)同左免开方的范围判断角度判断点积a.dot(b)同左面向检测、投影侧向/法线叉积a.cross(b)标量a.cross(b)Vector3转向方向、表面法线位置插值a.lerp(b, t)同左相机跟随、缓动旋转插值lerp_angle(a, b, t)q.slerp(r, t)平滑转向组合/传递Transform2D * tTransform3D * t局部 ↔ 全局换算反变换t.affine_inverse()同左世界坐标转局部坐标参考文档以上示例均基于 Godot 4.x。官方文档中对应章节数学教程位于 tutorials/math/含向量与矩阵专题各类完整 API 在 classes/ 目录下。建议对照vector_math.rst、matrices_and_transforms.rst、vectors_advanced.rst三篇原文配合本文的任务路线练习一遍。【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从嘉立创EDA到AD:PCB 3D模型精准定位与结构验证全流程 2026/9/28 18:53:04

从嘉立创EDA到AD:PCB 3D模型精准定位与结构验证全流程

搞硬件设计的朋友应该都有过这种经历:PCB画完只是第一步,元器件高度对不对、外壳开孔位置准不准、接插件会不会和结构件互相顶住,这些靠眼睛看二维图纸根本看不出来。我自己的习惯是从嘉立创EDA/立创商城直接拿元器件的3D模型(STE…

阅读更多 →
制造业异常考勤闭环管理:从漏打卡到旷工的规则设计与系统落地 2026/9/28 18:52:58

制造业异常考勤闭环管理:从漏打卡到旷工的规则设计与系统落地

1. 异常考勤为什么在制造业这么难管:先从车间的真实场景说起做制造业人力工作的朋友应该都有体会:办公室白领的考勤管理相对简单,钉钉打个卡、漏了一次补一张说明就完事。但到了工厂车间,画风完全不同——三班倒、两班倒、加班连班…

阅读更多 →
【GitHub】Ruflo 深度解析:Claude Code 多智能体编排的 config.toml 骨架与 MCP 接入 TaoToken 实践 2026/9/28 18:52:58

【GitHub】Ruflo 深度解析:Claude Code 多智能体编排的 config.toml 骨架与 MCP 接入 TaoToken 实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
TreeSize和windirstat哪个查大文件更适合新手? 2026/9/28 18:52:58

TreeSize和windirstat哪个查大文件更适合新手?

C盘突然飘红,想找出哪个文件夹在"吃"空间,打开TreeSize一看满屏彩色方块,直接懵了——这是很多新手的真实经历。TreeSize和WinDirStat到底哪个更适合没有技术背景的普通用户?实测之后,答案可能和你想的不太一…

阅读更多 →
OpenClaw 本地部署实战:用 TaoToken 统一 Key 打通自主 AI 智能体执行链路 2026/9/28 18:52:57

OpenClaw 本地部署实战:用 TaoToken 统一 Key 打通自主 AI 智能体执行链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
QT事件循环全解析:从exec()到信号槽,彻底告别界面卡死 2026/9/28 18:52:51

QT事件循环全解析:从exec()到信号槽,彻底告别界面卡死

QT开发中遇到的那些"莫名其妙"的问题,十有八九都能归结到同一个根上:事件循环。界面突然卡死、信号死活不触发、定时器不走了、窗口关不掉,拆到底都是事件循环与处理机制的事。这篇文章我结合这些年的开发经验,把事件循环的概念、执行流程和分发机制做一次系统梳理,适…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉