拆解六面骰子
VVE 自带的 vve_examples:dice_6 是理解刚体完整路径的好样本:它足够小,又同时涉及随机姿态、偏心冲量、八顶点碰撞、着陆规整、item display 和专用模拟器。
模块数据
默认 _class:
function vve_examples:dice_6/_zero
execute positioned 0 0 0 rotated 0 0 as 0-0-0-0-0 run function vve:object/_anchor_to
scoreboard players set a int 2500
scoreboard players set mass int 17
scoreboard players set inertia int 500
function vve_examples:dice_6/_model
data modify storage vve_examples:class dice_6_plate set from storage vve_examples:io result物理半边长是 0.25 格,显示缩放在 _update_display 中由 a × 0.0003 写入 transformation。这个系数是当前骰子资源模型与物理尺寸之间的映射,不是通用 VVE 常量。
_roll:从上下文创建运动
_roll 要求“世界实体执行者 + 执行位置 + 执行朝向”。它完成:
- 从
dice_6_plate创建 item display 实例; _get读入新实例;_rand_quat生成随机姿态;- 从执行位置与朝向构造偏心冲量;
vve:block/_apply_impulse同时改变平动与转动;_store写回;- 注册销毁/点数输出回调。
使用专门 marker 作为投掷者,可避免内部 tp 影响玩家:
summon marker 0 106 -2 {Tags:["dice_thrower"]}
execute as @e[tag=dice_thrower,limit=1] at @s rotated 0 -25 anchored eyes positioned ^ ^ ^0.5 run function vve_examples:dice_6/_roll
kill @e[tag=dice_thrower]main_c:一帧骰子物理
源码阶段依次是:
function vve_examples:dice_6/_get
execute as 0-0-0-0-0 run function vve:object/_iter_motion
execute as 0-0-0-0-0 run function vve:block/_iter_cpoints_c
scoreboard players operation vy int -= vve_gravity int
execute if score shift_response int matches 1 run function vve:object/_apply_shift
execute if score impulse_response int matches 1 run function vve:object/_apply_impulse_f
execute if score couple_response int matches 1 as 0-0-0-0-0 run function vve:object/_apply_couple
function vve:object/_apply_friction
# 支撑足够且法向速度足够小后进行姿态规整
function vve:object/_sync_motion
function vve_examples:dice_6/_store_iter_cpoints_c 遍历 (±a,±a,±a),将偏心冲量拆成平动冲量和力偶矩。落地阶段通常会同时看到 shift、impulse、friction 与 grab-layer 信号。
专用模拟器
vve_examples:dice_simulator/main_loop 每个子步执行四类骰子的 main_c:d4、d6、d8、d12。它自己的 _consts 先恢复 VVE 默认值,再设置较高抓地/实心摩擦与反弹逆映射值。
如果项目只使用 d6,可以复制模拟器模板并只调度 d6,避免无意义遍历。不要直接修改 VVE 包内示例;在自己的命名空间生成模拟器模块。
点数如何得出
骰子姿态由局部坐标轴/四元数表示。点数读取函数根据哪一个本地面法向最朝上判定结果。这个过程依赖落地姿态已经稳定;若在高速旋转中调用,得到的只是当时“最朝上的面”,不是最终点数。
为什么落地会抖
常见原因不止一个:
- 同一骰子被两条 tick 路径重复执行;
- 支撑判定在阈值两侧来回切换;
- 稳定标志确定后仍施加一次较大的 penetration shift;
- 摩擦、冲量与
_regular顺序不一致; - 物理已稳定,但 display interpolation 在旧/新变换之间重复重启。
本站实验包采用“稳定判定先于最终位移/冲量应用”的兼容覆盖,并在连续低速接触后冻结演示骰子。这是演示层策略,不改动 VVE 原数据包,也不应被误写成 VVE 3.0.1 通用静体 API。
骰子回归应该断言什么
不要断言每次随机投掷最终点数相同。应固定初始状态并检查性质:
- 若干 tick 后
y保持在地面接触范围; vx/vy/vz与angular_*进入低速阈值;- 对象没有越过坐标安全边界;
- 稳定后再推进若干 tick,状态变化仍在容差内;
- display entity 存在且 transformation 有限;
- 相同 seed/初态的 JVM 与 Web snapshot 一致。
首页 GIF 与在线实验正是这条路径的可视化结果。