Godot 数学库 5 个场景吃透向量、变换矩阵与四元数实战指南【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs这是一次 15 分钟的组内分享主题是 Godot 数学库。我做了五年游戏开发真正高频用到的数学其实就四类向量、变换矩阵、点积叉积、旋转插值。本文不按教材章节讲而是按游戏场景组织移动对象、旋转缩放、判断碰撞、平滑运动、性能避坑。会写 GDScript 就能全部看懂。 Godot 向量与 Vector2 用法让精灵从 A 点走到 B 点让一个精灵从 A 点走到 B 点你要给它的哪些属性赋值答案位置和速度。一个向量就是同时告诉引擎往哪走和走多远。注意 Godot 的 2D 坐标系X 向右Y 向下。这是图形学常见约定Y 方向容易把新人绕晕。// 目的算出从当前位置指向目标的方向并按固定速度逐帧移动var velocity (target - position).normalized() * speed position velocity * delta第一行先拿到从当前位置指向目标的方向向量normalized()把它的长度归一成 1再乘以speed就变成该走多快。第二行是沿这个方向走 速度 × 帧时间 的距离。这是 2D 游戏里最常见的移动写法。其他常用运算都是按分量进行的加减和标量乘除a b、a - b、a * 2、a / 2长度与平方长度a.length()、a.length_squared()2D 向量夹角a.angle_to(b)判断距离时养成用distance_squared_to()比较的习惯为什么更快最后一节解释。 Godot Transform3D 旋转为什么用角度转着转着就翻跟头每帧用角度去转物体为什么转着转着会翻一下先搞清楚变换的构成。Godot 变换矩阵分两套2D 用Transform2D3D 用Transform3D。两者都由两部分组成basis3D 里是三个轴向控制旋转和缩放和 origin控制位置。组合变换可以相乘// 目的依次给同一个变换加上位置、90 度旋转和缩放var transform Transform2D() transform.origin Vector2(100, 50) transform transform.rotated(PI / 2) transform transform.scaled(Vector2(2, 1.5)) $Sprite2D.transform transform两个变换相乘就是组合先作用右操作数子节点的局部变换再作用左操作数父节点这是场景树层级的底层原理。为什么欧拉角会翻车用角度三元组欧拉角转 3D 物体很直观但做动画插值时会出问题接近 Y 180° 时X 和 Z 的旋转顺序会发生跳变物体朝着意料之外的方向翻转这就是万向节锁。所以 Godot 里有四元数Quaternion用四个分量直接表示任意 3D 旋转没有奇点也没有万向节锁。// 目的用四元数 slerp 从无旋转到 180 度之间平滑插值var start_rot Quaternion.IDENTITY var end_rot Quaternion.from_euler(Vector3(0, PI, 0)) var current_rot start_rot.slerp(end_rot, 0.5)slerp是球形线性插值沿旋转球面上的最短路径过渡是平滑旋转的标准写法。四元数和矩阵互相转也不麻烦Basis(quaternion)变矩阵basis.get_rotation_quaternion()变回来。日常建议单轴旋转、2D 用角度就够了3D 平滑动画把四元数存进变量用 slerp 插值。 Godot 碰撞检测 点积角色该不该回头角色面朝左目标在右边它该不该回头别写一堆 if-else一行点积dot就能给出答案// 目的目标方向与朝向夹角在 45 度以内才判定为面对目标var to_target (target - origin).normalized() return to_target.dot(facing_direction) 0.7怎么理解点积两个单位向量的点积结果是它们夹角的余弦。同向 1反向 -1垂直 0。所以 0.7表示两者夹角小于约 45°。视野判断、背后攻击判定、寻路朝向判断都能用。叉积cross负责另一件事求法线。3D 里把三角形面的两条边做叉积就得到这个面的法向量2D 里cross()返回一个数字正负号告诉你 b 在 a 的左侧还是右侧。平面与分离轴定理SATGodot 提供了Plane类Plane(normal, point)创建plane.distance_to(point)求点到平面的距离做地面或触发面靠它。凸多边形碰撞检测的通用算法是 SAT如果找到一条分离轴让两个多边形在这条轴上的投影不重叠就没撞把所有轴都查完还没有才算碰撞。2D 项目实际做碰撞交给物理引擎Area2DCollisionShape2D更省事。自己写 SAT 主要是为了理解原理或者应对移动前先预判碰撞这类特殊需求。 Godot 四元数 slerp 平滑运动帧率掉到 30 还丝滑吗帧率从 60 掉到 30你的角色还丝滑吗关键在一件事别每帧加固定量要每帧按比例插值。向量插值用lerp角度插值用lerp_angle旋转插值用slerp上一节讲的四元数。三种各管各的别混用。// 目的相机平滑跟随目标并始终看向目标var desired_position target_node.global_position offset global_position global_position.lerp(desired_position, follow_speed * delta) look_at(target_node.global_position, Vector3.UP)lerp(start, end, t)的好处t 在 0 到 1 之间时返回从 start 到 end 沿途的一个点。每帧只朝目标挪一个比例follow_speed × delta靠近目标时自然减速观感平滑。注意中间的* delta让插值系数和帧率挂钩实际速度就和帧率无关了。帧率掉到 30 时每帧步进变大角色速度不变——这就是30 帧依然丝滑的关键。角度插值lerp_angle直接 lerp 角度有个坑从 350° 到 10°线性插值会走 180° 的远路。2D 里改用lerp_anglerotation lerp_angle(rotation, target_angle, rotation_speed * delta)它会自动选短路径角色转向不会倒转半圈。⚡ Godot 数学性能优化5 个反模式对照数学运算本身不贵贵在每帧、对几千个对象重复算同一件事。列出我踩过的 5 个反模式❌ 慢写法用length()含开方做距离比较。✅ 快写法用length_squared()比较阈值也提前平方如if position.distance_squared_to(target) activation_range * activation_range:❌ 慢写法几百个粒子逐个套用完整变换transform * v。✅ 快写法取出basis做basis * v只要旋转和缩放时它更快。❌ 慢写法循环里每帧都算归一化方向。✅ 快写法方向不变时单位向量缓存一次反复用。❌ 慢写法每帧算transform.affine_inverse()。✅ 快写法逆矩阵缓存起来只在变换变化时重算。❌ 慢写法对所有对象两两调用distance_to()。✅ 快写法先用平方距离粗筛剩下的再算精确距离。2D vs 3D 常用方法速查运算类型2D3D用途向量创建Vector2(x, y)Vector3(x, y, z)位置、方向、速度平方长度length_squared()length_squared()距离快速比较归一化normalized()normalized()取方向向量点积dot()dot()角度判断、投影叉积cross()返回数字cross()返回向量法线、左右判断线性插值lerp()lerp()位置平滑跟随角度/旋转插值lerp_angle()slerp()四元数转向、旋转动画接下来可以动手做三件事用lerp和distance_squared_to做一个 2D 弹球球在盒子里反弹带速度衰减。给 3D 场景加一个自由相机WASD 移动 鼠标转向朝向用slerp插值。把每帧走固定距离改成position velocity * delta在 60fps 和 30fps 下验证速度一致。【免费下载链接】godot-docsGodot Engine official documentation项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考