Virtual Reality-spel och gör din kropp en Controller! (Unity + Visual Studio + Kinect + Oculus) (7 / 11 steg)
Steg 7: Kinect Scripting
Skapa en ny mapp inuti mappen skript som heter KinectScripts. Nu i mappen skapa två nya skript. en som kallas BodyManger och den andra kallas BodyView.
BILD 1 OVAN
BodyManager
Första vi behöver BodyManager - detta objekt kommer att Mange Kinect sensor anslutningen och läsa i alla organ data kommer från Kinect.
Importera Kinect bibliotek med:
använder Windows.Kinect;
Då vi måste vissa fält för chefen att lagra och data och få sensordata.
privat KinectSensor _Sensor;
privat BodyFrameReader _Reader;
privat organ [] _Data = null;
offentliga organ [] GetData()
{
återvända _Data;
}
Okej så nu vill i metoden Start vi upprätta en anslutning för Kinect.
void Start()
{
_Sensor = KinectSensor.GetDefault();
om (_Sensor! = null)
{
_Reader = _Sensor.BodyFrameSource.OpenReader();
om (! _Sensor.IsOpen)
{
_Sensor.Open();
}
}
}
Nu när anslutningen är öppna och läsa i data behöver vi lagra det i matrisen kropp. Vi kommer att göra detta varje bildruta av spelet, därför måste vi redigera metoden Update().
Vi kontrollera först om _Reader har fastställts och anslutningen har slutförts. Om den har vi kommer att ta den sista bildrutan, läsaren läser i och om det inte är null, vi kan då kontrollera om data är det.
void Update()
{
om (_Reader! = null)
{
var ram = _Reader.AcquireLatestFrame();
om (ram =! = null)
{
IF(_Data == null)
{
Skriv koden här
}
}
}
}
Nu måste vi få kroppen data från Senor. För att göra detta kommer vi att skapa en ny kropp matris med data från Sensor.BodyFrameSource.BodyCount.
I slutet av metoden bör se ut så här:
void Update()
{
om (_Reader! = null)
{
var ram = _Reader.AcquireLatestFrame();
om (frame! = null)
{
om (_Data == null)
{
_Data = ny Body[_Sensor.BodyFrameSource.BodyCount];
}
}
}
}
Behöver vi att uppdatera strömmen av data från läsaren. Genom att lägga till följande kod för att manipulera bildrutan.
void Update()
{
om (_Reader! = null)
{
var ram = _Reader.AcquireLatestFrame();
om (frame! = null)
{
om (_Data == null)
{
_Data = ny Body[_Sensor.BodyFrameSource.BodyCount];
}
ram. GetAndRefreshBodyData(_Data);
ram. Dispose();
ram = null;
}
}
}
Den sista metoden i klassen kroppen Manager är OnApplicationQuit(), som gör sig läsaren, och stänger den Sensor strömmen, ställer det till null.
void OnApplicationQuit()
{
om (_Reader! = null)
{
_Reader.Dispose();
_Reader = null;
}
om (_Sensor! = null)
{
om (_Sensor.IsOpen)
{
_Sensor.Close();
}
_Sensor = null;
}
}
Kropp Visa
Nästa skriptet att skriva är en Rita benstommen. Vi kommer inte nödvändigtvis behöver se skelettet för spelet, men jag ska visa dig hur du visar skelett kroppsspårning. Vi behöver också skelett data att spåra händerna, vars stat kommer att diktera controller-befäl.
För denna MonoBehavoir klass behöver vi, ett material att dra benet i Unity scenen. En gameobject att lagra BodyManger, för att styra strömmen av Kinect.
offentligt Material finfördelas;
offentliga GameObject BodyManager;
Vi behöver också ett BodyManager-objekt och en ordlista att lagra organ spåras.
privat ordlista _Bodies = ny Dictionary();
privat BodyManager _BodyManager;
Sedan behöver vi kartlägga alla ben av två lederna som de kommer att anslutas till.
privat ordlista _BoneMap = ny Dictionary()
{
{Kinect.JointType.FootLeft, Kinect.JointType.AnkleLeft},
{Kinect.JointType.AnkleLeft, Kinect.JointType.KneeLeft},
{Kinect.JointType.KneeLeft, Kinect.JointType.HipLeft},
{Kinect.JointType.HipLeft, Kinect.JointType.SpineBase},
{Kinect.JointType.FootRight, Kinect.JointType.AnkleRight},
{Kinect.JointType.AnkleRight, Kinect.JointType.KneeRight},
{Kinect.JointType.KneeRight, Kinect.JointType.HipRight},
{Kinect.JointType.HipRight, Kinect.JointType.SpineBase},
{Kinect.JointType.HandTipLeft, Kinect.JointType.HandLeft}, //Need detta för HandSates
{Kinect.JointType.ThumbLeft, Kinect.JointType.HandLeft},
{Kinect.JointType.HandLeft, Kinect.JointType.WristLeft},
{Kinect.JointType.WristLeft, Kinect.JointType.ElbowLeft},
{Kinect.JointType.ElbowLeft, Kinect.JointType.ShoulderLeft},
{Kinect.JointType.ShoulderLeft, Kinect.JointType.SpineShoulder},
{Kinect.JointType.HandTipRight, Kinect.JointType.HandRight}, //Needthis för Hand
{Kinect.JointType.ThumbRight, Kinect.JointType.HandRight},
{Kinect.JointType.HandRight, Kinect.JointType.WristRight},
{Kinect.JointType.WristRight, Kinect.JointType.ElbowRight},
{Kinect.JointType.ElbowRight, Kinect.JointType.ShoulderRight},
{Kinect.JointType.ShoulderRight, Kinect.JointType.SpineShoulder},
{Kinect.JointType.SpineBase, Kinect.JointType.SpineMid},
{Kinect.JointType.SpineMid, Kinect.JointType.SpineShoulder},
{Kinect.JointType.SpineShoulder, Kinect.JointType.Neck},
{Kinect.JointType.Neck, Kinect.JointType.Head},
};
BodyView Update()
Nu i enighet Update() metoden måste vi kontrollera om kroppen Manager inte är null och att den har data.
void Update()
{
int state = 0;
om (BodyManager == null)
{
hemkomst.
}
_BodyManager = BodyManager.GetComponent();
om (_BodyManager == null)
{
returnera
}
Kinect.Body [] data = _BodyManager.GetData();
om (data == null) {
hemkomst.
}
}
Nästa, men fortfarande i metoden Update(), vi måste få mängden organ i förteckningen över organ som spårade. Ta sedan bort okänd organ.
Lista trackedIds = ny lista ();
foreach (var kroppen i data)
{
om (kroppen == null)
{
fortsätta;
}
om (kropp. IsTracked)
{
trackedIds.Add (organ. TrackingId);
}
}
Lista knownIds = ny lista (_Bodies.Keys);
Först ta bort ospårad organ
foreach (ulong trackingId i knownIds)
{
om (! trackedIds.Contains(trackingId))
{
Destroy(_Bodies[trackingId]);
_Bodies.Remove(trackingId);
}
}
Nu när vi har nycklarna för att spåra organ måste vi skapa en body-objekt med det tracking ID-nyckel. Vi behöver skriva två fler metoder. En CreateBodyObject() metod som kommer att ta en ulong id och en RefreashBodyObject() metod som kommer att ta ett Kinect.Body-objekt och en GameObject för kroppen. Vi kommer att använda dessa metoder när vi går igenom data, och hitta om organ inuti spåras eller inte. Om det spåras men inte har en TrackingId, måste vi skapa en kropp med det TrackingID. Om det spåras och har en TrackingId då behöver vi bara uppdatera dras kroppen.
foreach (var kroppen i data)
{
om (kroppen == null)
{
fortsätta;
}
om (kropp. IsTracked)
{
om (! _Bodies.ContainsKey (organ. TrackingId))
{
_Bodies [kropp. TrackingId] = CreateBodyObject (organ. TrackingId);
}
RefreshBodyObject (kropp, _Bodies [kropp. TrackingId]);
}
}
}
CreateBodyObject()
CreateBodyObject tar ett ID och returnerar en kropp gameobject. Så måste vi först skapa en gameobject som kommer att lagra lämpliga uppgifter Hämtad; då behöver vi en for-loop gå igenom varje led Rita kroppen.
privat GameObject CreateBodyObject(ulong id)
{
GameObject kropp = nya GameObject ("kroppen:" + id);
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++) {
}
returnera kropp;
}
Varje led i kroppen vi skapa en kub och lägga till en lineRenderer till att cube. Kuben kommer att dras på varje gemensamt medan linje återgivningstillägget kommer att dras för att ansluta lederna.
privat GameObject CreateBodyObject(ulong id) {
GameObject kropp = nya GameObject ("kroppen:" + id);
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++) {
GameObject jointObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
LineRenderer lr = jointObj.AddComponent();
LR. SetVertexCount(2);
LR.material = finfördelas;
LR. SetWidth (0.05f, 0.05f);
jointObj.transform.localScale = ny Vector3 (0.3f, 0.3f, 0.3f);
jointObj.name = jt. ToString();
jointObj.transform.parent = body.transform;
}
returnera kropp;
}
RefreashBodyObject()
Nu att skriva den ResfreshBodyObject metoden. I denna metod måste vi gå igenom varje gemensam typ möjligt precis som vi gjorde i metoden CreateBodyObject. Men denna gång vi passerar i det aktuella organet, samt den lämpliga spårningsnummer så vi inte drar benen för fel person.
privata void RefreshBodyObject (Kinect.Body kropp, GameObject bodyObject)
{
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++)
{
}
}
Inuti detta for-loop behöver vi få nyckelvärde parar vi gjort innan i ben slingan för alla fogar.
privata void RefreshBodyObject (Kinect.Body kropp, GameObject bodyObject)
{
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++)
{
Kinect.Joint sourceJoint = kropp. Lederna [jt];
Kinect.Joint? targetJoint = null;
IF(_BoneMap.ContainsKey(JT))
{
targetJoint = kropp. Lederna [_BoneMap [jt]];
}
}
}
Vi behöver också uppdatera skelett ställning så det är i den exakta platsen på skärmen. För att göra detta måste vi skriva en metod för att få Vetcor3 från sourceJoint.
privata statisk Vector3 GetVector3FromJoint(Kinect.Joint joint)
{
returnera nya Vector3(joint. Position.X * 10, gemensamma. Position.Y * 10, gemensamma. Position.Z * 10);
}
Omfattningen av 10 är att utvidga skelettet, som gör det lättare att arbeta med. Nu har vi möjlighet att korrigera gameObjects ställning.
privata void RefreshBodyObject (Kinect.Body kropp, GameObject bodyObject)
{
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++)
{
Kinect.Joint sourceJoint = kropp. Lederna [jt];
Kinect.Joint? targetJoint = null;
IF(_BoneMap.ContainsKey(JT)) {
targetJoint = kropp. Lederna [_BoneMap [jt]];
}
Omvandla jointObj = bodyObject.transform.FindChild (jt. ToString());
jointObj.localPosition = GetVector3FromJoint(sourceJoint);
}
}
Nästa steg den för slinga är att få linerenderer från bodyObject, som var kuben vi skapar för varje gemensamt. Vi måste se om målet gemensamma har ett värde. Om den gör det kan vi då dra en linje från den ursprungliga gemensamt till målet.
LineRenderer lr = jointObj.GetComponent ();
IF(targetJoint.HasValue)
{
LR. SetPosition (0, jointObj.localPosition);
LR. SetPosition (1, GetVector3FromJoint(targetJoint.Value));
}
annat
{
LR.Enabled = false;
}
Stor! Så vi är nästan klar med ritning skelettet. Det finns lite mer information som kommer att vara till hjälp att SDK ger dig, som är att spåra status. Det finns tre lägen att välja mellan, spårade, Inferred eller NotTracked. Vi kan ha linje återgivningstillägget visar oss statligt av spårning genom att ändra sin färg. För att göra detta behöver vi en metod som returnerar en färg baserat på det aktuella läget.
privata statisk färg GetColorForState(Kinect.TrackingState state)
{
Växla (staten) {
fall Kinect.TrackingState.Tracked:
återvända Color.green;
fall Kinect.TrackingState.Inferred:
återvända Color.red;
standard:
återvända Color.black;
}
}
Nu vi lägga till ytterligare en rad till den for-loop av RefreachBodyObject metoden och vi är klar.
privata void RefreshBodyObject (Kinect.Body kropp, GameObject bodyObject)
{
för (Kinect.JointType jt = Kinect.JointType.SpineBase, jt < = Kinect.JointType.ThumbRight, jt ++)
{
Kinect.Joint sourceJoint = kropp. Lederna [jt];
Kinect.Joint? targetJoint = null;
om (_BoneMap.ContainsKey(jt))
{
targetJoint = kropp. Lederna [_BoneMap [jt]];
}
Omvandla jointObj = bodyObject.transform.FindChild (jt. ToString());
jointObj.localPosition = GetVector3FromJoint(sourceJoint);
LineRenderer lr = jointObj.GetComponent();
om (targetJoint.HasValue)
{
LR. SetPosition (0, jointObj.localPosition);
LR. SetPosition (1, GetVector3FromJoint(targetJoint.Value));
LR. SetColors(GetColorForState(sourceJoint.TrackingState), GetColorForState(targetJoint.Value.TrackingState));
}
annat
{
LR.Enabled = false;
}
}
}
Och det är det för att rita skelettet!