In the below example (I have tried to trim), I have been scratching my head over how the local variable initialTarget
as a Vector3 gets overwritten when a function called SetTarget is used that takes a position. It seems to always set the initialTarget
Vector3 to the last position used in SetTarget which is passed as position
in the function arguments. Is there something basic about Typescript I am missing here? The code below is all the places that initialTarget
is used
Original Post on Discord
by user 103054507105067008
private initialTarget: THREE.Vector3;
start() {
if (this._controls) {
//this.camGo = GameObject.getComponent(this.gameObject, Camera);
if (this.camGo && !this.setFromTargetPosition()) {
console.log("NO TARGET");
//@ts-ignore
const forward = new THREE.Vector3(0, 0, -1).applyMatrix4(this.camGo.cam.matrixWorld);
this.initialTarget = this.targetPosition as THREE.Vector3;
this.setTarget(forward);
this.startCamPos = forward;
//this.startCamPos = getWorldPosition(this.context.mainCamera);
console.log(this.initialTarget);
}
}
}
public resetCamPos()
{
console.log("setting pos");
console.log(this.initialTarget);
this.setTarget(this.initialTarget);
this.setCameraTarget(this.startCamPos, true);
}
public setTarget(position: THREE.Vector3 | null = null, immediate: boolean = false) {
//console.log(this.initialTarget);
//console.log(position);
this.toggleStickyMode(false);
if (!this._controls) return;
this.isTransitioning = true;
console.log(position);
if (position !== null)
{
let pos = position;
this.targetPosition.copy(pos);
}
//console.log(this.initialTarget);
if (immediate)
this._controls.target.copy(this.targetPosition);
else
{
this._lerpCameraToTarget = true;
this._lerpToTargetPosition = true;
}
position = null;
}
by user 103054507105067008
In a nutshell, initialTarget
is set in Start, then it is passed in another function as the position
that setTarget
takes, but somehow when that setTarget
function runs, initialTarget
is overwritten
by user 103054507105067008
In threejs/javascript Vector3 are not structs/value types. You pass around reference types here. So when you pass your initialTarget Vector in a function and modify the vector in that function your initialTarget vector will be changed. This is a big big difference to Unity
I realise I can work around this by making that position be a gameobject position I can grab, but of course I was stifled as to why it was changing.
by user 103054507105067008
I tried using let
as I saw that in some docs but it still got overwritten
by user 103054507105067008
I also tried making a new vector which would take the value of initialTarget
and passing that new vector instead but the initialTarget
value still changed when I used that new vector!
by user 103054507105067008
It’s like it all points back to the original value still
by user 103054507105067008
That would mean you somehow still pass in a reference to your original vector
Code like this fools you:
let pos = position;
this.targetPosition.copy(pos);
since pos is still position
even tho you declare a new variable - it IS the same vector
this is what I mean above - there are no value types in js like in Unity for these (just the builtin types for number, boolean, undefined, null and symbol)
Seems it
public resetCamPos()
{
let pos = new THREE.Vector3(0,0,0);
pos = pos.copy(this.initialTarget);
console.log("setting pos");
console.log(this.initialTarget);
this.setTarget(pos);
}
This was what didn’t work
by user 103054507105067008
Vector3 is a reference type
Maybe there’s another path that accidentally uses initialTarget? (btw you could also just write this.initialTarget.clone()
)
I have double checked all initialTarget references
by user 103054507105067008
I’ll use that .clone()
as you said, shall I make a new Vector3 and do like
const pos = this.initialTarget.clone()
by user 103054507105067008
Yup depending on how often you do that per frame its fine (i would avoid it if its called a lot per frame).
Only gets set once when a button is pressed
by user 103054507105067008