Skip to content

频繁加载和销毁gltf,存在内存泄漏 #2838

@xujie-phper

Description

@xujie-phper

代码示例

`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(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 (


<canvas
id="canvas"
ref={canvasRef}
className="galacean-canvas"
style={{ width: '100vw', height: '100vw' }}
/>

  <Button color="primary" onClick={changeRandomModel}>
    随机更换模型
  </Button>
</div>

);
};`

内存表现

与机型,设备无关,通用行为

Image

引擎版本

1.3.19

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions