In first-person view, when moving left and right, the ray behaves normally. However, through the light source on the arm, the SpotLight can be seen moving, even though the light source is bound inside the lightAnchorNode within the playerNode. When pressing the V key to switch to third-person view and moving left and right again, the origin point of the ray becomes delayed, leaving a visual trail of movement, but the SpotLight returns to normal. This effect becomes more noticeable when pressing the Shift key to move quickly.
Here I’ve made a simple demo at: https://playground.babylonjs.com/#NEMERE#52
When using the A and D keys to move back and forth, the laser and flashlight can be seen shaking erratically, while in third-person view, they behave normally
Hi @Yasinli29 — nice repro! The flicker is a one-frame parallax between your first-person camera and the parented SpotLight. Here’s what happens each frame:
Your Player.onBeforeRender callback updates playerNode.position to the new value.
Your CameraManager.onBeforeRender callback then copies cameraAnchorNode.absolutePosition into the FP camera. But absolutePosition is a cached value that is only refreshed during the world-matrix pass of the render phase — i.e. after all onBeforeRender callbacks. So the camera gets the previous frame’s position.
The SpotLight (parented under playerNode → flashlightAnchor) is read directly from the freshly-recomputed world matrix during render, so it ends up at the current frame’s position.
Result: camera lags one frame behind the spotlight → visible jitter, especially while strafing or sprinting. Third-person works because ArcRotateCamera.lockedTarget is resolved later in the pipeline, after world matrices are up to date.
Two small fixes needed in your code:
In CameraManager.registerRenderObserver, force the world matrix to refresh before reading the position:
In Player’s constructor, register the render observer synchronously (not inside loadModel().then(...)) so player position is updated before CameraManager reads it; guard the animator call with ?. since the model is still loading:
Yesterday I also spent the whole day looking for the issue, and finally discovered that there was a discrepancy between cameraAnchorNode.absolutePosition and its actual position. In the end, I used playerNode.position.add(cameraAnchorNode.position) to determine the final position of cameraAnchorNode and solved the problem. Your reply is extremely important to me — I didn’t even know such a magical method as computeWorldMatrix existed. Thank you so much.