From 462ee62a9a20f7d97cddd26b638e7819051f1e15 Mon Sep 17 00:00:00 2001 From: min Date: Tue, 9 Jun 2026 18:07:25 +0300 Subject: [PATCH] =?UTF-8?q?fix(g7):=20Touched=20=D0=BD=D0=B0=20=D1=81?= =?UTF-8?q?=D0=BF=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D1=8F=D1=85=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7?= =?UTF-8?q?=20AABB-check=20=D0=B2=20Heartbeat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BabylonScene._detectTouchEvents работает только для скриптов с явным target. Спавненные runtime через __rbxl_spawn_part (падающие кубы) не имеют target — Babylon их не проверяет, Touched молчит. Решение: shim.fireHeartbeat теперь сам делает AABB игрок↔part для всех part id >= 800000 (наш range спавненных). При пересечении фейерит Touched.Fire(hrp); при выходе — TouchEnded. --- src/editor/engine/lua/RobloxShim.js | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index 122086d..6f92cf1 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -2038,6 +2038,38 @@ export function registerRobloxShim(lua, opts) { fireHeartbeat(dt) { try { HEARTBEAT_SIGNAL.Fire(dt); } catch (_) {} try { STEPPED_SIGNAL.Fire(performance.now() / 1000, dt); } catch (_) {} + // Авто-детект Touched на спавненных частях (id >= 800000): + // BabylonScene._detectTouchEvents срабатывает только для скриптов + // с явным target. Спавненные через __rbxl_spawn_part примитивы + // (падающие кубы, снаряды) Babylon не знает, поэтому делаем + // AABB-check игрок↔part прямо в shim каждый кадр. + try { + const pp = api._realPlayerPos; + if (!pp) return; + const phw = 0.4, phh = 0.9, phd = 0.4; + for (const [id, part] of partById.entries()) { + if (id < 800000) continue; + if (!part || part.Destroyed) continue; + if (!part.Touched || part.Touched.connections.length === 0) continue; + const pos = part._state?.Position; + const size = part._state?.Size; + if (!pos || !size) continue; + const hw = size.X / 2 + 0.1; + const hh = size.Y / 2 + 0.1; + const hd = size.Z / 2 + 0.1; + const overlap = + pp.x + phw > pos.X - hw && pp.x - phw < pos.X + hw && + pp.y + phh > pos.Y - hh && pp.y - phh < pos.Y + hh && + pp.z + phd > pos.Z - hd && pp.z - phd < pos.Z + hd; + if (overlap && !part.__lastTouching) { + part.__lastTouching = true; + try { part.Touched.Fire(hrp); } catch (_) {} + } else if (!overlap && part.__lastTouching) { + part.__lastTouching = false; + try { part.TouchEnded.Fire(hrp); } catch (_) {} + } + } + } catch (_) {} }, fireTargetEvent(p) { if (!p) return;