This shows you the differences between two versions of the page.
|
irva:laboratoarevr:04 [2025/11/10 02:40] 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 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 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 400: | Line 485: | ||
| Testați dacă ''hitInfo.collider'' are atașat un script de tip **Bottle** - dacă testul trece, apelați 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) | ||