Entity.SetLocalPosition affects saved Vec 3 variable when that variable supposed to be a constant

Hi everyone…i was trying to save a entity position on initialize function to use it later as a return point but i noticed when I change it using entity.setLocalPosition() it changes my object position but also changes the saved variable. I suspected this start position variable was still linked with entity position and i could reproduce the issue below

How can i keep this variable without changing with the entity position?

Start P : [9.238950729370117, 1.1956046835178515, -6.695291519165039]
Start P : [9.238950729370117, 2.1956046835178515, -6.695291519165039]

Hi @MuriloCamargo! Can you try the way below?

let startPosition = entity.getLocalPosition().clone();
1 Like

To add to this

pc.vec3 is an object, not a constant. It has its properties, methods and so on.

What Albertos suggests you is to make a clone of the object, so when you change the original object, you still have the backup.

3 Likes

I will try this! Thanks

Now it works as I intended but i want to make a feedback about entity.getLocalPosition() (and any other function that returns theses objects)

I don’t know if this description is misleading or if I don’t understand correctly the term “readOnly” because i know the object won’t move if I change this returned variable but i think since is a ready only return this object should come cloned out of the box so it doesn’t change when the object change.

Using google tools i can see the graph-node.js and i think all these readOnly functions should clone their return values before returning them. If my project was a little bigger (> 1000 lines of code) i would never think the problem is Vec3 that is not cloned before stored

The functions for getting transforms (position/scale/rotation) will return you a reference to the vector- or quaternion-like object. When it says a read-only, it means that the engine will modify these objects when it deems necessary and will overwrite your setting, if you decide to write some values there directly.

Cloning a vector will allocate a new memory for the new object. Doing it every frame will trigger a garbage collector sooner. A common pattern is to allocate a temporary vector once, and then re-use it by copying the current values of a transform into it, when needed.

// pre-allocate a vector
myScript.v1 = new pc.Vec3();

myScript.prototype.someMethod = function() {
    var entity = this.entity;
    var currentPosition = myScript.v1.copy(entity.getPosition());
    entity.setPosition(1, 1, 1);
    entity.setPosition(currentPosition); // return to original position
}
2 Likes

So the graph-node.js return their read only values just because its a cheaper than creating a new Vec3 object before return ? Your ideia to create a “v1” outside the scope of the method is just to avoid creating too many copies of Vec3 each time the function is called right?

Right. It is not my idea, it is just a common practice in resource management - you want to re-use already allocated resources. It doesn’t have to be exactly there, its an example.

In many cases, the position value is needed only temporarily, like do something if position.x > 10. We don’t need to allocate a new vector each time we do this test - that will generate a lot of garbage really quickly.

If one needs the current values of the transform for some later use, then a good practice is to copy those to another vector.

3 Likes

Thanks!

1 Like