Differences

This shows you the differences between two versions of the page.

Link to this comparison view

irva:laboratoarevr:04 [2025/11/10 02:04]
andrei.lapusteanu
irva:laboratoarevr:04 [2025/11/11 18:18] (current)
andrei.lapusteanu
Line 1: Line 1:
- 
 ====== Laborator VR ​04. Meta XR. Setup și interacțiuni de bază ​====== ====== Laborator VR ​04. Meta XR. Setup și interacțiuni de bază ​======
- 
-<​hidden>​ 
  
 Dispozitivele dezvoltate de către Meta (în trecut, cunoscute ca și Oculus) sunt soluții `all-in-one` ce permit dezvoltarea aplicațiilor de realitate virtuală și oferă suport pentru cele mai recente funcționalități din acest domeniu, precum hand tracking, realitate mixtă (MR), audio spațializat,​ eye și body tracking. Dispozitivele dezvoltate de către Meta (în trecut, cunoscute ca și Oculus) sunt soluții `all-in-one` ce permit dezvoltarea aplicațiilor de realitate virtuală și oferă suport pentru cele mai recente funcționalități din acest domeniu, precum hand tracking, realitate mixtă (MR), audio spațializat,​ eye și body tracking.
Line 85: Line 82:
  
   * Descărcați și importați în proiectul de Unity:   * Descărcați și importați în proiectul de Unity:
-    * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-core-sdk-269169|Meta XR Core SDK]] +    * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-interaction-sdk-265014|Meta XR Interaction ​SDK]]. Acesta va instala ca dependințe:​ 
-    * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-interaction-sdk-essentials-264559|Meta XR Interaction ​SDK Essentials]] +      * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-core-sdk-269169|Meta XR Core SDK]] 
-    * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-interaction-sdk-265014|Meta XR Interaction ​SDK]] +      * [[https://​assetstore.unity.com/​packages/​tools/​integration/​meta-xr-interaction-sdk-essentials-264559|Meta XR Interaction SDK Essentials]] 
-      * Importați //Example Scenes// din sample-urile pachetului+    * Importați //Example Scenes// din sample-urile pachetului ​**Meta XR Interaction ​SDK**
     * Aveți linked pașii oficiali pentru [[https://​developer.oculus.com/​documentation/​unity/​unity-package-manager/​|importul pachetelor]] și modalități de [[https://​developer.oculus.com/​documentation/​unity/​unity-xr-plugin/​|update ]]a acestora     * Aveți linked pașii oficiali pentru [[https://​developer.oculus.com/​documentation/​unity/​unity-package-manager/​|importul pachetelor]] și modalități de [[https://​developer.oculus.com/​documentation/​unity/​unity-xr-plugin/​|update ]]a acestora
   * Acceptați prompt-urile care vă apar, restart la editor dacă este necesar   * Acceptați prompt-urile care vă apar, restart la editor dacă este necesar
Line 113: Line 110:
 <​note>​ <​note>​
 OpenXR reprezintă backend-ul necesar pentru a dezvolta și face build-uri folosind Meta XR. OpenXR reprezintă backend-ul necesar pentru a dezvolta și face build-uri folosind Meta XR.
-Se poate instala, în mod alternativ, din **Package Manager**, apăsați pe (+), selecați **Add package from git URL**, introduceți ''​com.unity.xr.oculus''​.+Se poate instala, în mod alternativ, din **Package Manager**, apăsați pe (+), selecați **Add package from git URL**, introduceți ''​com.unity.xr.openxr''​.
 </​note>​ </​note>​
  
Line 156: Line 153:
 </​note>​ </​note>​
  
-=== Erori build Gradle === +<note warning>​ 
 +Dacă întâmpinați erori de compilare la build, cel mai probabil sunt datorită script-ului ''​GravityGunController''​ din laboratorul 3. Pe scurt, build-ul din laboratorul curent încearcă să compileze acest script, care conține componente specifice SteamVR, iar cum SteamVR nu este inclus în build, acele componente nu sunt găsite.
  
-<note important>​ +Unity package-ul pentru L3 a fost actualizat pentru a rezolva această problemă, ​**dar pentru a rezolva ​pe loc eroarea** cuprindeți întreg script-ul ''​GravityGunController''​ într-o directivă de preprocesare corespunzătoare build-urilor Standalone, astfel: 
-S-ar putea ca setarea **Project Settings → Player → Other Settings → Target API Level**, care în mod implicit este pe **Automatic (highest installed)**,​ să nu fie suficientă,​ așadar recomandăm să testați API Level-uri 31+ (setați-le manual).+ 
 +<code c#> 
 +#if UNITY_STANDALONE  
 + 
 +// ... script GravityGunController ... 
 + 
 +#endif 
 +</​code>​
 </​note>​ </​note>​
  
Line 167: Line 172:
  
   * Importați ultima versiune a pachetului ''​IRVA_L4_VR_MetaXR_Skeleton''​ care se găsește în folder-ul **UnityPackages** din folder-ul root al proiectului   * Importați ultima versiune a pachetului ''​IRVA_L4_VR_MetaXR_Skeleton''​ care se găsește în folder-ul **UnityPackages** din folder-ul root al proiectului
 +  * Deschideți scena din schelet - veți lucra pentru următoarele task-uri în aceasta
  
 ==== Building Blocks ===== ==== Building Blocks =====
Line 190: Line 196:
 ==== Interactions Rig ==== ==== Interactions Rig ====
  
-În trecut, ​componentele player-ului trebuiau alcătuite din building block-uri separate. De exemplu, dacă doream un player care să poată folosi atât controllerele cât și mâinile pentru a interacționa cu un obiect trebuiau inserate:+În primele iterații ale sistemului de building blocks ​componentele player-ului trebuiau alcătuite din building block-uri separate. De exemplu, dacă doream un player care să poată folosi atât controllerele cât și mâinile pentru a interacționa cu un obiect trebuiau inserate:
   * Building block | Camera Rig   * Building block | Camera Rig
   * Building block | Controller Tracking   * Building block | Controller Tracking
Line 208: Line 214:
  
 <​note>​ <​note>​
-Urătoarele subsecțiuni au scop informativ - vă recomandăm să le parcurgeți pentru a vă familiariza cu modul în care este configurat player-ul!+Următoarele subsecțiuni au scop informativ - vă recomandăm să le parcurgeți pentru a vă familiariza cu modul în care este configurat player-ul!
 </​note>​ </​note>​
  
Line 245: Line 251:
 <note important>​ <note important>​
  
-Ce este esențial de reținut este că orice **interacțiune** necesită pe de-o parte un **interactor**,​ de exemplu, un **HandGrabInteractor** (vedeți în ierarhie **[BuildingBlock] OVRInteractionComprehensive -> LeftInteractions -> Hand and No Controller -> HandGrabInteractor**) care poate **interacționa** doar cu un obiect care are atașat un script de tip **interactibil**,​ în cazul acesta, un **HandGrabInteractable**+Ce este esențial de reținut este că orice **interacțiune** necesită pe de-o parte de un **interactor**,​ de exemplu, un **HandGrabInteractor** (vedeți în ierarhie **[BuildingBlock] OVRInteractionComprehensive -> LeftInteractions -> Hand and No Controller -> HandGrabInteractor**) care poate **interacționa** doar cu un obiect care are atașat un script de tip **interactibil**,​ în cazul acesta, un **HandGrabInteractable**
  
 **Rețineți**,​ de asemenea, că **interactorul** poate **interacționa** cu un **interactibil de același tip** - de exemplu, un interactor de tip **Poke** nu poate comunica cu un interactibil de tip **Distance** Grab. **Rețineți**,​ de asemenea, că **interactorul** poate **interacționa** cu un **interactibil de același tip** - de exemplu, un interactor de tip **Poke** nu poate comunica cu un interactibil de tip **Distance** Grab.
Line 293: Line 299:
  
 === Construcție pose pentru hand grab === === Construcție pose pentru hand grab ===
 +
 +Dacă ați testat scena sample **ComprehensiveRigExample** poate ați observat faptul modelul mâinii se conformează unor pose-uri prestabilite atunci obiectele din scenă (torța și cana).
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_samples_1.gif?​400 |}}
 +
 +De asemenea, SDK-ul oferă suport pentru diferite dimenisuni ale mâinii (în funcție de utilizator).
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_samples_2.gif?​400 |}}
 +
 +Acest feature oferă un grad sporit de imersivitate,​ întrucât dezvoltatorii se pot asigura de faptul că interacțiunea mână-obiect virtual este desenată fără probleme cum ar fi clipping-ul.
 +
 +<note tip>
 +În continuare în laborator sunt prezentați pașii necesari pentru realizarea acestui pose custom - găsiți mai multe detalii legate de proces în documenția oficială:
 +  * [[https://​developers.meta.com/​horizon/​documentation/​unity/​unity-isdk-creating-handgrab-poses|Create a Hand Grab Pose (PC)]]
 +  * [[https://​developers.meta.com/​horizon/​documentation/​unity/​unity-isdk-create-handgrab-poses-mac|Create a Hand Grab Pose (Mac)]]
 +</​note>​
 +
 +Meta SDK oferă un utilitar pentru a crea pose-uri custom pentru obiecte/​modele artbitrare printr-un proces de înregistrare a unui snapshot al pose-ului.
 +
 +În acest laborator, obiectul **[Gun]** are atașat doar un script ''​Grabbable'',​ dar momentan nu are un ''​HandGrabInteractable''​. În loc să atașăm manual această componentă (care nu definește un pose al mâinii), vom crea cu acest utilitar un nou pose, care va crea la rândul său componenta ''​HandGrabInteractable''​ necesară.
 +
 +Deschideți utilitarul din toolbar, **Meta -> Interaction -> Hand Grab Pose Recorder**.
 +
 +Completați câmpurile de la secțiunea **1**.
 +  * **LeftInteractions** sau **RightInteractions** (copil al obiectului **[BuildingBlock] OVRInteractionComprehensive**),​ în funcție de ce mână doriți să folosiți
 +  * Rigidbody-ul obiectului **[Gun]**
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_custom_setup.png?​400 |}}
 +
 +Pentru a înregistra un pose custom, urmați următorii pași (aveți și un GIF de ajutor după lista de mai jos)
 +  * Rulați scena (Play mode)
 +  * Asigurați-vă că aveți fereastra utilitarului selectată
 +  * Puneți-vă casca
 +  * Așezați-vă mâna pe grip-ul armei într-un pose ca și cum ați ține-o în mână
 +  * Când sunteți mulțumiți de pose, apăsați pe butonul **Space** de pe tastatură - ar trebui să vă apară un ghost ce indică capturarea pose-ului
 +  * **Nu ieșiți înca din Play mode!** Dați-vă casca jos și apăsați pe butonul de la secțiunea 3, **Save To Collection**
 +  * Puteți închide acum Play mode și ultimul pas este apăsarea butonului de la secțiunea 4, **Load From Collection**
 +  * Verificați în inspector dacă s-a creat un nou obiect **HandGrabInteractable**,​ copil al obiectului **[Gun]**
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_custom_1.gif?​600 |}}
 +
 +=== Ajustări pose custom ===
 +
 +În continuare, puteți rafina pose-ul prin manipularea încheieturilor de pe obiectul **HandGrabInteractable -> HandGrabPose**. Ajustați poziția degetelor după caz.
 +
 +Va trebui să modificați pose-ul astfel încât acesta indică **apăsarea completă a trăgaciului armei**. Workflow recomandat (aveți GIF mai jos):
 +  * Rămâneți în Edit mode
 +  * De pe **GunTriggerPivot** selectați **Testing | Set full curl** pentru a simula poziția trăgaciului complet apăsat
 +  * Selectați **HandGrabPose**
 +  * Asigurați-vă că aveți gizmo-urile active în Scene View
 +  * Rotiți incheieturile pentru a ajusta pose-ul
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_custom_2.gif?​600 |}}
 +
 +=== Reguli de grabbing și de pose ===
 +
 +Ultimele ajustări pe care trebuie să le faceți țin de **regulile** care determină grab-ul obiectului, precum și specificarea constrângerilor degetelor în momentul în care arma este ținută în mână.
 +
 +<note tip>
 +  * Nu vrem să facem grab folosind degetul arătător (index) întrucat s-ar putea să declanșăm tragerea armei în momentul grab-ului!
 +  * De asemenea, cât timp ținem arma în mână am dori să **constrângem pose-ul** tuturor degetelor (să fie fixe), mai puțin pe cel arătător, pentru a putea interacționa cu trăgaciul armei
 +</​note>​
 +
 +Pentru a realiza aceste setări, modicați de pe **HandGrabInteractable** atât **Pinch Grab Rules** cât și **Palm Grab Rules** astfel:
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_grab_rules.png?​350 |}}
 +
 +În final, ajustați pose-ul degetelor astfel (de pe **HandGrabPose**,​ **Fingers Freedom**):
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_rules.png?​350 |}}
 +
 +=== Finalizare task hand pose custom ===
 +
 +Pentru a valida setup-ul pentru pose-ul custom al mâinii:
 +  * Rulați scena
 +  * Faceți grab pe armă
 +  * Observați dacă mâna virtuală se conformază pose-ului creat (face snap) precum și dacă aveți liberate de mișcare pentru degetul arătător
 +
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_hand_pose_custom_3.gif?​500 |}}
  
 === Detecție eveniment grab / release armă === === Detecție eveniment grab / release armă ===
Line 315: Line 400:
 </​code>​ </​code>​
  
-Pentru a accesa **interactorul** care a declanșat **interacțiunea** și în esență obiectul tip ''​IHand''​ aferent, puteți interoga structura ''​SelectingInteractors''​, care descrie intractorii care interacționează în mod curent cu interactibilul (arma) astfel:+Pentru a accesa **interactorul** care a declanșat **interacțiunea** și în esență obiectul tip ''​IHand''​ aferent, puteți interoga structura ''​SelectingInteractors'' ​- aceasta ​descrie intractorii care interacționează în mod curent cu interactibilul (arma) astfel:
  
 <code c#> <code c#>
Line 359: Line 444:
 Afișați în consolă valoarea pe care o obțineți. În continuare va trebui să setați valorile min și max (din inspector) pentru ''​usableFingerCurlRange''​ folosind **valoarea afișată în consolă**: Afișați în consolă valoarea pe care o obțineți. În continuare va trebui să setați valorile min și max (din inspector) pentru ''​usableFingerCurlRange''​ folosind **valoarea afișată în consolă**:
   * Rulați scena, luați arma în mână   * Rulați scena, luați arma în mână
-  * Îndoiți degetul arătător suficient cât **doar să atingă** trăgaciul armei - notați valoarea de curl din consolă - aceasta va fi valoarea de **minim** pentru slider +  * Îndoiți degetul arătător suficient cât **doar să atingă** trăgaciul armei - notați valoarea de curl din consolă - aceasta va fi valoarea de **maxim** pentru slider 
-  * Îndoiți (aproape) complet degetul arătător, până în momentul în care pose-ul degetului nu se mai schimbă ​ - notați valoarea de curl din consolă - aceasta va fi valoarea de **maxim** pentru slider ​+  * Îndoiți (aproape) complet degetul arătător, până în momentul în care pose-ul degetului nu se mai schimbă ​ - notați valoarea de curl din consolă - aceasta va fi valoarea de **minim** pentru slider ​
  
 **Normalizați valoarea curl-ului** între valorile de minim și maxim obținute. De exemplu, dacă min/max slider sunt [200;250], remapați în range-ul [0;1]. În script-ul ''​Utils''​ aveți metoda ajutătoare ''​Remap''​. **Normalizați valoarea curl-ului** între valorile de minim și maxim obținute. De exemplu, dacă min/max slider sunt [200;250], remapați în range-ul [0;1]. În script-ul ''​Utils''​ aveți metoda ajutătoare ''​Remap''​.
Line 366: Line 451:
 Pentru a roti trăgaciul armei, apelați metoda ''​SetCurl''​ de pe script-ul **GunTriggerCurlController**. Pentru a roti trăgaciul armei, apelați metoda ''​SetCurl''​ de pe script-ul **GunTriggerCurlController**.
  
-Restul de script se ocupă de detecția ​evenumentului ​de tragere pe baza unui prag, anume ''​triggerThreshold''​. Logica deja dată apelează evenimentele de trăgaci apăsat (''​OnTriggerPressed''​) sau trăgaci lăsat liber (''​OnTriggerReleased''​).+Restul de script se ocupă de detecția ​evenimentului ​de tragere pe baza unui prag, anume ''​triggerThreshold''​. Logica deja dată apelează evenimentele de trăgaci apăsat (''​OnTriggerPressed''​) sau trăgaci lăsat liber (''​OnTriggerReleased''​).
  
 <note tip>În mod opțional puteți varia valoarea threshold-ului din inspector.</​note>​ <note tip>În mod opțional puteți varia valoarea threshold-ului din inspector.</​note>​
Line 398: Line 483:
 </​code>​ </​code>​
  
-Testați dacă ''​hitInfo.collider''​ are atașat un script de tip **Bottle** - dacă testul trece, ​apelai ​metoda ''​Shatter''​ de pe ''​Bottle''​.+Testați dacă ''​hitInfo.collider''​ are atașat un script de tip **Bottle** - dacă testul trece, ​apelați ​metoda ''​Shatter''​ de pe ''​Bottle''​.
  
 +=== Resetare sticle ===
  
-==== Tasks ====+Pentru a reseta sticlele de pe cea de-a doua masă din scenă, ne vom folosi de un **intractibil de tip Poke** - pe scurt, această funcționează ca un buton virtal și primește input de la **interactorul** de tip **HandPokeInteractor**.
  
-  - Urmăriți pașii desciși ​în laborator pentru a face **setup** SDK-ului **Meta XR**: Meta Quest App, Quest Link, Meta XR Unity package +Îl aveți deja definit ​în scenă.
-  - Importați și testați în modul **Quest Link** scenele sample +
-  - Realizați și testați un **build pe headset** al uneia dintre aceste scene sample +
-  +
-TODO+
  
-</hidden>+{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_poke_interactor.png?​300 |}} 
 + 
 +<note tip> 
 +Rețineți, aceste componente, precum acest interactibil de tip Poke, se pot adăuga în scenele voastre folosind meniul Building Blocks! 
 +</note> 
 + 
 +Legarea se poate realiza și în cod, dar pentru acest task, folosiți-vă de evenimentele expuse în inspector de pe script-ul ''​InteractableUnityEventWrapper''​ atașat obiectului **BottleReset_PokeInteractable**. Evenimentul de interes este ''​Select''​. 
 + 
 +Legați la acesta metoda ''​SpawnBottles''​ din script-ul ''​BottlesManager''​ - îl găsiți atașat de obiectul **BottlesTable** în scenă. 
 + 
 +=== Demo implementare task-uri === 
 + 
 +{{ :​irva:​laboratoarevr:​irva_2025_vr_l4_final.gif?​450 |}} 
 + 
 +==== Tasks ====
  
 +  - Urmăriți pașii descriși în laborator pentru a face setup SDK-ului Meta XR
 +  - Importați și testați în modul Quest Link scenele sample
 +  - Realizați și testați un build pe headset al uneia dintre aceste scene sample
 +  - Creați un nou pose custom pentru a ține arma în mână
 +    - Folosiți utilitarul Hand Grab Pose Recorder
 +    - Ajustați pose-ul după înregistrarea acestuia (poziția încheieturilor degetelor)
 +    - Aplicați regulile pentru grabbing și pose de pe ''​HandGrabInteractable''​ și ''​HandGrabPose''​
 +  - Completați script-ul ''​GunHandGrabController''​ pentru a detecta momentul în care arma este grabbed
 +    - Nu uitați să asignați întâi în inspectorul acestui script componentele necesare de pe Interaction Rig!
 +  - Completați script-ul ''​GunFingerCurlController''​ pentru a citi și aplica inputul corespuzător valorii de curl a degetului arătător
 +  - Completați script-ul ''​GunRaycastController''​ pentru a realiza raycast-ul în urma evenimentului de tragere și adăugați logica de spargere a sticlelor în cazul în care raza se intersectează cu un obiect de tip ''​Bottle''​
 +  - Legați poke interactable-ul "Reset Bottles"​ de script-ul ''​BottlesManager''​ pentru a reseta sticlele
 +  - [✨Bonus✨] Creați un nou poke interactor
 +    * Atașat de armă (de ex. în partea stângă / lângă grip)
 +    * Prin apăsarea acestuia se va face toggle între modul de tragere semi-automatic și automat al armei
 +    * La apăsare să schimbați textul (opțional și culoarea) interactorului astfel încât acesta să indice modul curent de tragere al armei
 +    * Extindeți logica ''​GunFireController''​ pentru logica de tragere tip automat (sau creați-vă propriile script-uri, după plac/​necesitate)
irva/laboratoarevr/04.1762733084.txt.gz · Last modified: 2025/11/10 02:04 by andrei.lapusteanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0