fix(g15): клик в 3-м лице по координатам курсора, не центру

В 3-м лице курсор свободный. _handlePlayClick ВСЕГДА пикал центром
экрана через _pickFromCenter — независимо от того где находится курсор.
Поэтому клик мышкой по мишени не срабатывал — пик шёл из центра.

Фикс: проверяем document.pointerLockElement:
- locked (1-е лицо) → _pickFromCenter (прицел всегда в центре)
- !locked (3-е лицо) → scene.pick(clickX, clickY) по реальной позиции
  курсора при клике.

Убрал debug-логи.
This commit is contained in:
min 2026-06-09 19:59:38 +03:00
parent 12efef7ff5
commit d6a874c8a0
2 changed files with 26 additions and 11 deletions

View File

@ -3271,7 +3271,30 @@ export class BabylonScene {
}
if (!this.gameRuntime) return;
const pick = this._pickFromCenter();
// В pointer-lock (1-е лицо) курсор скрыт в центре — пикаем центром.
// В 3-м лице (свободный курсор) — пикаем по координатам клика.
const locked = (document.pointerLockElement === this.canvas);
let pick;
if (!locked && Number.isFinite(clickX) && Number.isFinite(clickY)) {
const pi = this.scene.pick(clickX, clickY, (mesh) => {
if (!mesh.isPickable) return false;
if (mesh === this._ghostMesh) return false;
if (mesh.name && mesh.name.startsWith('gridLine')) return false;
return true;
});
if (pi?.hit) {
let m = pi.pickedMesh;
if (m?.metadata?._isBlockProto && this.blockManager) {
const proxy = this.blockManager.findProxyByPickInfo(pi);
if (proxy) m = proxy;
}
pick = { mesh: m, point: pi.pickedPoint, pickInfo: pi };
} else {
pick = null;
}
} else {
pick = this._pickFromCenter();
}
const target = pick?.mesh ? this._meshToTarget(pick.mesh) : null;
const point = pick?.point ? { x: pick.point.x, y: pick.point.y, z: pick.point.z } : null;
// 1) Self-onClick — только если target есть

View File

@ -2173,27 +2173,19 @@ export function registerRobloxShim(lua, opts) {
if (!p) return;
const id = p.primId ?? p.target;
const part = partById.get(Number(id));
if (p.kind === 'click') {
// eslint-disable-next-line no-console
console.warn('[shim fireTargetEvent click] primId=', id, 'part=', !!part);
}
if (!part) return;
if (p.kind === 'touch' || p.kind === 'touched') {
part.Touched.Fire(hrp);
} else if (p.kind === 'untouch' || p.kind === 'untouched') {
part.TouchEnded.Fire(hrp);
} else if (p.kind === 'click') {
// ClickDetector создаётся лениво — стрельба по 3D-объектам.
// ClickDetector — стрельба по 3D-объектам.
// Фейерим без аргумента (передача объектов в Lua через wasmoon
// может крашить с null.then).
try {
const cd = part._clickDetector;
// eslint-disable-next-line no-console
console.warn('[shim click]', 'partId=', id, 'cd=', !!cd, 'sig=', !!cd?.MouseClick, 'conns=', cd?.MouseClick?.connections?.length);
if (cd && cd.MouseClick) cd.MouseClick.Fire();
} catch (e) {
console.warn('[shim click err]', e?.message || e);
}
} catch (_) {}
try {
if (part.Clicked) part.Clicked.Fire();
} catch (_) {}