前回の続きを書いていきます!
今回はUnityちゃんを動かしていこうと思います
↓参考にした記事です↓
http://www.buildinsider.net/small/bookkinectv2/0703
#もくじ
1.Unityちゃんインポート
2.kinect側の準備
3.コードを最低限の部分だけ書く
Assets>UnityChan>Modelsの中にモデルが入っているのでHierarchyに置いちゃいましょう
#2.kinect側の準備
前回の記事にあったKinectViewフォルダのMainSceneを開いて、BodyManagerをプレファブ化しちゃいます
このプレファブ化したBodyManagerを先ほどUnityちゃんを出したシーンのHierarchyに入れます
これでKinect側の準備はOKです!
せっかくなのでBodyManagerにアタッチされているBodySourceManagerの中身をざっくり紹介します
using UnityEngine;
using System.Collections;
using Windows.Kinect;
public class BodySourceManager : MonoBehaviour
{
private KinectSensor _Sensor;
private BodyFrameReader _Reader;
private Body[] _Data = null;//認識した体の情報がはいります(最大6人)
public Body[] GetData()
{
return _Data;
}
void Start () //Kinectを開く系の処理をしています
{
_Sensor = KinectSensor.GetDefault();
if (_Sensor != null)
{
_Reader = _Sensor.BodyFrameSource.OpenReader();
if (!_Sensor.IsOpen)
{
_Sensor.Open();
}
}
}
void Update ()
{
if (_Reader != null)
{
var frame = _Reader.AcquireLatestFrame();
if (frame != null)
{
if (_Data == null)//取得した体の情報を入れている
{
_Data = new Body[_Sensor.BodyFrameSource.BodyCount];
}
frame.GetAndRefreshBodyData(_Data);
frame.Dispose();
frame = null;
}
}
}
void OnApplicationQuit()//アプリ終了時に呼ばれる関数
{
if (_Reader != null)//BodyFrameReaderを破棄
{
_Reader.Dispose();
_Reader = null;
}
if (_Sensor != null)//キネクトを停止
{
if (_Sensor.IsOpen)
{
_Sensor.Close();
}
_Sensor = null;
}
}
}
今回大切なのが、Bodyのデータです
これを使えば結構色々なことできます
#3.コードを最低限の部分だけ書く
今回は記事を参考にしますが、分かりやすくするために本当に最低限の部分だけ書いていきます
流れとしては
・最初に追尾した人のBodyデータを取得する
・そのBodyデータに基づいてUnityちゃんを動かす
てな感じでいってみようと思います
まず、BodySourceManagerスクリプトに次のコードを追加します
キネクトを傾かせて置いたときの対策です(記事参照)
public class BodySourceManager : MonoBehaviour
{
//~中略~
public Windows.Kinect.Vector4 FloorClipPlane
{
get;
private set;
}
void Update ()
{
if (_Reader != null)
{
var frame = _Reader.AcquireLatestFrame();
if (frame != null)
{
if (_Data == null)
{
_Data = new Body[_Sensor.BodyFrameSource.BodyCount];
}
frame.GetAndRefreshBodyData(_Data);
// FloorClipPlaneを取得する
FloorClipPlane = frame.FloorClipPlane;
frame.Dispose();
frame = null;
}
}
}
}
お次にVectorExtensionsスクリプトを作成し、Vector4の拡張クラスとして定義します(記事参照)
using UnityEngine;
public static class VectorExtensions
{
public static Quaternion ToQuaternion( this Windows.Kinect.Vector4 vactor, Quaternion comp )
{
return Quaternion.Inverse( comp ) *
new Quaternion( -vactor.X, -vactor.Y, vactor.Z, vactor.W );
}
public static Windows.Kinect.Vector4 ToMirror( this Windows.Kinect.Vector4 vector )
{
return new Windows.Kinect.Vector4()
{
X = vector.X,
Y = -vector.Y,
Z = -vector.Z,
W = vector.W
};
}
}
KinectAvatarスクリプトを作ります
今回はミラーなどを省きました!
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Windows.Kinect;
public class KinectAvatar : MonoBehaviour {
[SerializeField]
BodySourceManager bodySourceManager;
//自分の関節とUnityちゃんのボーンを入れるよう
[SerializeField] GameObject Ref;
[SerializeField] GameObject LeftUpLeg;
[SerializeField] GameObject LeftLeg;
[SerializeField] GameObject RightUpLeg;
[SerializeField] GameObject RightLeg;
[SerializeField] GameObject Spine1;
[SerializeField] GameObject LeftArm;
[SerializeField] GameObject LeftForeArm;
[SerializeField] GameObject LeftHand;
[SerializeField] GameObject RightArm;
[SerializeField] GameObject RightForeArm;
[SerializeField] GameObject RightHand;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//最初に追尾している人のBodyデータを取得する
Body body = bodySourceManager.GetData().FirstOrDefault(b => b.IsTracked);
// Kinectを斜めに置いてもまっすぐにするようにする
var floorPlane = bodySourceManager.FloorClipPlane;
Quaternion comp = Quaternion.FromToRotation(
new Vector3(-floorPlane.X, floorPlane.Y, floorPlane.Z), Vector3.up);
Quaternion SpineBase;
Quaternion SpineMid;
Quaternion SpineShoulder;
Quaternion ShoulderLeft;
Quaternion ShoulderRight;
Quaternion ElbowLeft;
Quaternion WristLeft;
Quaternion HandLeft;
Quaternion ElbowRight;
Quaternion WristRight;
Quaternion HandRight;
Quaternion KneeLeft;
Quaternion AnkleLeft;
Quaternion KneeRight;
Quaternion AnkleRight;
Quaternion q;
Quaternion comp2;
CameraSpacePoint pos;
// 関節の回転を取得する
if (body != null)
{
var joints = body.JointOrientations;
//Kinectの関節回転情報をUnityのクォータニオンに変換
SpineBase = joints[JointType.SpineBase].Orientation.ToQuaternion(comp);
SpineMid = joints[JointType.SpineMid].Orientation.ToQuaternion(comp);
SpineShoulder = joints[JointType.SpineShoulder].Orientation.ToQuaternion(comp);
ShoulderLeft = joints[JointType.ShoulderLeft].Orientation.ToQuaternion(comp);
ShoulderRight = joints[JointType.ShoulderRight].Orientation.ToQuaternion(comp);
ElbowLeft = joints[JointType.ElbowLeft].Orientation.ToQuaternion(comp);
WristLeft = joints[JointType.WristLeft].Orientation.ToQuaternion(comp);
HandLeft = joints[JointType.HandLeft].Orientation.ToQuaternion(comp);
ElbowRight = joints[JointType.ElbowRight].Orientation.ToQuaternion(comp);
WristRight = joints[JointType.WristRight].Orientation.ToQuaternion(comp);
HandRight = joints[JointType.HandRight].Orientation.ToQuaternion(comp);
KneeLeft = joints[JointType.KneeLeft].Orientation.ToQuaternion(comp);
AnkleLeft = joints[JointType.AnkleLeft].Orientation.ToQuaternion(comp);
KneeRight = joints[JointType.KneeRight].Orientation.ToQuaternion(comp);
AnkleRight = joints[JointType.AnkleRight].Orientation.ToQuaternion(comp);
// 関節の回転を計算する
q = transform.rotation;
transform.rotation = Quaternion.identity;
comp2 = Quaternion.AngleAxis(90, new Vector3(0, 1, 0)) *
Quaternion.AngleAxis(-90, new Vector3(0, 0, 1));
Spine1.transform.rotation = SpineMid * comp2;
RightArm.transform.rotation = ElbowRight * comp2;
RightForeArm.transform.rotation = WristRight * comp2;
RightHand.transform.rotation = HandRight * comp2;
LeftArm.transform.rotation = ElbowLeft * comp2;
LeftForeArm.transform.rotation = WristLeft * comp2;
LeftHand.transform.rotation = HandLeft * comp2;
RightUpLeg.transform.rotation = KneeRight * comp2;
RightLeg.transform.rotation = AnkleRight * comp2;
LeftUpLeg.transform.rotation = KneeLeft *
Quaternion.AngleAxis(-90, new Vector3(0, 0, 1));
LeftLeg.transform.rotation = AnkleLeft *
Quaternion.AngleAxis(-90, new Vector3(0, 0, 1));
// モデルの回転を設定する
transform.rotation = q;
// モデルの位置を移動する
pos = body.Joints[JointType.SpineMid].Position;
Ref.transform.position = new Vector3(-pos.X, pos.Y, -pos.Z);
}
}
}
それではこのKinectAvatarスクリプトをUnityちゃんにアタッチし、シリアライズの部分を入れていきます!
そして最後にBodySorceManagerの場所にBodySorceManagerオブジェクトを入れましょう
これで準備は完了のはず!!
カレンダーの時間ちょっとすぎてしまったんでまた更新します!!
では!