Stap 7: Kinect Scripting
Maak een nieuwe map in uw Scripts map Called KinectScripts. Nu in die map maken twee nieuwe scripts; een BodyManger genoemd en de andere BodyView.
AFBEELDING 1 HIERBOVEN
BodyManager
Eerst wij moeten BodyManager - dit object zal Mange de Kinect sensor verbinding en lees in alle lichaam gegevens afkomstig van de Kinect.
De bibliotheek van de Kinect met importeren:
using Windows.Kinect;
Dan wij sommige velden moet voor de manager om op te slaan en de gegevens en sensorgegevens ophalen.
privé KinectSensor _Sensor;
privé BodyFrameReader _Reader;
privé lichaam [] _Data = null;
openbaar lichaam [] GetData()
{
retourneren _Data;
}
Oke dus nu willen in de methode Start we de verbinding voor de Kinect.
VOID Start()
{
_Sensor = KinectSensor.GetDefault();
Als (_Sensor! = null)
{
_Reader = _Sensor.BodyFrameSource.OpenReader();
Als (! _Sensor.IsOpen)
{
_Sensor.Open();
}
}
}
Nu dat de verbinding geopend is en in de gegevens lezen we moeten te slaan in de array van het lichaam. Wij doen dit elke frame van het spel, daarom moeten we de methode Update() bewerken.
Eerst controleren we om te zien of de _Reader is vastgesteld en de verbinding is voltooid. Als er zullen we het laatste frame en dat de lezer lezen if it's not null, kunnen we dan controleren om te zien of de gegevens er.
void Update() { if (_Reader != null) { var frame = _Reader.AcquireLatestFrame(); if(frame = != null) { if(_Data == null) { //Write Code here } } } }
Nu moeten we het lichaam gegevens ophalen uit de Senor. Om dit te doen die zullen we moeten een nieuwe instantie array maken met gegevens uit de Sensor.BodyFrameSource.BodyCount.
Aan het eind moet de methode als volgt uitzien:
VOID Update()
{
Als (_Reader! = null)
{
var frame = _Reader.AcquireLatestFrame();
Als (frame! = null)
{
Als (_Data == null)
{
_Data = new Body[_Sensor.BodyFrameSource.BodyCount];
}
}
}
}
Dan moeten we voor het vernieuwen van de stroom van gegevens van de lezer. Door het toevoegen van de volgende code om te manipuleren van het frame.
VOID Update()
{
Als (_Reader! = null)
{
var frame = _Reader.AcquireLatestFrame();
Als (frame! = null)
{
Als (_Data == null)
{
_Data = nieuwe Body[_Sensor.BodyFrameSource.BodyCount];
}
frame. GetAndRefreshBodyData(_Data);
frame. Dispose();
frame = null;
}
}
}
De laatste methode in de klasse lichaam Manager is OnApplicationQuit(), die beschikt over de lezer, en de Sensor stream sluit, wordt het ingesteld op null.
VOID OnApplicationQuit()
{
Als (_Reader! = null)
{
_Reader.Dispose();
_Reader = null;
}
Als (_Sensor! = null)
{
Als (_Sensor.IsOpen)
{
_Sensor.Close();
}
_Sensor = null;
}
}
Lichaam weergave
Het volgende Script te schrijven behoort tot het opstellen van het skelet. Wij zal niet per se hoeven te zien van het skelet voor het spel, echter, ik zal je laten zien hoe om te laten zien van skeletale lichaam bijhouden. We moeten ook de skelet gegevens voor het bijhouden van de handen, wier land controller opdrachten dicteren zal.
Voor deze klasse van MonoBehavoir zullen we, een materiaal te trekken van het bot in de scène van de eenheid. Een gameobject voor het opslaan van de BodyManger, om te bepalen van de stroom van de Kinect.
public Material BoneMaterial; public GameObject BodyManager;
We moeten ook een BodyManager-object en een woordenboek voor het opslaan van de organen worden bijgehouden.
private Dictionary _Bodies = new Dictionary();private BodyManager _BodyManager;
Daarna nodig hebben wij om kaart te brengen door de twee gewrichten die zij zal worden aangesloten op alle beenderen.
private Dictionary _BoneMap = new 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 this for 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 for Hand State{ 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 in de eenheid Update() methode moeten we controleren om te zien als de Manager van het lichaam niet nul is en dat er gegevens.
void Update(){ int state = 0; if (BodyManager == null) { return; } _BodyManager = BodyManager.GetComponent(); if (_BodyManager == null) { return } Kinect.Body[] data = _BodyManager.GetData(); if (data == null){ return; } }
Vervolgens, terwijl nog steeds in de Update() methode moeten we om het bedrag van de organen in de lijst van bijgehouden instanties. Verwijder onbekende organen.
Lijst van trackedIds = nieuwe lijst ();
foreach (var lichaam in gegevens)
{
Als (lichaam == null)
{
blijven;
}
Als (lichaam. IsTracked)
{
trackedIds.Add (body. TrackingId);
}
}
Lijst van knownIds = nieuwe lijst (_Bodies.Keys);
Eerst verwijderen ongevolgde organen
foreach (ulong trackingId in knownIds)
{
Als (! trackedIds.Contains(trackingId))
{
Destroy(_Bodies[trackingId]);
_Bodies.Remove(trackingId);
}
}
Nu hebben wij de sleutels voor het bijhouden van de instanties moeten we een body-object te maken met die tracking ID sleutel. We moeten meer op twee manieren schrijven. Een CreateBodyObject() methode die nemen zal een ulong-id en een RefreashBodyObject() methode die een Kinect.Body-object en een GameObject voor het lichaam nemen zal. Nadat we gaan door middel van de gegevens, en vinden als organen binnen worden bijgehouden of niet, zullen wij deze methoden gebruiken. Als het wordt bijgehouden, maar niet een TrackingId hoeft, dan moet wij een instantie te maken met dat TrackingID. Als het wordt bijgehouden en een TrackingId heeft moet we gewoon vernieuwen de getekende lichaam.
foreach (var lichaam in gegevens)
{
Als (lichaam == null)
{
blijven;
}
Als (lichaam. IsTracked)
{
Als (! _Bodies.ContainsKey (lichaam. TrackingId))
{
_Bodies [body. TrackingId] = CreateBodyObject (lichaam. TrackingId);
}
RefreshBodyObject (body, _Bodies [body. TrackingId]);
}
}
}
CreateBodyObject()
De CreateBodyObject heeft van een ID en retourneert een gameobject lichaam. We moeten dus eerst maken van een gameobject dat de juiste gegevens ontvangen slaat; dan we moeten een for-lus te doorlopen elke gewricht te trekken van het lichaam.
private GameObject CreateBodyObject(ulong id){ GameObject body = new GameObject("Body:" + id); for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++){ } return body;}
Voor elke gewricht in het lichaam wij een kubus maken en een lineRenderer toevoegen aan deze kubus. De kubus worden getrokken bij elke joint terwijl de renderer lijn worden getrokken voor de verbinding van de gewrichten.
private GameObject CreateBodyObject(ulong id) { GameObject body = new GameObject("Body:" + id); for (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 = BoneMaterial; lr.SetWidth(0.05f, 0.05f); jointObj.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f); jointObj.name = jt.ToString(); jointObj.transform.parent = body.transform; } return body;}
RefreashBodyObject()
Nu aan het schrijven van de ResfreshBodyObject-methode. Bij deze methode moeten we gaan via elk gezamenlijke type mogelijk net als wij in de CreateBodyObject-methode. Maar deze keer we in de huidige instantie, alsmede de passende passeren zijn trackingnummer zodat we niet de botten te voor de verkeerde persoon trekken.
private void RefreshBodyObject (Kinect.Body lichaam, GameObject bodyObject)
{
voor (Kinect.JointType jt = Kinect.JointType.SpineBase; jt < = Kinect.JointType.ThumbRight; jt ++)
{
}
}
We moeten krijgen van de belangrijke value-paren die we voor in de lus van de bot voor elke gezamenlijke gemaakt binnen dit for-lus.
private void RefreshBodyObject (Kinect.Body lichaam, GameObject bodyObject)
{
voor (Kinect.JointType jt = Kinect.JointType.SpineBase; jt < = Kinect.JointType.ThumbRight; jt ++)
{
Kinect.Joint-sourceJoint = lichaam. Gewrichten [jt];
Kinect.Joint? targetJoint = null;
if(_BoneMap.ContainsKey(JT))
{
targetJoint = lichaam. Gewrichten [_BoneMap [jt]];
}
}
}
We moeten ook bijwerken van de skeletten positie, dus het is in de nauwkeurige plaats op het scherm. Om dit te doen we schrijven een methode moeten om de Vetcor3 van de sourceJoint.
private static Vector3 GetVector3FromJoint(Kinect.Joint joint){ return new Vector3(joint.Position.X * 10, joint.Position.Y * 10, joint.Position.Z * 10);}
De schaal van 10 is uit te breiden van het skelet, waardoor het makkelijker om te werken met. Nu hebben we positie om te corrigeren voor de positie van de gameObjects.
private void RefreshBodyObject(Kinect.Body body, GameObject bodyObject){ for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++) { Kinect.Joint sourceJoint = body.Joints[jt]; Kinect.Joint? targetJoint = null; if(_BoneMap.ContainsKey(jt)){ targetJoint = body.Joints[_BoneMap[jt]]; } Transform jointObj = bodyObject.transform.FindChild(jt.ToString()); jointObj.localPosition = GetVector3FromJoint(sourceJoint); }}
Volgende stap in de voor lus is om de linerenderer van de bodyObject, die de kubus we voor elke gezamenlijke maken was. Vervolgens willen we zien als doel gezamenlijke een waarde heeft. Als dat zo is kunnen we dan trekken een lijn afkomstig van de oorspronkelijke pakking naar het doel.
LineRenderer lr = jointObj.GetComponent ();
if(targetJoint.HasValue)
{
LR. SetPosition (0, jointObj.localPosition);
LR. SetPosition (1, GetVector3FromJoint(targetJoint.Value));
}
anders
{
LR.enabled = false;
}
Geweldig! Dus we zijn bijna klaar met het opstellen van het skelet. Er is een beetje meer informatie die nuttig zijn dat de SDK geeft u, die is controlestatus. Er zijn drie staten om uit te kiezen, bijgehouden, Inferred of NotTracked. Kunnen we de lijn renderer tonen ons de staat van het opsporen door het veranderen van de kleur. Om dit te doen moeten we een methode die een kleur op basis van de huidige status terugkeren zal.
private static Color GetColorForState(Kinect.TrackingState state){ switch (state){ case Kinect.TrackingState.Tracked: return Color.green; case Kinect.TrackingState.Inferred: return Color.red; default: return Color.black; }}
Nu voegen we nog een regel aan de for-lus van de RefreachBodyObject methode en we zijn klaar.
private void RefreshBodyObject(Kinect.Body body, GameObject bodyObject){ for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++){ Kinect.Joint sourceJoint = body.Joints[jt]; Kinect.Joint? targetJoint = null; if (_BoneMap.ContainsKey(jt)) { targetJoint = body.Joints[_BoneMap[jt]]; } Transform jointObj = bodyObject.transform.FindChild(jt.ToString()); jointObj.localPosition = GetVector3FromJoint(sourceJoint); LineRenderer lr = jointObj.GetComponent(); if (targetJoint.HasValue) { lr.SetPosition(0, jointObj.localPosition); lr.SetPosition(1, GetVector3FromJoint(targetJoint.Value)); lr.SetColors(GetColorForState(sourceJoint.TrackingState), GetColorForState(targetJoint.Value.TrackingState)); } else { lr.enabled = false; }}}
En thats it voor het tekenen van het skelet!