This shows you the differences between two versions of the page.
irva:laboratoarevr:03 [2024/10/12 00:52] andrei.lapusteanu |
irva:laboratoarevr:03 [2024/10/29 12:34] (current) andrei.lapusteanu typos |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Laborator VR 03. SteamVR. Advanced input ====== | ====== Laborator VR 03. SteamVR. Advanced input ====== | ||
- | În acest laborator vom studia câteva aspecte mai avansate legate de input - cum îl putem citi în cod, cum ne putem defini acțiuni noi / custom - veți reuni aceste aspecte în implementarea unui gravity gun! | + | În acest laborator vom studia câteva aspecte mai avansate legate de input - cum îl putem citi în cod, cum ne putem defini acțiuni custom - veți reuni aceste aspecte în implementarea unui gravity gun! |
<note warning> | <note warning> | ||
Line 11: | Line 11: | ||
Sistemul de input folosit în SteamVR se bazează pe **acțiuni**. | Sistemul de input folosit în SteamVR se bazează pe **acțiuni**. | ||
- | Înainte să discutăm despre el, prezentăm pe scurt în continuare cele 2 paradigme de folosire al input-ului în **Unity**. | + | Înainte să discutăm despre el, vom prezenta pe scurt cele 2 paradigme de folosire a input-ului în **Unity**. |
<note> | <note> | ||
- | Următoarele subsecțiuni au scop informativ, nu sunt esențiale în rezolvarea laboratorului, dar vă introduc în modalitatea în care SteamVR se ocupă de input. | + | Următoarele subsecțiuni au scop informativ, nu sunt esențiale în rezolvarea laboratorului, dar vă introduc în modalitatea în care se prelucreză input-ul în SteamVR. |
</note> | </note> | ||
Line 46: | Line 46: | ||
* **MovementOnFoot** pentru mișcare pedestră (WASD pe tastatură sau joystick pe un controller) | * **MovementOnFoot** pentru mișcare pedestră (WASD pe tastatură sau joystick pe un controller) | ||
* **MovementInCar** pentru condusul unei mașini (**aceleași taste WASD** pe tastatură sau joystick pe un controller, dar într-un alt context!) | * **MovementInCar** pentru condusul unei mașini (**aceleași taste WASD** pe tastatură sau joystick pe un controller, dar într-un alt context!) | ||
- | * **MovementInBoat** pentru navigarea cu o barcă. | + | * **MovementInBoat** pentru navigarea cu o barcă |
O **acțiune** reprezintă o interacțiune definită de utilizator care poate fi activată prin diverse tipuri de input-uri. Acțiunile se pot lega la una sau mai multe intrări fizice printr-un **binding**. | O **acțiune** reprezintă o interacțiune definită de utilizator care poate fi activată prin diverse tipuri de input-uri. Acțiunile se pot lega la una sau mai multe intrări fizice printr-un **binding**. | ||
Line 54: | Line 54: | ||
* La o cale dorită în **Project window** din Unity, **click-dreapta -> Create -> Input Actions** | * La o cale dorită în **Project window** din Unity, **click-dreapta -> Create -> Input Actions** | ||
* În acest asset puteți crea mapping-uri, acțiuni și binding-uri, un exemplu este prezentat în imaginea de mai jos. | * În acest asset puteți crea mapping-uri, acțiuni și binding-uri, un exemplu este prezentat în imaginea de mai jos. | ||
- | * De asemenea, este util să bifați **Generate C# Class** din inspectorul acestui asset pentru a-l utiliza ușor în script-urile voastre | + | * De asemenea, este util să bifați **Generate C# Class** din inspectorul acestui asset pentru a-l utiliza mai ușor în script-urile voastre |
{{ :irva:laboratoarevr:irva_2024_vr_l3_newinputsystem.png?700 |}} | {{ :irva:laboratoarevr:irva_2024_vr_l3_newinputsystem.png?700 |}} | ||
Line 92: | Line 92: | ||
Sistemul de input din SteamVR **nu** se bazează în mod expres pe sistemul de input din Unity; SteamVR are un sistem propriu bazat pe acțiuni. Cu toate acestea, conceptele utilizate (acțiuni, mapări, evenimente) sunt foarte similare. Înțelegerea sistemului de input bazat pe acțiuni din Unity vă va ajuta să înțelegeți mai bine modul în care funcționează cel din SteamVR. | Sistemul de input din SteamVR **nu** se bazează în mod expres pe sistemul de input din Unity; SteamVR are un sistem propriu bazat pe acțiuni. Cu toate acestea, conceptele utilizate (acțiuni, mapări, evenimente) sunt foarte similare. Înțelegerea sistemului de input bazat pe acțiuni din Unity vă va ajuta să înțelegeți mai bine modul în care funcționează cel din SteamVR. | ||
+ | |||
+ | ===== Import schelet laborator ===== | ||
+ | |||
+ | * Importați ultima versiune a pachetului ''IRVA_L3_VR_SteamVR_Skeleton'' care se găsește în folder-ul **UnityPackages** din folder-ul root al proiectului | ||
+ | * Folder-ul **Assets -> L3_VR_SteamVR_Advanced** conține asset-urile suport pentru acest laborator. Deschideți scena ''L3_VR_SteamVR_GravityGun'' | ||
+ | |||
+ | {{ :irva:laboratoarevr:irva_2024_vr_l3_labscene.png?400 |}} | ||
+ | |||
+ | Această scenă conține prefab-ul de player, câteva mese pe care se află câteva obiecte, precum și un gravity gun. | ||
===== Sistemul de input din SteamVR ===== | ===== Sistemul de input din SteamVR ===== | ||
Line 120: | Line 129: | ||
// - `SteamVR_Input_Sources` can be used to set a specific device to read from. In this case any device which has this action. | // - `SteamVR_Input_Sources` can be used to set a specific device to read from. In this case any device which has this action. | ||
var grabPinchState = SteamVR_Actions._default.GrabPinch.GetState(SteamVR_Input_Sources.Any); | var grabPinchState = SteamVR_Actions._default.GrabPinch.GetState(SteamVR_Input_Sources.Any); | ||
- | Debug.Log($"[SteamVRInputActionsTesting] grabPinchState = {grabPinchState}"); | + | Debug.Log($"[SteamVRInputActionsTesting] Polling: grabPinchState = {grabPinchState}"); |
} | } | ||
} | } | ||
Line 132: | Line 141: | ||
</note> | </note> | ||
- | <GIF_WIP> | + | {{ :irva:laboratoarevr:irva_2024_vr_steamvr_l3_1.gif?500 |}} |
==== Citire input folosind evenimente (metodă recomandată) ==== | ==== Citire input folosind evenimente (metodă recomandată) ==== | ||
Line 149: | Line 158: | ||
| | ||
// Method called when `onChange` from the `GrabPinch` is invoked. | // Method called when `onChange` from the `GrabPinch` is invoked. | ||
- | private void OnGrabPinchChanged(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource, bool newState) | + | private void OnGrabPinchChanged(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource, bool grabPinchState) |
{ | { | ||
- | Debug.Log($"[SteamVRInputActionsTesting] fromAction = {fromAction}, fromSource = {fromSource}, newState = {newState}"); | + | Debug.Log($"[SteamVRInputActionsTesting] Events: grabPinchState = {grabPinchState}"); |
} | } | ||
} | } | ||
Line 163: | Line 172: | ||
</note> | </note> | ||
- | <GIF_WIP> | + | {{ :irva:laboratoarevr:irva_2024_vr_steamvr_l3_2.gif?500 |}} |
==== Task-ul vostru ==== | ==== Task-ul vostru ==== | ||
Line 179: | Line 188: | ||
Editați binding-ul curent (click pe **Edit** de pe **oculus_touch (Local changes)**. | Editați binding-ul curent (click pe **Edit** de pe **oculus_touch (Local changes)**. | ||
- | * În noua ferestră puteți lega **butoanele fizice** ce **acțiuni** (acesta este în esență un **binding**) | + | * În noua ferestră puteți lega **butoanele fizice** de **acțiuni** (acesta este în esență un **binding**) |
* În partea de sus puteți naviga prin diverse **action set-uri** (default, platformer, etc.). Ramâneți pentru moment pe cel default. | * În partea de sus puteți naviga prin diverse **action set-uri** (default, platformer, etc.). Ramâneți pentru moment pe cel default. | ||
* Observați în partea stăngă binding-urile deja configurate pentru **Trigger** - găsiți aici acțiunea de **Grab Pinch** | * Observați în partea stăngă binding-urile deja configurate pentru **Trigger** - găsiți aici acțiunea de **Grab Pinch** | ||
Line 186: | Line 195: | ||
<note tip> | <note tip> | ||
- | * Ca să legăm informația învățată: Acest **Grab Pinch** este o **acțiune** binded pe butonul de **Trigger**, conținută în **action set-ul default**. | + | * Ca să legăm informația învățată: Acest **Grab Pinch** este o **acțiune** binded pe butonul de **Trigger**, conținută în **action set-ul default** |
- | * În spate, SteamVR va genera cod care ne permite să referențiem în script-urile noastre aceste elemente. | + | * În spate, SteamVR va genera cod care ne permite să referențiem în script-urile noastre aceste elemente |
* Pe scurt, acesta este motivul pentru care putem referenția în cod ''SteamVR_Actions._default.GrabPinch'' | * Pe scurt, acesta este motivul pentru care putem referenția în cod ''SteamVR_Actions._default.GrabPinch'' | ||
</note> | </note> | ||
Line 226: | Line 235: | ||
{{ :irva:laboratoarevr:irva_2024_vr_l3_steamvrbindings6.png?400 |}} | {{ :irva:laboratoarevr:irva_2024_vr_l3_steamvrbindings6.png?400 |}} | ||
- | |||
- | <GIF_WIP> | ||
Awesome 🎉! În acest moment toată logica necesară acestei acțiuni (și al binding-ului) este finalizată. | Awesome 🎉! În acest moment toată logica necesară acestei acțiuni (și al binding-ului) este finalizată. | ||
Line 234: | Line 241: | ||
Pentru a testa dacă această nouă acțiune a fost configurată corect, completați script-ul ''SteamVRInputActionsTesting'' și afișați mesaje în consolă atunci când interogați această nouă acțiune **TouchTrigger**. | Pentru a testa dacă această nouă acțiune a fost configurată corect, completați script-ul ''SteamVRInputActionsTesting'' și afișați mesaje în consolă atunci când interogați această nouă acțiune **TouchTrigger**. | ||
+ | * Puteți utilza oricare din cele două metode prezentate (polling via ''Update'' sau folosind evenimente) | ||
+ | |||
+ | {{ :irva:laboratoarevr:irva_2024_vr_steamvr_l3_3.gif?500 |}} | ||
+ | |||
+ | ===== Rendering stereo ===== | ||
+ | |||
+ | În aplicațiile de VR dezvolatate cu Unity se poate seta parametrul **Stereo Rendering Mode**, care specifică modalitatea de desenare a scenei în realitate virtuală - acest aspect este controlabil întrucât în general există două ecrane (unul pentru fiecare ochi) care trebuie actualizate și există câteva moduri de bază: | ||
+ | * **Multipass**: Scena este desenată de două ori - o dată pentru fiecare ochi | ||
+ | * **Single Pass**: Scena este desenată o singură dată (într-un singur render pass, într-o singură textură) | ||
+ | * **Single Pass Instanced**: La fel cu **Single Pass** dar folosește și tehnica de **GPU instancing** (aceasta grupează mai eficient draw call-uri, reducându-le numărul) | ||
+ | |||
+ | Metodele de tip **single pass** sunt cele mai eficiente din punct de vedere computațional, dar pot suferi de **incompatibilități cu diverse shadere**. Un exemplu folosit în acest laborator este componenta de tip **LineRenderer**, care nu este desenată corect în cazul desenării single pass. | ||
+ | |||
+ | <note tip>Pentru acest laborator va trebui să schimbați din **Edit -> Project Settings -> XR Plug-In Management -> OpenVR Stereo Rendering Mode** în **Multipass**.</note> | ||
+ | |||
+ | <note important> | ||
+ | Este recomandat să dezvoltați aplicațiile în modurile cele mai eficiente (single pass) și să rețineți această setare pentru situații similare în viitor. În cadrul acestui laborator compromisul folosind Multipass este preferat pentru a ne ușura munca. | ||
+ | </note> | ||
+ | |||
+ | ===== Gravity gun ===== | ||
+ | |||
+ | Pentru a aplica cunoștințele pe care le-ați învățat pe parcursul acest laborator, va trebuie să finalizați implementarea unui **gravity gun**. | ||
+ | |||
+ | Logica de funcționare a acestui **gravity gun** este deja implimentată, voi va trebui să configurați și să legați input-ului necesar folosind **acțiuni** și **binding-uri**. | ||
+ | |||
+ | Obiectul **[GravityGun]** din scena suport este de tip **Throwable**, așadar îi puteți face grab. | ||
+ | |||
+ | <note tip> | ||
+ | Vă recomandăm (pentru acest obiect în mod particulat) să faceți grab folosind doar **grip-ul** (butonul lateral), întrucât trigger-ul va fi folosit pentru logica de funcționare. | ||
+ | </note> | ||
+ | |||
+ | ==== Funcționare gravity gun ==== | ||
+ | |||
+ | După ce **gravity gun-ul** a **fost grabbed**, va trebui să implementați următorul comportament: | ||
+ | * Dacă nu este apăsat nici un alt buton, nu trebuie să faceți nimic | ||
+ | * Dacă butonul de **trigger** este **atins (touched)**, iar un obiect este în raza sa de acțiune, are loc un efect de **snap** al acelui obiect - acesta este adus și fixat de arma gravitațională | ||
+ | * Dacă butonul de **trigger** este lăsat liber (eveniment-ul eferent **touch-ului** trece din ''true'' în ''false'', obiectul snapped este **tossed**, anume lăsat să cadă liber | ||
+ | * Dacă un obiect este snapped, iar butonul de **trigger** este **apăsat (click)**, obiectul este **propulsat (throw)** | ||
+ | |||
+ | {{ :irva:laboratoarevr:irva_2024_vr_steamvr_l3_4.gif?500 |}} | ||
+ | |||
+ | ==== Detalii implementare ==== | ||
+ | |||
+ | Logica de funcționare este implementată în ''GravityGunController'', iar obiectele interactibile care interacționează cu gravity gun-ul implementează ''GravityGunObject''. | ||
+ | * În ''GravityGunController'' aveți metodele ''SnapObject'', ''TossObject'' și ''ThrowObject'' deja implementate - acestea vor trebui apelate pe baza input-ului definit de voi | ||
+ | * Veți avea nevoie în esență de **2 acțiuni** (de ex. **GravityGunTouch** și **GravityGunClick**) | ||
+ | * Va trebui să vă definiți **2 binding-uri** (de ex. pe evenimentele de tip **Click** și **Touch** din meniul de bind-uri SteamVR) | ||
+ | * În ''GravityGunController'' va trebui să implementați logica pentru input-urile definite anterior | ||
+ | * Dacă optați pentru polling pe ''Update'', vedeți ce metode de input trebuie să folosiți (de ex. ''GetStateUp'', ''GetStateDown'', etc.) | ||
+ | * Dacă optați pentru implementarea bazată pe evenimente, vedeți ce evenimente de input trebuie să folosiți (de ex. ''onStateUp'', ''onStateDown'', etc.) | ||
+ | * Legați input-ul de metodele de ''SnapObject'', ''TossObject'' și ''ThrowObject'' pentru a finaliza implementarea | ||
+ | |||
+ | ===== Task-uri ===== | ||
+ | |||
+ | - Implementați în ''SteamVRInputActionsTesting'' logica de citire a input-ului pentru acțiunea **GrabPinch** folosind oricare dintre metodele prezentate (polling, evenimente). Afișați rezultatul în consolă pentru a confirma funcționarea | ||
+ | * Faceți referire la secțiunile //Citire input prin polling// și //Citire input folosind evenimente (metodă recomandată)// pentru snippet-uri din cod și explicații suplimentare | ||
+ | - Creați-vă o nouă acțiune **TouchTrigger**, realizați-i binding-ul pe logica de **Touch** și implementați în ''SteamVRInputActionsTesting'' logica de citire a input-ului. Afișați rezultatul în consolă pentru a confirma funcționarea | ||
+ | * Faceți referire la secțiunea //My first (new) SteamVR binding// pentru explicații suplimentare | ||
+ | - Finalizați logica pentru **gravity gun** | ||
+ | * Definiți-vă noile acțiuni și binding-uri | ||
+ | * Legați input-ul în script-ul ''GravityGunController'' și apelați metodele ''SnapObject'', ''TossObject'' și ''ThrowObject'' pe baza acestuia | ||
+ | * Faceți referire la capitolul //Gravity gun// (și subcapitolele acestuia) pentru explicații suplimentare | ||
+ | - **[✨Bonus✨]** Implementați o mecanică de **rotire** a obiectului snapped de către gravity gun folosind **stick-ul direcțional (joystick)** al controller-ului | ||
+ | * Modalitatea de transformare a input-ului oferit de joystick în rotația efectivă este la latitudinea voastră (mai precis trebuie să vedeți față de ce axe (X, Y, Z, locale, globale) rotați bazat pe valoarea input-ului | ||
+ | * Modulați viteza de rotație în funcție de valoarea analogică (0-1) oferită de joystick | ||
- | <GIF_WIP> |