This is an old revision of the document!
ManoMotion este un SDK ce permite dezvoltarea de aplicații în AR, unde modalitatea de input este determinată de hand tracking.
SDK-ul este construit pe baza unor metode de computer vision și machine learning ce facilitează detecția mâinilor – este antrenat, de asemenea, să recunoască o serie de gesturi, de care vom vorbi în acest laborator.
Putem crea aplicații sau jocuri folosinf ARFoundation + ManoMotion care să nu necesite interacțiunea cu touchscreen-ul – modalitatea de input fiind dictată de către poziția mâinii detectate, precum și a gesturilor efectuate.
Un preview asupra aplicației la care veți lucra în acest laborator îl puteți viziona în următorul videoclip – versiunea prezentată este cea finală (cu task-urile rezolvate).
ManoMotion SDK (împreună cu ARFoundation) sunt deja incluse în laborator, iar setările aferente build-ului au fost realizate (s-ar putea sa trebuiască să schimbați doar target platform-ul).
De asemenea, în scena aferentă laboratorului acesta (L6-Scene), există deja un manager script care are deja setat license key-ul pentru ManoMotion.
Următorii pași nu sunt necesari în cadrul acestui laborator, dar ilustrează modalitatea de adăugare a package-ului ManoMotion în proiect, generarea și inserarea license key-ului (în framework este deja făcut setup-ul și se foloște un license key).
Un proiect ce folosește ManoMotion se utilizează de camera smartphone-ului ca input – SDK-ul procesează fluxul de frame-uri primite de la camera and does its magic (detecție mână & gesturi).
Ne putem folosi destul de ușor de informația oferită de SDK – acesta setează valorile unor structuri de date (enums) pe care le putem interoga per frame.
Informația oferită este de mai multe tipuri, împărțită pe o serie de clase:
Reprezintă clase “generale” de detecție, valori posibile:
ManoClass.NO_HAND ManoClass.GRAB_GESTURE ManoClass.POINTER_GESTURE ManoClass.PINCH_GESTURE
Acestea sunt gesture de tip trigger – De exemplu, momentul (sau frame-ul) în care s-a detectat un “grab”, adică SDK-ul a detectat gestul de tip închidere pumn. Alt exemplu este un gest de tip “release”, care este true în frame-ul în care s-a detectat gestul de deschidere a pumnului. Valori posibile:
ManoGestureTrigger.NO_GESTURE ManoGestureTrigger.CLICK ManoGestureTrigger.RELEASE_GESTURE ManoGestureTrigger.GRAB_GESTURE ManoGestureTrigger.PICK ManoGestureTrigger.DROP
Gesturi continue, anume cele care persistă pe mai multe frame-uri – gestul de tip “closed hand” este detectat în toate frame-urile în care este detectată o mână cu pumnul strâns. Valori posible:
ManoGestureContinuous.NO_GESTURE ManoGestureContinuous.HOLD_GESTURE ManoGestureContinuous.OPEN_HAND_GESTURE ManoGestureContinuous.OPEN_PINCH_GESTURE ManoGestureContinuous.CLOSED_HAND_GESTURE ManoGestureContinuous.POINTER_GESTURE
Specifică ce parte a mâinii este detectată – palma sau dosul palmei. Valori posibile:
HandSide.None HandSide.Backside HandSide.Palmside
// Detected hand information HandInfo handInfo = ManomotionManager.Instance.Hand_infos[0].hand_info; // Detected gesture information GestureInfo gestInfo = handInfo.gesture_info; ManoClass manoClass = gestInfo.mano_class; // Gesture class ManoGestureTrigger gestTrigger = gestInfo.mano_gesture_trigger; // Trigger gesture ManoGestureContinuous gestCont = gestInfo.mano_gesture_continuous; // Continuous gesture HandSide handSide = gestInfo.hand_side; // Hand side int gestureState = gestInfo.state; // Gesture state Vector3 palmPosNorm = handInfo.tracking_info.palm_center; // Norm. screen coords [0...1] /** To get screen coords in pixels, multiply 'palmPosNorm' x/y with Screen.width, Screen.height */
În principal, aceste informații înlocuiesc input-ul clasic, așadar am putea testa pe Update(), de exemplu:
void Update() { // Grab hand info from ManoMotion's SDK HandInfo handInfo = ManomotionManager.Instance.Hand_infos[0].hand_info; if(handInfo.gesture_info.mano_gesture_trigger == ManoGestureTrigger.GRAB_GESTURE) { // Do something only on the frame this is true } if(handInfo.gesture_info.mano_gesture_continuous == ManoGestureContinuous.OPEN_HAND_GESTURE) { // Do something every frame this is true } }
Proiectul are deja partea de AR configurată precum și baza unui joc (clonă simplified Fruit Ninja), la care va trebui să implementați câteva feature-uri.
Aplicația de laborator este configurată într-o serie de etape, care ajută la configurarea spațiului AR de joc. Acestea sunt:
Script-uri (se vor explica cele care sunt relevante):
1. Înainte de a lucra la joculețul propus, vă recomandăm mai întâi să testați scena demo oferită de către cei de la ManoMotion. Aceasta se găsește în Assets > ManoMotion ARFoundation > Scenes > ManoMotion SDK CE ARFoundation Features
În cazul în care activați toate feature-urile din scena demo, ar trebui sa obțineți o scenă similara cu cea prezentată mai jos:
2. În cazul în care nu au fost probleme, faceți switch la scena de laborator (L6_Scene) și realizați un build. Citiți cu atenție etapele de inițializare – pasul acesta este încheiat dacă instațiați scena de joc iar fructele încep să se spawneze.
3. Pentru a tăia fructele, vă este oferit un obiect care ar trebui să urmărească poziția mâinii (mai exact, acest obiect de tip cursor este numit “Spikeball_Cursor” și se găsește în prefab-ul “GameScene” din Assets > Prefabs > L6_ManoMotion). Implementarea va trebui realizată în script-ul CursorPositionController. Rezultat corect: Obiectul cursor urmărește poziția mâinii și poate tăia fructele instanțiate în scenă. Urmăriți todo-urile din script.
4. Va trebui să implementați diverse gesturi pentru a altera logica jocului. De exemplu, în frame-urile în care este detectat podul palmei, opriți spawning de fructe. Pentru detalii, urmăriți todo-urile din script-ul HandGestureController
5. Pentru fiecare frame în care se detectează gestul de tip continuu CLOSED_HAND_GESTURE, creșteți spawn rate-ul de 20 de ori. Pentru detalii, urmăriți todo-urile din script-ul HandGestureController
6. Când este detectat gestul de trigger de tip PICK, realizați o implementare prin care să “tăiați” (distrugeți) toate fructele instanțiate în acel moment în scena. Nu folosiți direct Destroy() pe ele, există o funcție deja implementată în controller-ul de fructe (use that!). Pentru detalii, urmăriți todo-urile din script-ul HandGestureController