cocos-engine
cocos-engine copied to clipboard
[3.x] Pointer lock still moves cursor
Creator version?(版本号)
3.3 and 3.4
Affected platform?(受影响的平台)
platforms with mouse
The issue is in mouse-input.ts around line 37, this code
const canvasRect = this._getCanvasRect();
const dpr = screenAdapter.devicePixelRatio;
let x = this._pointLocked ? (this._preMousePos.x / dpr + mouseEvent.movementX) : (mouseEvent.clientX - canvasRect.x);
let y = this._pointLocked ? (this._preMousePos.y / dpr - mouseEvent.movementY) : (canvasRect.y + canvasRect.height - mouseEvent.clientY);
x *= dpr;
y *= dpr;
return new Vec2(x, y);
}
the lines that check this._pointLocked and then add movement to the locked position are wrong. If the pointer is locked, the x/y position reported should not change. One solution is
let x = this._pointLocked ? (this._preMousePos.x / dpr ) : (mouseEvent.clientX - canvasRect.x);
let y = this._pointLocked ? (this._preMousePos.y / dpr): (canvasRect.y + canvasRect.height - mouseEvent.clientY);
I'm sure there's some reason this code was written like this in the past but it causes issues because the mouse pointer moving while hidden will cause it to go over UI elements. Those UI elements will get events rather than the up event making its way up to the system level. This makes it difficult to support right click mouse camera movement where you hide the cursor and just use deltas to rotate/move the camera.
for reference: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
The reason for this is that usually the game will have a game mouse, and if pointerlock is canceled, the game mouse should overlap with the system mouse. If you do need fixed coordinates, you can get the current mouse position after starting pointerlock.
The reason for this is that usually the game will have a game mouse, and if pointerlock is canceled, the game mouse should overlap with the system mouse. If you do need fixed coordinates, you can get the current mouse position after starting pointerlock.
This doesn't solve the problem of UI elements getting hover events since that is internal to the engine. Also, it seems like a bad assumption that the game will have a game cursor that should be tracked. A first person game would not have a game cursor at all and would have a reticle in the center of the screen that never moves.
Perhaps an option could be added to the engine to provide the desired behavior? Either track the real cursor (the case you mentioned) or don't track it.