频繁加载和销毁gltf,存在内存泄漏
代码示例
`import React, { useEffect, useState, useRef } from 'react'; import { Button } from 'antd-mobile'; import { WebGLEngine, Scene, Entity, Camera, DirectLight, Vector3, AssetType, GLTFResource, Animator, } from '@galacean/engine'; import { LitePhysics } from '@galacean/engine-physics-lite'; import { registerIncludes } from '@galacean/engine-toolkit'; import { ShaderLab } from '@galacean/engine-shader-lab'; import { OrbitControl } from '@galacean/engine-toolkit'; import './styles.less';
export default () => { const canvasRef = useRef<HTMLCanvasElement>(null); const engineRef = useRef<WebGLEngine | null>(null); const sceneRef = useRef<Scene | null>(null); const rootEntityRef = useRef<Entity | null>(null); const modelEntityRef = useRef<Entity | null>(null); const animatorRef = useRef<Animator | null>(null); const requestRef = useRef<number | null>(null);
const [isLoading, setIsLoading] = useState(false);
// 初始化引擎 const initEngine = async () => { if (!canvasRef.current) return;
try {
registerIncludes();
const shaderLab = new ShaderLab();
const engine = await WebGLEngine.create({
canvas: 'canvas',
physics: new LitePhysics(),
shaderLab,
graphicDeviceOptions: {
preserveDrawingBuffer: false,
},
});
engine.canvas.resizeByClientSize();
// 创建场景
const scene = engine.sceneManager.activeScene;
// 创建根实体
const rootEntity = scene.createRootEntity();
// 创建相机
const cameraEntity = rootEntity.createChild('camera');
const camera = cameraEntity.addComponent(Camera);
cameraEntity.addComponent(OrbitControl);
cameraEntity.transform.setPosition(0, 0, 2);
// 创建光源
const lightEntity = rootEntity.createChild('directLight');
const light = lightEntity.addComponent(DirectLight);
lightEntity.transform.setPosition(1, 1, 1);
lightEntity.transform.lookAt(new Vector3(0, 0, 0));
light.intensity = 1.0;
// 设置场景背景
scene.background.solidColor.set(0.5, 0.5, 0.5, 1);
engineRef.current = engine;
sceneRef.current = scene;
rootEntityRef.current = rootEntity;
await loadModel(
'https://mdn.alipayobjects.com/chain_myent/uri/file/as/mynftmerchant/202508141045460216.gltf',
);
engine.run();
// 窗口大小变化处理
const handleResize = () => {
engine.canvas.resizeByClientSize();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
} catch (err) {
console.error('初始化引擎失败:', err);
}
};
// 加载模型 const loadModel = async (modelUrl: string) => { if (!engineRef.current || !sceneRef.current) return;
setIsLoading(true);
const requestId = ++requestRef.current;
try {
console.log('开始加载模型:', modelUrl);
// 清除之前的模型
if (modelEntityRef.current) {
modelEntityRef.current.destroy();
modelEntityRef.current = null;
animatorRef.current = null;
}
// 加载GLTF资源
const gltfResource = await engineRef.current.resourceManager.load<GLTFResource>({
url: modelUrl,
type: AssetType.GLTF,
timeout: 20000,
});
//竟态检查
if (requestId !== requestRef.current) {
const gltfRoot = gltfResource.instantiateSceneRoot();
gltfRoot?.destroy();
return;
}
console.log('模型加载成功:', gltfResource);
// 创建模型实体
const modelEntity = rootEntityRef.current!.createChild('model');
const gltfRoot = gltfResource.instantiateSceneRoot();
// 将GLTF根节点添加到场景中
modelEntity.addChild(gltfRoot);
console.log(rootEntityRef.current, '===rootEntityRef.current');
modelEntityRef.current = modelEntity;
} catch (err) {
console.error('加载模型失败:', err);
} finally {
setIsLoading(false);
}
};
// 随机更换模型,MODEL_CONFIGS就是模型列表 const changeRandomModel = () => { const randomIndex = Math.floor(Math.random() * MODEL_CONFIGS.length); const newModelUrl = MODEL_CONFIGS[randomIndex].url;
console.log('切换到新模型:', newModelUrl);
loadModel(newModelUrl);
};
useEffect(() => { initEngine();
return () => {
if (engineRef.current) {
engineRef.current.destroy();
}
};
}, []);
return ( <div className="url-test-container"> <canvas id="canvas" ref={canvasRef} className="galacean-canvas" style={{ width: '100vw', height: '100vw' }} />
<Button color="primary" onClick={changeRandomModel}>
随机更换模型
</Button>
</div>
); };`
内存表现
与机型,设备无关,通用行为
引擎版本
1.3.19