PlayerAnimator (JumpController + MinimalLocomotion)
Аниматор на Animancer, полностью управляется дельтой Transform (никакого Animator-контроллера,
никаких параметров). Поэтому одинаково работает на локальном игроке и на сетевых репликах —
единственный вход это позиция Transform. Foot IK — сторонний (HoaxGames.FootIK / iStep) через
ApplyAnimatorIK на Layer 0, включается один раз, сам гасит коррекцию в воздухе.
Оба скрипта висят на объекте с AnimancerComponent и дерут один Layer 0. Чтобы не конфликтовать,
на время прыжка JumpController ставит локомоушн на Suspend() (тот продолжает мерить скорость, но
анимацию не трогает); PlayLocomotion() снимает Suspend на приземлении.
MinimalLocomotion — ходьба/бег/стойка
Idle-клип отдельно + один Cartesian-микшер движения (17 нод: idle + 8 walk + 8 run, порог = м/с).
Скорость берётся из (pos - prevPos)/dt в локальных осях (X=стрейф, Z=вперёд).
Инспектор:
- _idle — отдельный Stand_Idle (короткий fade).
- _locomotion — MixerTransition2D (Type=Cartesian).
- _dampMove — демп параметра микшера (разгон/поворот/реверс).
- _idleThreshold — ниже этой скорости считаем «стоим».
- _idleEnterDelay — гистерезис: скорость должна ПРОДЕРЖАТЬСЯ ниже порога столько сек, прежде чем
щёлкнуть idle-клип. Главный фикс дёрганья поз на спаме W/S (реверс короче окна idle не включает).
- _reverseDampMove — более короткий демп при развороте (цель против текущего параметра).
- _minMoveMagnitude — минимальная величина параметра при движении (0=выкл); поднимает медленное
движение из мёртвой зоны центра микшера в чистую направленную позу (темп ног правит warp).
- _enableWarp,_minScale,_maxScale,_minRefSpeed — speed-warp: подгон темпа проигрывания под
реальную скорость (reference = взвешенная скорость текущей смеси нод).
JumpController — прыжок/полёт/приземление
Фазы: Grounded → JumpStart → Airborne → Landing → Grounded. Земля — SphereCast/CheckSphere из
_groundCastOrigin. Скорости меряются дельтой Transform в LateUpdate.
Флоу:
- Отрыв (ClassifyTakeoff): стоя на месте (hSpeed ≤ _movementThreshold И vy > _jumpVyThreshold)
→ JumpStart (_startGrounded). Иначе (в движении/падение с края) → Airborne (_airLoop).
Старта из ходьбы/бега нет намеренно.
- JumpStart → Airborne по апексу/удару в потолок/концу клипа. Приземление приоритетнее.
- Приземление (EnterLanding) — по двум интервалам скорости касания (мгновенно): скорость в
[runMin,runMax] + вперёд → _landRun; в [walkMin,walkMax] + вперёд → _landWalk; в любом
интервале, но НЕ вперёд → _landStrafe; всё вне обоих интервалов → idle end
(_landSoft/_landHard, жёсткое ТОЛЬКО по времени полёта). Неназначенный moving-клип → idle end.
Скорость касания = _lastAirLocalVelocity (последний воздушный кадр).
- Landing → Grounded (ReturnToLocomotion) по концу клипа (End Time из инспектора Animancer) или по
прерыванию движением, но не раньше grace-окна.
Инспектор:
- Клипы: _startGrounded,_airLoop,_landSoft,_landHard,_landWalk,_landRun,_landStrafe.
- Ground Check: _groundCastOrigin,_groundMask,_groundCheckRadius,_groundCheckDistance.
- _jumpVyThreshold — vy отрыва для прыжка с места. _movementThreshold — порог «стоит/движется».
- _walkLandMin/Max,_runLandMin/Max — два интервала скорости касания (4 числа): попал в run-интервал
→ run, в walk-интервал → walk, вне обоих → idle. «Всё выше = run» → _runLandMax большим (напр. 100).
- _hardLandingAirtime — сек в воздухе, после которых idle-приземление жёсткое (_landHard).
- _minLandingAirtime — ниже этого времени полёта landing-флоу не проигрывается (микро-хопы → сразу локо).
- _landingInterruptDelay — grace: сколько landing-клип обязан отыграть до прерывания движением
(защита от residual-скорости торможения; End Time окном НЕ блокируется).
- _debugLog — цветные логи каждого перехода: head (JUMP-START/AIRBORNE/LAND-RUN/WALK/STRAFE/IDLE/→LOCO),
клип+fade, причина (hSpeed/maxAir/dir/в какой интервал попал/причина выхода) и (+Ns) с прошлого
перехода. У MinimalLocomotion своя галка _debugLog — логирует вход в IDLE/MIXER с fade.
Прерывание уже играющего landing: idle-ленд рубится началом движения (> _movementThreshold);
moving-ленд рубится торможением ниже нижней границы своего интервала (run→_runLandMin, walk→_walkLandMin)
→ уходим в локо. Оба — не раньше grace-окна _landingInterruptDelay.
Клипы/ноды раскладывает редактор-утилита Editor/LocoV0Setup.cs (меню LocoV0/…); тайминги
(Start/End Time, Fade) правятся в самих ClipTransition в инспекторе и утилитой НЕ затираются.
Известные ограничения на реплике и планы — см. TODO.md.