【開発手法】Azure Kinectを使ったアプリ開発『どうぶつコマ』
どうも、インタラクションデザイナーのMIZUTANI KIRIN(@mizutanikirin)です!普段はKinectを中心にいろいろなセンサーを使った体験型ゲーム、インタラクションアプリを作っています。今回Azure Kinectを使ったアプリ「どうぶつコマ」の開発経緯やどうやってアプリを実現したのか?を紹介していきます。
1. どうぶつコマとは?
自分で好きな動物のコマを作り、そのコマで対戦をさせることができる子供用アプリです。1~2人で対戦ができます。
(1) はじめに動物を作ります。
動物のポーズをするとその動物を呼び出せます。呼び出せる動物は9個。何もポーズをしなかったときはヒトになります。
(2) 動物がコマに変身し、できたコマで対決をします。
対決はプレイヤーが1回転したスピードと選んだ動物の特性(強さ)で勝敗が決まります。
2. 開発環境
- Windows 10 Pro
- Azure Kinect
- Unity 2019.2.19f1
- Azure Kinect Examples for Unity
3. 開発の経緯
Azure Kinectではボーンの数、Depthの範囲などKinect V2から変わった点が多々ありますが、その中でも進化したBodyトラッキングに注目して動作検証をしていました。
進化したBodyトラッキング
感覚的に良くなっているなと思った点も含めると、以下の点が良くなっています。
(1) ボーンの数が増えている
(2) 後ろを向いていてもトラッキングしてくれる
(3) 胸より下が映ってなくても胸より上をトラッキングしてくれる
回転取得
「どうぶつコマ」は上記の中でも後ろを向いていてもトラッキングしてくれる点が面白く、つまり回転角度を取得できるんじゃないか?と思い、回転するコマで対戦するアプリを作成しました。
4. 実装方法
回転取得方法
Neckの回転角度で試した感じ、角度は割と正確に取得できます。ただ多少ブレがあるため1周を4ブロックに分けて簡易化させ、プレイヤーがどのエリアに今いるのかを把握し、順番通りにエリアを通ったら回転したと判別させています。例えば、右回りだとエリアが2→1→0→3→2とNeckの向きが変わると1回転したと判別しています。逆に左回りだと2→3→0→1→2の順番になります。
コードで書くと以下のような場合分けをしています。
int thisArea;
if (angle <= 45 || angle > 315) thisArea = 0;
else if (angle > 45 && angle <= 135) thisArea = 1;
else if (angle > 135 && angle <= 225) thisArea = 2;
else thisArea = 3;
ポーズ認識
ポーズは9種類あり、これらポーズの判別を以下2つの方法で認識をさせています。
(1) 「Azure Kinect Examples for Unity」に入っているStaticPoseDetectorを使用して認識させる
(2) 対象となる各部位の位置から判定して認識させる
それぞれ詳しく説明していきます。
(1) StaticPoseDetectorを使う方法
こちらは事前に用意したモデルのポーズとどれくらい似ているかをStaticPoseDetectorが判別してくれます。例えばクマの場合、以下のようなポーズを作ってInspectorでどの部位を比較するか設定しておけばいいだけです。
ただこの方法だと対処しきれない場合がでてきます。例えば、ゾウだと人によって腕を出す方向が違ったり、どれくらい前に出すかが違います。そういったポーズは次の(2)の方法を使って判別させました。
(2) 対象となる各部位の位置から判定する方法
動物によって実装コードは違いますが、ゾウの場合は「手が前に出ていて、首より下にあるとき」にゾウと判別しています。
// 各jointの位置
ulong id = kinectManager.GetUserIdByIndex(skeletonManager.playerIndex);
Vector3 handLeft = kinectManager.GetJointPosition(id, 9);
Vector3 handRight = kinectManager.GetJointPosition(id, 14);
Vector3 neck = kinectManager.GetJointPosition(id, 4);
// 腕の長さ
Vector3 elbowLeft = kinectManager.GetJointPosition(id, 7);
Vector3 shoulderLeft = kinectManager.GetJointPosition(id, 6);
float armLength = Vector3.Distance(handLeft, elbowLeft) * 100 + Vector3.Distance(elbowLeft, shoulderLeft) * 100;
// neckと手の距離(Z方向)
float handLeftLength = Mathf.RoundToInt((spineChest.z - handLeft.z) * 100);
float handRightLength = Mathf.RoundToInt((spineChest.z - handRight.z) * 100);
// ゾウ (手が前に出ていて、首より下にあるとき)
if ((handLeftLength > armLength * 0.6f && Mathf.Abs(handRightLength) < armLength * 0.4f && neck.y > handLeft.y) ||
(handRightLength > armLength * 0.6f && Mathf.Abs(handLeftLength) < armLength * 0.4f && neck.y > handRight.y)) {
// ゾウと判別
poseNum = 10;
}
コード中でarmLengthを使っているのは人によって腕の長さが違うため、相対的にどれくらい前に出ているかをif文で判別しています。子ども対象のアプリを作っているとこういった注意が必要です。子供対象であっても大人もプレイするので身長差を考えた上でアプリを作っていかないといけません。
さて、いかがでしたでしょうか?少しでもAzure Kinectのアプリ作成の参考になれば幸いです。
編集後記
広報のマリコです!今回はインタラクションデザイナーのMIZUTANIKIRINに技術解説をして貰いました。いつも可愛くて面白いアプリを開発してくれるMIZUTANIですが、今回使っているAzureKinectなど最新機器を使っているスピード感はさすがですね!子どもたちは、なぜかグルグル回ることが大好きなので「どうぶつコマ」は、きっとたくさんの子どもたちに楽しんで貰えるんだろうなぁと思いました!また体験型アプリは子供から大人まで楽しめるように身体的な特徴の違いも考えて開発するという体験型アプリならではの大変さもあるんですね。
子どもたちが「どうぶつコマ」で遊んでいる姿を見るのが楽しみです!
デザイニウム公式
・インタラクティブサイト
・Twitter
・Facebook
この記事が気に入ったらサポートをしてみませんか?