fix(lua): part.Position теперь реально двигает куб

КОРНЕВАЯ ПРИЧИНА: BabylonScene.freezeStaticPrimitives() замораживает
world matrix anchored-примитивов при Play для оптимизации.
mesh.position.set(x,y,z) после этого не обновляет рендер.

Фикс в PrimitiveManager.updateInstance: если patch содержит position/
rotation/size — расфризить world matrix прежде чем менять transform.
This commit is contained in:
min 2026-06-08 12:19:14 +03:00
parent ecc2055b3d
commit 936f93a42c
4 changed files with 40 additions and 22 deletions

View File

@ -185,7 +185,12 @@ export class GameRuntime {
sb.setOnCommand(({ cmd, payload }) => {
if (cmd === 'partSet' || cmd === 'partVel' ||
cmd === 'sceneCreate' || cmd === 'sceneDelete') {
try { handleLuaCommand(null, cmd, payload, this); } catch (_) {}
try {
handleLuaCommand(null, cmd, payload, this);
} catch (e) {
// eslint-disable-next-line no-console
console.error('[GameRuntime] handleLuaCommand failed:', cmd, payload, e);
}
} else {
this._handleCommand(null, cmd, payload);
}

View File

@ -689,7 +689,16 @@ export class PrimitiveManager {
const data = this.instances.get(id);
if (!data) return;
// Позиция
// Позиция / поворот / размер — нужно расфризить world matrix,
// иначе freezeStaticPrimitives() сделает mesh.position.set бессмысленным.
const positionChanged = patch.x !== undefined || patch.y !== undefined || patch.z !== undefined;
const transformChanged = positionChanged
|| patch.rotationX !== undefined || patch.rotationY !== undefined || patch.rotationZ !== undefined
|| patch.sx !== undefined || patch.sy !== undefined || patch.sz !== undefined;
if (transformChanged && data._worldMatrixFrozen) {
try { data.mesh.unfreezeWorldMatrix?.(); } catch (_) {}
data._worldMatrixFrozen = false;
}
if (patch.x !== undefined) data.x = patch.x;
if (patch.y !== undefined) data.y = patch.y;
if (patch.z !== undefined) data.z = patch.z;

View File

@ -279,7 +279,6 @@ function newPart(primData, sendFn) {
};
// Setter'ы шлют partSet → BabylonScene.primitiveManager через handleLuaCommand.
// Формат payload должен соответствовать rbxl-lua-integration.js#handleLuaCommand.
const send = (prop, value) => {
try { sendFn('partSet', { primId: p.__primId, prop, value }); } catch (_) {}
};

View File

@ -122,9 +122,11 @@ export function handleLuaCommand(_scriptId, cmd, payload, runtime) {
return;
}
if (cmd === 'partSet') {
try {
const pm = runtime.scene3d?.primitiveManager;
if (!pm) return;
if (!pm) {
console.warn('[partSet] no primitiveManager. scene3d=', !!runtime.scene3d);
return;
}
const primId = payload?.primId;
const prop = payload?.prop;
const value = payload?.value;
@ -141,10 +143,13 @@ export function handleLuaCommand(_scriptId, cmd, payload, runtime) {
else if (prop === 'anchored') patch.anchored = value;
else if (prop === 'canCollide') patch.canCollide = value;
else if (prop === 'opacity') patch.opacity = value;
try {
if (typeof pm.updateInstance === 'function') pm.updateInstance(primId, patch);
else if (typeof pm.applyPatch === 'function') pm.applyPatch(primId, patch);
else if (typeof pm.update === 'function') pm.update(primId, patch);
} catch (e) {}
} catch (e) {
console.error('[partSet] updateInstance failed:', e);
}
return;
}
if (cmd === 'sceneCreate') {