如何修复 three.js 加载超过 2 分钟后崩溃的问题
How to fix three.js loading more than 2 minutes and it's crashing
我正在制作一款 3D 游戏,我才刚刚开始。但是,我很快 运行 遇到了一个问题,本地主机 GET 花费了 2 多分钟,在生命周期大约 15-45 秒后,canvas 变成白色,在控制台中,我收到警告显示WebGL 上下文已经丢失。此外,在任务管理器中,游戏占用了 30% CPU 和 100% 的 GPU。
这是一个新的在线 3d 多人游戏。我试图在新帧之后处理内存,但那没有用。我也尝试过预加载所有纹理以使用更少 CPU,但 30% CPU 保持不变。这是我的代码:(客户端)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.autoUpdate = false;
var preLoad = new THREE.TextureLoader();
var sunTexture = preLoad.load("/static/sun-texture.jpg");
var mercuryTexture = preLoad.load("/static/mercury-texture.jpg");
var socketio = io();
var Geometries = [];
socketio.on("TX2", function (data) {
Geometries = [];
var collectedEntities = [];
data.objects.forEach(obj => {
collectedEntities.push(obj);
});
DisplayAllEntities(collectedEntities);
});
function DisplayAllEntities(objects) {
var loader;
objects.forEach(obj => {
if (obj.geometry == "sphere") {
if (obj.type != "ordinary_sphere") {
switch (obj.type) {
case "sun":
var material = new THREE.MeshBasicMaterial({ map: sunTexture });
break;
case "mercury":
var material = new THREE.MeshBasicMaterial({ map: mercuryTexture });
camera.position.z = obj.z + 500;
break;
}
}
loader = new THREE.TextureLoader();
var texture = loader.load(obj.texture)
var geometry = new THREE.SphereGeometry(obj.radius, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var mesh = new THREE.Mesh(geometry, material);
Geometries.push(mesh);
} else if (obj.geometry == "cube") {
loader = new THREE.TextureLoader();
var texture = loader.load(obj.texture)
var geometry = new THREE.CubeGeometry(obj.width, obj.height, obj.depth);
var material = new THREE.MeshBasicMaterial({ map: texture });
var mesh = new THREE.Mesh(geometry, material);
mesh.position = {"x": obj.x, "y": obj.y, "z": obj.z}
Geometries.push(mesh);
}
loader = null;
});
scene.children = [];
scene.dispose();
Geometries.forEach(obj => {
scene.add(obj);
});
render();
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
服务器只是计算位置,然后将它们发送给客户端进行渲染。
我希望获得更低的 CPU 和 GPU 使用率以及更短的加载时间,但性能仍然保持不变。
每次需要渲染时都创建每个对象,尤其是加载相应的纹理时,效率非常低。更好的解决方案是预先设置对象,然后不断更新这些对象。这需要
- 服务器发出初始化(设置对象、加载纹理等)
- 服务器发出游戏状态更新(adding/removing 个项目,如果需要)
- 服务器发出更新位置。 (这是每秒执行 60 次的那个)
- 每个对象都有一个由服务器在创建时给出的唯一 ID,以便客户端知道服务器引用了哪个对象。
这需要更多的努力,但会大大提高性能
我正在制作一款 3D 游戏,我才刚刚开始。但是,我很快 运行 遇到了一个问题,本地主机 GET 花费了 2 多分钟,在生命周期大约 15-45 秒后,canvas 变成白色,在控制台中,我收到警告显示WebGL 上下文已经丢失。此外,在任务管理器中,游戏占用了 30% CPU 和 100% 的 GPU。
这是一个新的在线 3d 多人游戏。我试图在新帧之后处理内存,但那没有用。我也尝试过预加载所有纹理以使用更少 CPU,但 30% CPU 保持不变。这是我的代码:(客户端)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.autoUpdate = false;
var preLoad = new THREE.TextureLoader();
var sunTexture = preLoad.load("/static/sun-texture.jpg");
var mercuryTexture = preLoad.load("/static/mercury-texture.jpg");
var socketio = io();
var Geometries = [];
socketio.on("TX2", function (data) {
Geometries = [];
var collectedEntities = [];
data.objects.forEach(obj => {
collectedEntities.push(obj);
});
DisplayAllEntities(collectedEntities);
});
function DisplayAllEntities(objects) {
var loader;
objects.forEach(obj => {
if (obj.geometry == "sphere") {
if (obj.type != "ordinary_sphere") {
switch (obj.type) {
case "sun":
var material = new THREE.MeshBasicMaterial({ map: sunTexture });
break;
case "mercury":
var material = new THREE.MeshBasicMaterial({ map: mercuryTexture });
camera.position.z = obj.z + 500;
break;
}
}
loader = new THREE.TextureLoader();
var texture = loader.load(obj.texture)
var geometry = new THREE.SphereGeometry(obj.radius, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var mesh = new THREE.Mesh(geometry, material);
Geometries.push(mesh);
} else if (obj.geometry == "cube") {
loader = new THREE.TextureLoader();
var texture = loader.load(obj.texture)
var geometry = new THREE.CubeGeometry(obj.width, obj.height, obj.depth);
var material = new THREE.MeshBasicMaterial({ map: texture });
var mesh = new THREE.Mesh(geometry, material);
mesh.position = {"x": obj.x, "y": obj.y, "z": obj.z}
Geometries.push(mesh);
}
loader = null;
});
scene.children = [];
scene.dispose();
Geometries.forEach(obj => {
scene.add(obj);
});
render();
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
服务器只是计算位置,然后将它们发送给客户端进行渲染。
我希望获得更低的 CPU 和 GPU 使用率以及更短的加载时间,但性能仍然保持不变。
每次需要渲染时都创建每个对象,尤其是加载相应的纹理时,效率非常低。更好的解决方案是预先设置对象,然后不断更新这些对象。这需要
- 服务器发出初始化(设置对象、加载纹理等)
- 服务器发出游戏状态更新(adding/removing 个项目,如果需要)
- 服务器发出更新位置。 (这是每秒执行 60 次的那个)
- 每个对象都有一个由服务器在创建时给出的唯一 ID,以便客户端知道服务器引用了哪个对象。
这需要更多的努力,但会大大提高性能