I’m currently developing a space game called Annihilation using Babylon.js and recently decided to start working on updating to Babylon 5.0. I’m now getting and error with Babylon 5 (alpha 61) where I can’t set Engine.prototype.version without Babylon throwing a TypeError (title). Renaming the property works fine, though I would prefer to keep the current property name. How can I fix this?
The game has other libraries and dependencies that make creating a playground for it very difficult. Please use this link to access the game, and F12/Devtools to view the source code and such.
Huh… Its done using plain Javascript, and my version declaration is pretty much game.version = "...". I found that if I remove the property declaration, version returns undefined.
Ah yes, it’s true you will also have the same error in plain js (when using Object.defineProperty) if you define a getter and not a setter for a property!
But the problem is the same: you defined a getter for a property and no setter.
My declaration is roughly equivalent to this though:
Object.prototype.assign = function(obj){Object.assign(this,obj)};
window.assign(BABYLON);
let game = new Engine(...);
game.assign({version:"Infdev",...});
I’m not using Object.defineProperty. The only thing I can think of is that I’ve done the shortcut but that should not change anything. Maybe something like Object.prototype.assign = function(obj){this = {...this,...obj}}; would copy all of Babylon correctly?
The thing is, why are you writing to the version property of the Babylon engine? You should only read from it.
game.assign({version:“Infdev”,…});
I think there may be a collision with the version property you add that way and the existing version property in Babylon engine (which only has a getter).
I haven’t checked for that as DevTools is blocked on my school Chromebook, but console.dir would probably reveal the issue. I’ll take a look at the Babylon source code and see if they added that. Thank you!
Object.defineProperty(ThinEngine.prototype, "version", {
/**
* Returns the version of the engine
*/
get: function () {
return this._webGLVersion;
},
enumerable: false,
configurable: true
});
Since Engine inherits from ThinEngine, this should be loaded into game.version - though its just returns undefined
Engine.Version doesn’t return undefined - that works fine. Engine.prototype.version returns undefined, and that is what I’m changing.
As for assigning BABYLON to window: It’s simply a matter of convenience. taking away all the BABYLONs in the code makes things more readable.
Finally, for assigning new properties to the engine. I’m simply using the engine object to store game metadata (e.g. the version, states of enabled features, etc.) since its creates less variables.
I think just renaming your property to gameVersion would resolve the error, but I think it would be helpful to create a separate Game class that has properties engine and version and store any other game data there as well.
I’m probably just gonna do game.engine as the engine instead of game. It would be great if the Babylon devs could fix this though since Engine.prototype.version/game.version returns undefined so it’s kind of useless.
In this playground engine.version is 2 for me (for WebGL2). I’m guessing your invalid assign statement results in it being undefined thou. https://playground.babylonjs.com/#1NSSYZ
Edit: oops I assumed you were using engine.version like I did above, but if you’re using Engine.prototype.version to try to get the version then that’s the wrong approach as answered below.
version is defined as a property in TS (getter only) on the ThinEngine class.
Once transpiled it ends up being the defineProperty code you showed above.
The issue is then scoping: calling prototype.version is excecuting the version code on the prototype scope where obviously the value is not defined whereas if you call it on an instance the scope being the instance one makes it all ok.
You are not meant to copy the prototype of a class to another class, you are meant to instantiate it. using the new keyword js takes care of the assignments for you.
@RaananW /@sebavan
I’m not copying a property between classes. I instantiate it first then try to change the property of the newly created engine object - that’s it. The property in question is new BABYLON.Engine(...).version. I’ve refactored my code so I’m using the build property instead, so no worries.