我正在使用BabylonJS,我只是从Blender导入了一个网格。
问题是在此行:
x = this.cube.position.x;
我知道
未捕获的TypeError:无法读取未定义的属性“位置”
这是完整的代码:
export class Game {
private canvas: HTMLCanvasElement;
private engine: BABYLON.Engine;
private scene: BABYLON.Scene;
private camera: BABYLON.FreeCamera;
private light: BABYLON.Light;
private skybox: BABYLON.Mesh;
private skyboxMaterial: BABYLON.StandardMaterial;
private waterMesh: BABYLON.Mesh;
private water: Materials.WaterMaterial;
private ground: BABYLON.Mesh;
private groundTexture: BABYLON.Texture;
private groundMaterial: BABYLON.StandardMaterial;
private sphere: BABYLON.Mesh;
private sphereMaterial: BABYLON.StandardMaterial;
private cube: BABYLON.Mesh;
constructor(canvasElement : string) {
// Create canvas and engine.
this.canvas = document.getElementById(canvasElement) as HTMLCanvasElement;
this.engine = new BABYLON.Engine(this.canvas, true);
}
createScene() : void {
this.scene = new BABYLON.Scene(this.engine);
this.camera = new BABYLON.FreeCamera("Camera", BABYLON.Vector3.Zero(), this.scene);
this.camera.attachControl(this.canvas, true);
this.light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), this.scene);
// Skybox
this.skybox = BABYLON.Mesh.CreateBox("skyBox", 1000.0, this.scene);
this.skyboxMaterial = new BABYLON.StandardMaterial("skyBox", this.scene);
this.skyboxMaterial.backFaceCulling = false;
this.skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("../../../assets/Terrain/skybox/TropicalSunnyDay", this.scene);
this.skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
this.skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
this.skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
this.skyboxMaterial.disableLighting = true;
this.skybox.material = this.skyboxMaterial;
// Ground
this.groundTexture = new BABYLON.Texture("../../../assets/Terrain/sand.jpg", this.scene);
this.groundTexture.vScale = this.groundTexture.uScale = 4.0;
this.groundMaterial = new BABYLON.StandardMaterial("groundMaterial", this.scene);
this.groundMaterial.diffuseTexture = this.groundTexture;
this.ground = BABYLON.Mesh.CreateGround("ground", 512, 512, 32, this.scene, false);
this.ground.position.y = -1;
this.ground.material = this.groundMaterial;
// Sphere
this.sphereMaterial = new BABYLON.StandardMaterial("sphereMaterial", this.scene);
this.sphereMaterial.diffuseTexture = new BABYLON.Texture("../../../assets/Terrain/wood.jpg", this.scene);
this.sphere = BABYLON.Mesh.CreateSphere("sphere", 16, 10, this.scene);
this.sphere.position.y = 20;
this.sphere.material = this.sphereMaterial;
// The first parameter can be used to specify which mesh to import. Here we import all meshes
BABYLON.SceneLoader.ImportMesh("cube", "../../../assets/Vessel/", "untitled.glb", this.scene, function (newMeshes) {
this.cube = newMeshes[0];
this.cube.position.y = 20;
this.cube.position.x = 20;
}.bind(this));
// Water
this.waterMesh = BABYLON.Mesh.CreateGround("waterMesh", 512, 512, 32, this.scene, false);
this.water = new Materials.WaterMaterial("water", this.scene, new BABYLON.Vector2(1024, 1024));
this.water.backFaceCulling = true;
this.water.bumpTexture = new BABYLON.Texture("../../../assets/Terrain/waterbump.png", this.scene);
this.water.windForce = -10;
this.water.waveHeight = 0.5;
this.water.bumpHeight = 0.1;
this.water.waveLength = 0.1;
this.water.waveSpeed = 50.0;
this.water.colorBlendFactor = 0;
this.water.windDirection = new BABYLON.Vector2(1, 1);
this.water.colorBlendFactor = 0;
this.waterMesh.material = this.water;
this.water.addToRenderList(this.skybox);
this.water.addToRenderList(this.ground);
this.water.addToRenderList(this.sphere);
this.water.addToRenderList(this.cube);
////////// RAY CAST TO FIND WATER HEIGHT ////////////
//var angle = 0;
this.scene.registerBeforeRender(function() {
let time = this.water._lastTime / 100000;
let x = this.sphere.position.x;
let z = this.sphere.position.z;
this.sphere.position.y = Math.abs((Math.sin(((x / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.x * 5.0) + (Math.cos(((z / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.y * 5.0));
x = this.cube.position.x;
z = this.cube.position.z;
this.cube.position.y = Math.abs((Math.sin(((x / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.x * 5.0) + (Math.cos(((z / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.y * 5.0));
}.bind(this));
}
doRender() : void {
// Run the render loop.
this.engine.runRenderLoop(() => {
this.scene.render();
});
// The canvas/window resize event handler.
window.addEventListener('resize', () => {
this.engine.resize();
});
}
我知道我可以进行空检查,但是我不明白为什么我的多维数据集是未定义的,因为(ImportMesh)是一个Synched函数。
一旦我设置了空检查,我就会摆脱错误。
答案 0 :(得分:0)
由于bue是使用ImportMesh
函数异步加载的,因此您在前几帧中没有使用它,这会导致在registerBeforeRender
函数中引发异常,请尝试以下操作:
this.scene.registerBeforeRender(function() {
let time = this.water._lastTime / 100000;
let x = this.sphere.position.x;
let z = this.sphere.position.z;
this.sphere.position.y = Math.abs((Math.sin(((x / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.x * 5.0) + (Math.cos(((z / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.y * 5.0));
if(this.cube) {
x = this.cube.position.x;
z = this.cube.position.z;
this.cube.position.y = Math.abs((Math.sin(((x / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.x * 5.0) + (Math.cos(((z / 0.05) + time * this.water.waveSpeed)) * this.water.waveHeight * this.water.windDirection.y * 5.0));
}
}.bind(this));
这是一种非常简单的方法。另一种方法是在加载多维数据集之后(在ImportMesh
的onSuccess回调中)注册before-Render函数