Програмування логіки захвату та метання предметів в VR
Взяти предмет рукою в VR та швирнути його в стіну – один із найбазовіших та одночасно один із найтехнічно неочевидних механік. Коли вона працює добре, гравець не помічає нічого. Коли погано – предмет телепортується в руку з затримкою, дрижить при утриманні, летить не туди або проваливається крізь підлогу.
Чому стандартний Rigidbody + Attach не працює як очікується
Перший інстинкт – при захваті переміститись об'єкт у позицію контролера та зробити його child. Це працює 5 секунд. Потім виясняється:
Rigidbody з isKinematic = false під контролером-батьком поводиться непередбачуваного: фізичний движок не знає, що об'єкт рухається кінематично, продовжує обчислювати колізії зі старим velocity. Об'єкт проходить крізь поверхні при швидкому рухові руки.
З isKinematic = true об'єкт перестає брати участь у фізиці взагалі: ігнорує колізії, не штовхає інші об'єкти. Можна розмахувати мечем крізь все.
Правильне рішення в XR Interaction Toolkit – XRGrabInteractable з Movement Type = VelocityTracking. У цьому режимі об'єкт не телепортується до руки – до нього застосовується velocity, яка рухає Rigidbody до target позиції. Фізика залишається активною. Об'єкт сталкується з перешкодами при переміщенні рукою. Параметри Track Position Strength та Track Rotation Strength визначають "жорсткість" слідування – високі значення (20–30) дають щільне прилипання до руки, низькі (5–10) – м'яке, з лагом, як буцьто тримаєш важкий шар.
Метання: звідки береться velocity
Після release потрібно передати об'єкту швидкість, що відповідає рухові руки. Здавалось би, просто rigidBody.velocity = controllerVelocity. Проблеми:
Velocity контролера в XR Node – це миттєве значення у момент release. Якщо гравець різко зупинив руку перед кидком (що роблять багато хто), velocity = 0 та об'єкт падає вертикально вниз. Реальний фізичний кидок використовує піковую швидкість у фазі метання, не фінальну.
Velocity smoothing: XRGrabInteractable збирає історію позицій контролера за останні N кадрів (за замовчуванням – Velocity Smoothing буфер 5–10 фреймів). При release вичислюється середня velocity за буфером. Це імітує фізичну інерцію. У версії XR Interaction Toolkit 2.3+ параметр Throw Velocity Scale додатково масштабує фінальну velocity – значення 1.5–2.0 дає ощущення більш "важкого" кидка.
Angular velocity для обертання. Якщо не передати angular velocity при кидку – об'єкт летить без обертання, що неестетично. rigidBody.angularVelocity = controllerAngularVelocity * throwAngularVelocityScale.
Специфіка для Quest та мобільного VR
На Quest controller tracking працює з затримкою 20–30 мс (Prediction компенсує частково). Velocity із InputDevice.TryGetFeatureValue(CommonUsages.deviceVelocity) вже передбачена Meta Runtime – використовувати саме її, не вичислювати вручну по дельті позицій.
Haptic feedback при захваті – обов'язковий для якості життя. XRBaseController.SendHapticImpulse(0.7f, 0.05f) при початку grab, SendHapticImpulse(0.3f, 0.02f) при release. Без вібрації VR-захват ощущається пластиковим.
Окрема тема – two-handed grab: зброя, яку можна тримати двома руками. XR Interaction Toolkit 2.x надає XRGrabInteractable з кількома Attach Points та логікою dominant/secondary hand. Для зброї потрібна кастомна логіка: основна рука визначає позицію, друга – додає обертання вздовж осі ствола.
Терміни: базова grab/throw механіка через XR Interaction Toolkit – 2–4 робочих дні; кастомна two-handed система з haptics та velocity tuning – 1–2 тижні. Вартість визначається після аналізу вимог проекту.





