What's the best simple way to handle the update pattern?

Yeah, but in this case {} is a property of the class. So the question is, does the hidden class shape include all properties that are themselves compound data types, and will de-optimization of the entire class occur when adding properties to sub-objects?

If the answer is no, then I’m back to the situation where it might be better for me to create object.userData.update and accept that clone will ignore this.

Also, since the GLTFLoader adds properties to userData and users are encouraged to add new properties here at runtime, it would be useful for us to know whether this is ever a performance issue.

I have no idea how to go about testing this though… I think testing JS engine optimizations is usually done on the command line using special tools.

Objects assigned are references to these objects, so what happens inside userData isn’t relevant for the Object3D instance. This is why i don’t create a empty userData object per instance and rather set this property to null on the prototype by default.

There is no issue with adding and removing properties to hashmaps, we use them for lut and other high frequent changes too.

If you still might prefer going with classes extending Mesh etc, for example class Enemy extends Mesh, you could also just copy the mesh from gltf on your new instance of Enemy, you would have to clone the loaded asset anyway.

Adding properties at runtime like this below wouldn’t be good anyway, you would mix instances with properties occasionally undefined. (progressively adding new properties)

function damage( enemyMesh ) {

	if ( enemyMesh.userData.health === undefined )
		enemyMesh.userData.health = 1.0;
	
	enemyMesh.userData.health -= 0.1;

}

This can be easily avoided by either extending the class or at the point you make a clone of your asset:

const enemy = enemyAsset.clone();

enemy.userData = {
	health: 1
};

That’s probably not the kind of data you want to store but i hope it illustrates what i mean.

I wouldn’t worry about clone, rather about serialization since it’s supposed to store static data :cat:

1 Like

Ah, of course. Makes sense.

Does this cause problems with the GLTFLoader?

Yeah, I’m doing something similar in a couple of larger apps that I’m working on. However, I feel it’s too complicated for an introductory tutorial, hence the monkey patching.

I’m not a fan of monkey patching but I also think in certain situations, especially in simple apps, it’s so much simpler than the alternatives that it’s worth doing. As long as you do due diligence and don’t adopt it as a common pattern.

I’ll go with Object3D.prototype.tick in the first section of the book, with a caveat that it’s not considered best practices, and then add a small section later in the book to explore alternatives.

1 Like

I like this, since the Enemy extends Mesh it’s possible to just do:

myEnemy.geometry = myMesh.geometry
myEnemy.material = myMesh.material

I don’t think it’s that simple, because GLTFLoader returns a Scene which may contain many kinds of objects, not just meshes. It’s not too bad if you know in advance how you glTF files are structured though.