5.2 装卸工序:加载器与异步装配


文档摘要

5.2 装卸工序:加载器与异步装配 本节摘要:加载器的本职是把异步运输编排成可靠工序:进度上报让用户等得起,失败兜底让产线不停车,进场整理让模型即插即用。本节承接格式验收,走完从发起加载到动画片段转交的全流程,把 LoadingManager 升级为全站统一的进场看板。 异步是常态,编排是本事 第 3 章已经埋过一次伏笔:贴图加载是异步的。模型加载只会更甚——一个 GLB 动辄数 MB,网络上走几百毫秒到几秒,期间主线程照常渲染。异步工序的全部难点在于"编排":多个模型并发加载时进度怎么汇总、其中一个失败时整单怎么办、加载完成后的整理代码写在哪个回调里。散着写回调是新手写法,回调套回调、错误无处接、进度各报各的;

5.2 装卸工序:加载器与异步装配

本节摘要:加载器的本职是把异步运输编排成可靠工序:进度上报让用户等得起,失败兜底让产线不停车,进场整理让模型即插即用。本节承接格式验收,走完从发起加载到动画片段转交的全流程,把 LoadingManager 升级为全站统一的进场看板。

异步是常态,编排是本事

第 3 章已经埋过一次伏笔:贴图加载是异步的。模型加载只会更甚——一个 GLB 动辄数 MB,网络上走几百毫秒到几秒,期间主线程照常渲染。异步工序的全部难点在于"编排":多个模型并发加载时进度怎么汇总、其中一个失败时整单怎么办、加载完成后的整理代码写在哪个回调里。散着写回调是新手写法,回调套回调、错误无处接、进度各报各的;本节的标准答案是把编排交给两套机制——单个加载器的进度回调,以及全局的 LoadingManager 看板。

图:一次模型装卸的异步时序

图:一次模型装卸的异步时序

动手:带看板的完整装卸线

背景:叉车、货架、传送带三个模型分头加载,要求页面顶部一条总进度、任一失败不阻塞其余两个、全部到齐后统一开场。

操作:LoadingManager 管汇总,单加载器回调管细节,进场整理三件套(轴心、单位、面数)封装成固定函数。

// 全站看板:汇总所有经手的资源 const manager = new THREE.LoadingManager(); manager.onProgress = (url, loaded, total) => { const pct = Math.round((loaded / total) * 100); document.querySelector('#bar').style.width = pct + '%'; }; manager.onLoad = () => startShowcase(); // 全部到齐才开场,避免半成品露脸 manager.onError = (url) => console.warn('进厂失败:', url); const gltfLoader = new GLTFLoader(manager); // 进场整理三件套:轴心落底、单位归一、面数报数 function prepModel(gltf, targetSize = 2) { const model = gltf.scene; // 1. 单位归一:按包围盒实际尺寸等比缩放到目标大小 const box = new THREE.Box3().setFromObject(model); const size = box.getSize(new THREE.Vector3()); const scale = targetSize / Math.max(size.x, size.y, size.z); model.scale.setScalar(scale); // 2. 轴心落底:重算缩放后的包围盒,把底部压到 y=0 box.setFromObject(model); model.position.y -= box.min.y; // 3. 动画片段转交:有就带出,交给动画系统(第 6 章) return { model, clips: gltf.animations }; } function loadForklift(url) { gltfLoader.load(url, (gltf) => { const { model, clips } = prepModel(gltf, 2.5); model.position.set(2, 0, -1); stage.scene.add(model); console.log('叉车进场,动画片段数:', clips.length); }, (evt) => { /* 单件进度:evt.loaded 与 evt.total,看板已汇总,这里可打点 */ }, () => placePlaceholder(2, 0, -1) // onError:失败不停车,放个占位件 ); }

结果:顶部进度条从 0 走到 100,三件模型陆续上架,全部到齐后展示开场;把叉车的地址故意改错,进度照常走完,叉车位置出现一个半透明占位方块,控制台报出失败清单——产线没停。

解读:三个设计决策值得复盘。第一,onLoad 放在 manager 上而不是单个加载器上:开场的条件是"全部到齐",单件的 onLoad 只够做单件的上架。第二,prepModel 里"先缩放、再重算包围盒、再压底"的顺序不能乱——包围盒必须按缩放后的实际尺寸重算,否则轴心落底永远差一截,这是装卸工序的隐性顺序依赖。第三,占位件兜底不是锦上添花:线上环境模型丢失的原因五花八门(缓存失效、路径笔误、跨域限制),占位件让画面保持完整结构,错误进清单而不是进用户眼睛。

变式:把 manager.onProgress 的进度条升级为带条目清单的看板(每件资源一行:进行中、完成、失败),交付评审时客户对"加载了什么、还差什么"一目了然。再进阶:对重复使用的模型做缓存——第一次加载后把 gltf 场景克隆入库,后续同款直接克隆上架,省网络也省解析;克隆时注意材质默认共享,需要独立换色的副本要单独处理材质实例。

跨域、缓存与重复进场

线上装卸还要过两道环境关。跨域:模型与贴图由第三方地址供给时,加载会因跨域限制静默失败,控制台只有一条模糊的加载错误;自托管资源目录是正解,实在要跨域引用则要求对方配置允许头——这条写进技术方案,别等上线才发现。缓存:浏览器对重复请求自动缓存,但模型迭代频繁时缓存会变成"更新不生效"的元凶,给资源地址附版本号参数是行业惯例,发布即换版本。重复进场:同一模型在页面多处使用(货架上的同款叉车三台),第一次加载后的场景对象可以克隆复用——但要注意克隆体默认共享材质,需要独立变色(比如选中高亮只亮一台)时,克隆后单独实例化该副本的材质,否则三台叉车会同时变红。这三道关都是"上线才暴露"的类型,验收阶段就在测试环境里用真实部署方式预演一遍,能省下上线夜的救火。

本节要点回顾

  • 编排交给机制:单件回调管细节,LoadingManager 管汇总,不散写回调;
  • 开场等全齐:onLoad 挂在看板上,半成品不露脸;
  • 进场三件套:单位归一、轴心落底、面数报数,顺序是先缩放再算盒再压底;
  • 失败不停车:占位件保结构完整,错误进清单不进用户眼睛;
  • 同款走克隆:重复模型缓存克隆上架,材质要独立变色时单独实例化。

外协件已入库上架。下一章装传动装置:渲染循环的心跳节拍、动画剪辑的混合调度、射线拾取的命中处理——沙盘要从静展台变成能玩的活场景。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U