7.1 KiB
Камера з конфігу платформи стала реальною (2026-08-14)
Слайдери camera_position_p/_l і camera_rotation_p/_l у Scene settings були
мертві: CameraFollowC.init() рахував позицію з константи CAMERA_OFFSET і
виводив кут одноразовим lookAt(), а конфіг не читав узагалі. Продюсер міг
крутити шість повзунків без жодного ефекту.
Вимога: повзунки прибирати не можна, вони мають працювати — і в експорті, і в прев'ю платформи.
Що з'ясувалось під час розбору
Формат конфігу читається не так, як виглядає. У globalSettings.ts кожна
вісь масивного параметра описана як [min, max, default], тому
camera_position_p виглядав як три трійки координат. Насправді дефолт — це
третій елемент кожної трійки, а в рантаймі Template.getCategory("global")
віддає плаский [x, y, z]. Перевірено прогоном справжнього
formConfigForPlayable(formConfigUI(...)) над нашим же globalSettings.
Старі дефолти були з іншої моделі камери. [-2, 5, 42] — це абсолютна
позиція камери зі статичного SDK-шаблону. У грі з follow-камерою абсолютна
позиція безглузда (її перезаписує кожен кадр), осмислений лише офсет відносно
гравця. Оскільки ці значення ніколи ні на що не впливали, від них нічого не
залежало — семантику переінтерпретовано на офсет.
Object3D.lookAt і Camera.lookAt — різні. Перша спроба вирахувати
еквівалентний кут дала x=53.13, y=0, z=0 і виглядала правдоподібно, але
контрольна перевірка (зібрати кватерніон назад із цих кутів і зміряти
forward · напрямок_на_ціль) дала −1.0 — камера дивилась рівно в
протилежний бік. Причина в самому three.js:
if (this.isCamera || this.isLight) _m1.lookAt(_position, _target, this.up);
else _m1.lookAt(_target, _position, this.up);
Звичайний Object3D наводить на ціль свою вісь +Z, камера — −Z. Розрахунок
на Object3D замість PerspectiveCamera дає дзеркальний результат.
Урок: будь-який офлайн-розрахунок орієнтації перевіряти зворотним ходом
(відновити з чисел і зміряти скалярний добуток), а не приймати правдоподібні
числа на віру.
Справжній кут для офсету (0, 8, -6) — x=-126.87, y=0, z=-180. Еквівалентна,
але читабельніша форма x=53.13, y=180, z=0 дає той самий кватерніон і той
самий up-вектор — саме її записано в дефолти. y=180 тут не довільне: риг стоїть
позаду гравця на −Z і дивиться назад у +Z, а камера three.js за замовчуванням
дивиться в −Z.
Тип параметра — int, тож 53.13 округлено до 53. Відхилення від старого
кадру — 0.13°, візуально непомітно.
Що змінено
globalSettings.ts— тільки дефолти (id, назви, типи й діапазони не чіпані; діапазони вже покривали нові значення). Портрет і ландшафт отримали однаковий риг, бо гра й досі використовує одинCAMERA_OFFSETдля обох — тепер їх можна розвести з платформи.CameraFollowC— новийapplyRigFromConfig(): читає офсет і кут за поточною орієнтацією, застосовує кут, лишається єдиним писаремcamera.rotation.readVec3()відсіює биті значення, і тоді кут виводиться старим способом (frameTargetAndStoreRotation()) — зламаний конфіг деградує до «кадрує гравця», а не до порожнього неба.beforeResourcesLoadedCb—updateVariableConfigтепер маршрутизуєcamera_position_*/camera_rotation_*уCameraFollowC, FOV лишається заCameraC. Роздільна власність — це і є захист від повторення бага з двома писарями.resizeCb— на зміні орієнтації перечитує і FOV, і риг.DebugConfigC— повзунки кута/дистанції сідають із того самого конфігу (readCameraRigFromConfig()), дубльована константаDEFAULT_CAMERA_OFFSETприбрана.setOffset()і далі авто-кадрує й синхронізуєrotationDeg.TestSceneC.CAMERA_OFFSET— лишився як фолбек, коментар оновлено.
Перевірено
npx vite build— 886 модулів, чисто.- Прогін реального SDK-пайплайна: гра читає
camera_position_p = [0, 8, -6],camera_rotation_p = [53, 180, 0]; відновлена з цих чисел камера дивиться на гравця з похибкою 0.13°. npx tsc --noEmitу проєкті не запускається —tsconfig.jsonміститьmoduleResolution: node10, яку TypeScript 7 видалив (TS5108). З обходом цієї опції лишаються дві доіснуючі помилки, обидві не в зміненому коді: deep-importthree/src/math/ColorуThreeC.tsі застаріла декларація SDK дляJoystickC.init({ color }).
Не перевірено
Візуально в браузері нічого не запускалось. Потрібен ручний прогін: старт у портреті, поворот у ландшафт, правка повзунків на платформі наживо.
Відкрите
Значення, збережені для вже наявних креативів на платформі, лишились у старій (абсолютній) семантиці — їх треба одноразово перевиставити на офсет-значення.