关于 xmath-usage
面向依赖 xmath 的 Defold 项目,介绍如何使用该库。指南通过原地执行向量、四元数和矩阵运算,复用已分配对象,减少高频循环中的分配。
主要功能
- 01确认项目依赖 xmath
- 02原地修改数学对象
- 03预分配可复用临时变量
- 04向量与四元数运算
- 05矩阵变换与插值
适用场景
- 01减少 update 循环中的分配
- 02复用临时向量值
- 03计算四元数旋转
- 04构建投影矩阵和视图矩阵
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ indiesoftby/ defold-agent-config --skill xmath-usage安装后在 Claude Code 中输入/xmath-usage确认已加载。
详细介绍
在 Defold 中使用 xmath 实现零分配数学运算
前提条件:验证 xmath 依赖项
应用本指南中的任何建议之前,必须确认项目使用了 xmath。检查 game.project 文件,查看是否包含依赖 URL thejustinwalsh/defold-xmath(例如 dependencies#N = https://github.com/thejustinwalsh/defold-xmath/archive/...)。或者,检查 .deps/ 目录中是否存在 xmath/。
如果在 game.project 中找不到 xmath 依赖项,也没有本地 xmath 模块,请勿应用本指南。告知用户该项目未使用 xmath,并建议添加此依赖项:
[project]
dependencies#N = https://github.com/thejustinwalsh/defold-xmath/archive/refs/heads/main.zip
核心概念:通过就地修改消除堆分配
标准 vmath 会在每次运算时创建新的 Lua 对象,导致热循环持续产生 GC 压力:
-- BAD: vmath allocates 3 new objects every frame
function update(self, dt)
local v = self.dir * 5 * dt -- alloc #1
local pos = go.get_position() -- alloc #2
local result = pos + v -- alloc #3
go.set_position(result)
end
xmath 会就地修改现有变量,将结果写入第一个参数。只需分配一次,即可重复使用:
-- GOOD: xmath reuses pre-allocated variables, zero allocations per frame
go.property("dir", vmath.vector3(0, 1, 0))
local v = vmath.vector3() -- allocate ONCE at module scope
function update(self, dt)
local pos = go.get_position()
xmath.mul(v, self.dir, 5 * dt) -- writes into v
xmath.add(v, pos, v) -- writes into v
go.set_position(v)
end
关键规则
- 在模块作用域或
init()中预先分配临时变量——绝不要在update()或on_message()中分配。 - 输出变量始终是第一个参数——这是与
vmath调用约定的根本区别。 - 函数不返回任何值——无法链式调用。每一步都使用一个临时变量。
- 使用
vmath创建初始对象——通过vmath.vector3()、vmath.vector4()、vmath.quat()、vmath.matrix4()分配临时缓冲区,然后使用xmath对其进行运算。 - 类型多态——
xmath.lerp等函数会根据输出参数的类型,对vector3、vector4和quaternion执行相应操作。
优化模式
-- Scratch variables — allocated once
local temp_v = vmath.vector3()
local temp_q = vmath.quat()
function update(self, dt)
-- Instead of: local dir = vmath.normalize(target - pos)
xmath.sub(temp_v, self.target, self.pos)
xmath.normalize(temp_v, temp_v) -- can use same variable as both input and output
-- Instead of: local rot = vmath.quat_rotation_z(angle)
xmath.quat_rotation_z(temp_q, self.angle)
-- Instead of: local rotated = vmath.rotate(rot, dir)
xmath.rotate(temp_v, temp_q, temp_v)
end
完整 API 参考
所有函数都会将结果写入第一个参数。不返回任何值。
向量运算(vector3 / vector4)
| 函数 | 等价写法 | 说明 |
|---|---|---|
xmath.add(out, v1, v2) | out = v1 + v2 | 将两个向量相加 |
xmath.sub(out, v1, v2) | out = v1 - v2 | 将两个向量相减 |
xmath.mul(out, v, n) | out = v * n | 将向量乘以标量 |
xmath.div(out, v, n) | out = v / n | 将向量除以标量 |
xmath.cross(out, v1, v2) | out = cross(v1, v2) | 叉积(仅适用于 vector3) |
xmath.mul_per_elem(out, v1, v2) | out.x = v1.x * v2.x, ... | 逐元素相乘 |
xmath.normalize(out, v) | out = normalize(v) | 归一化向量 |
xmath.rotate(out, q, v) | out = rotate(q, v) | 用四元数旋转 vector3 |
xmath.vector(out) | out = (0,0,0) | 重置为零向量 |
插值(vector3 / vector4 / quaternion)
| 函数 | 等价写法 | 说明 |
|---|---|---|
xmath.lerp(out, t, v1, v2) | out = lerp(t, v1, v2) | 线性插值 |
xmath.slerp(out, t, v1, v2) | out = slerp(t, v1, v2) | 球面插值 |
四元数运算
| 函数 | 说明 |
|---|---|
xmath.quat(out) | 重置为单位四元数 (0, 0, 0, 1) |
xmath.conj(out, q) | 四元数的共轭 |
xmath.quat_axis_angle(out, axis, angle) | 根据轴和角度生成四元数 |
xmath.quat_basis(out, x, y, z) | 根据 3 个基向量(vector3)生成四元数 |
xmath.quat_from_to(out, v1, v2) | 从 v1 到 v2 的旋转四元数 |
xmath.quat_rotation_x(out, angle) | 绕 X 轴旋转 |
xmath.quat_rotation_y(out, angle) | 绕 Y 轴旋转 |
xmath.quat_rotation_z(out, angle) | 绕 Z 轴旋转 |
矩阵运算(matrix4)
| 函数 | 说明 |
|---|---|
xmath.matrix(out [, m1]) | 重置为单位矩阵或从 m1 复制 |
xmath.matrix_axis_angle(out, axis, angle) | 根据轴和角度生成旋转矩阵 |
xmath.matrix_from_quat(out, q) | 根据四元数生成矩阵 |
xmath.matrix_frustum(out, left, right, bottom, top, near, far) | 视锥投影矩阵 |
xmath.matrix_inv(out, m) | 矩阵逆矩阵 |
xmath.matrix_look_at(out, eye, look_at, up) | 视图矩阵 |
xmath.matrix4_orthographic(out, left, right, bottom, top, near, far) | 正交投影 |
xmath.matrix_ortho_inv(out, m) | 正交逆矩阵 |
xmath.matrix4_perspective(out, fov, aspect, near, far) | 透视投影 |
xmath.matrix_rotation_x(out, angle) | 绕 X 轴旋转 |
xmath.matrix_rotation_y(out, angle) | 绕 Y 轴旋转 |
xmath.matrix_rotation_z(out, angle) | 绕 Z 轴旋转 |
xmath.matrix_translation(out, position) | 根据 vector3/vector4 生成平移矩阵 |
评论
支持 Markdown