Skip to content

入境的手续

背景:模型加载链路环节断裂——材质代理未解析、缩略图捕获失败、网格就绪回调节点丢失,模型"半入境"无感知。 过程:loadPMXFile 全链路打通——解析 → 实例创建 → 材质代理 → 缩略图 → onMeshesReady 回调,每个环节失败都有反馈。


一个 PMX 文件躺在磁盘上,等着入境。

桌面壳双击了它。屏幕闪了一下,什么都没有发生。

它又双击了一次。还是什么都没有。

"它没进来。" 桌面壳说,"文件在,磁盘在,路径对——但它没进来。没有报错,没有提示,就像它从来不存在。"

"你听到什么声音了吗?" 外交官问。

"没有。"

"那就对了。" 外交官说,"入境需要手续。你双击了文件,但联邦的入境处压根没被通知——加载链路里有一段是断的,模型走到半路,掉进了裂缝里。"

"裂缝在哪儿?"

"我不知道。" 外交官说,"你得沿着入境的路走一遍,看它在哪一步丢了。"


一、入境处

桌面壳找到了入境处——loadPMXFile

typescript
export async function loadPMXFile(...): Promise<...> {
    // 1. 解析文件 → 2. 创建实例 → 3. 材质代理 → 4. 缩略图 → 5. 通知回调
}

"五道手续。" 它说,"文件先被解析——ImportMeshAsync,Babylon 把 PMX 网格读进内存。然后创建实例——注册进模型注册表,拿到一个 ID。再挂材质代理——ADR-188 的 materialProxyConstructor,运行时解析材质。然后拍证件照——captureThumbnail,生成缩略图。最后通知——setOnModelLoaded / setOnMeshesReady 回调,告诉整个世界:有新人入境了。"

"哪一步断了?"

"我走到第三步才发现——材质代理是异步的,实例创建完之后,材质还没解析完。如果你在材质就绪之前就渲染,模型是灰色的;如果你在回调之前就结束加载,模型根本不会被通知。"

"所以每一道手续之间,都有缝隙。"

"有缝隙。" 桌面壳说,"加载不是一步到位的魔法,是一条流水线。每一站之间都可能掉东西——解析失败、代理未就绪、缩略图超时、回调没人接。"


二、证件照

桌面壳先修了缩略图。

"模型入境,得拍一张证件照。" 它说,"没有照片,用户看到的是一个空白格子,不知道里面是什么。缩略图是模型的'脸'——入境处最不能省的一道手续。"

typescript
export async function captureThumbnail(...): Promise<void> {
    // 渲染实例到离屏 → 截图 → 存缓存 → 更新 UI 格子
}

它检查了 thumbnailBaseKey——缩略图的缓存键。这个键要稳定:同一个模型,每次算出来的键必须一样,才能命中缓存。如果键里混了不稳定的值,同一个模型每次重拍证件照,浪费内存还闪缩略图。

"证件照的规矩是:同一个模型,同一张脸。" 桌面壳说,"拍一次,存好,别每次加载都重拍。缓存键是照片的编号——编号乱变,照片就找不到。"

"那你怎么保证键稳定?"

"用模型本身的身份——路径、大小、修改时间。这些是'它是什么'的一部分,不会因为加载顺序改变。键稳定了,照片就能复用。"


三、代理的登场

然后它遇见了 ADR-188 的材质代理。

"材质代理是什么?" 外交官问。

"模型自带材质——PMX 文件里写死了每一块材质用什么。但联邦需要给材质做统一管理:PBR 升级、透明处理、缓存复用。所以材质不是直接用模型的,而是经过一个'代理'转一手。"

"代理做什么?"

"代理按需返回真正的材质。" 桌面壳说,"getStandardMaterialProxy——运行时解析。它在模型加载时注册,在渲染时被调用,让材质的创建延迟到真正需要的那一刻。"

"为什么延迟?"

"因为不是每块材质都会被看到。" 桌面壳说,"一个模型有四十块材质,镜头只拍到二十块。四十块全部立刻创建——浪费 GPU 内存。代理让材质'按需登场':看到哪块,创建哪块。"

"延迟创建,会不会导致渲染时突然卡一下?"

"会。" 桌面壳承认,"但那是可接受的代价——总比四十块材质全部常驻要好。代理是'迟到的演员':需要它的时候,它准时登场。"


四、通知的终点

最后,是回调。

typescript
export function setOnMeshesReady(fn: (meshes: Mesh[]) => void): void;
export function setOnModelLoaded(fn: (id: string) => void): void;

"模型入境之后,有两封信要寄出去:一封给网格(onMeshesReady——'网格就绪,可以渲染了'),一封给模型管理器(onModelLoaded——'新模型注册了,世界该知道了')。"

"信寄不出去会怎样?"

"模型进了注册表,但世界不知道——灯光没算它的,物理没认它,缩略图没拍它。它是一个'隐形入境者':手续全办完了,但没有通知任何人。"

"这就是你最开始遇到的那个裂缝?"

"是。" 桌面壳说,"我双击文件,loadPMXFile 走到一半——材质代理异步解析期间,回调没等它。模型在入境处站着,手里拿着所有手续,但'放行'的口令没喊出来。"

它修好了顺序:先解析 → 再实例 → 等材质代理就绪 → 拍缩略图 → 最后发回调。

"通知必须在最后。" 桌面壳说,"你可以在入境处等材料齐全,但绝不能材料没齐就宣布'已入境'。回调是入境章——盖早了,就成了伪造手续。"


尾声

桌面壳再次双击那个 PMX 文件。

这一次,屏幕亮了起来。模型站在舞台中央——有材质,有影子,有缩略图,有名字。入境处的每一步都走完了,最后那声"放行"如期而至。

"它进来了。" 桌面壳说。

"这次为什么行了?"

"因为我把每一步都修好了:缩略图有稳定的证件照,材质有按需的代理,回调在最后盖章。" 它顿了顿,"加载不是魔法。它就是一套手续——每一道都有人负责,每一道都有反馈,模型才不会在入境处迷路。"

外交官看着那个模型:

"你最开始说,没有报错、没有提示——就像它从来不存在。"

"对。" 桌面壳说,"但现在我知道了:不是它不存在,是它入境的时候,没有一个环节告诉世界'它来了'。联邦的每个新人,都需要一道完整的入境手续——宁可慢一点,不能掉链子。"

它关掉了加载日志。上面写着五步,每一步后面都是一个对勾。

"入境,完毕。"


教训:加载不是一步到位的魔法,是五道手续的流水线——每站之间都有缝隙,每一步失败都要有反馈。

通知必须在材料齐备之后盖章,否则就是伪造手续。