メカ徒然日記
とある工学屋のブログ.鳥人間とかプログラミングとか.
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


Unityリンク集
Unityを触っていて、よくお世話になっているサイトをまとめて乗っけとくと便利かな、と。
毎回検索するのも面倒なので、、、
ブックマーク代わりに

ゲームは初心者に優しく

Unityユーザマニュアル(公式)

テラシュールウェア

rigidbody

実験工房掲示板

チリペディア

○×つくろー!->ゲーム作ろー!

コガネブログ
スポンサーサイト

OculusRift+Unity失敗 解決事例 主にカメラ
本記事はOculus Rift Advent Calendar 2013 19日目
12/19担当記事として執筆しました。

[まえがき]
Oculus Rift,素晴らしいですね。ヘッドトラッキング付立体視HMDが3万円台
(為替レート・送料・税関代込)で手に入るなんていい世の中になりました。
さっそく飛びついたわけです.
僕はHPASimというフライトシムをC++で書いており、
これをOculusRiftでやりたいなぁ、と思い、ここ3か月ほどUnityに触っています。
なるほど。キャラクターを配置したり、簡単な物理を導入するの、早い!
Rigidbodyの追加されたキャラクターを置いて、跳ね回るキャラクタを眺め回すまでせいぜい1時間。
ああUnity素晴らしい。
MMD4Mecanimのおかげで、キャラクター出すのがボタン押すだけになってて、もうすごいんです。
これらをCで書くのって、結構つらい。


しかし簡単にゲーム作れるかというと、そうはいきませんでした。
というわけで本記事はプログラム書き始めて数年の趣味プログラマが、
OculusRift+Unityで引っかかったネタになります。

内容で、ほかの人とかぶったらごめんなさい。

[ひっかかりポイントと解決]
まず引っかかったのがカメラ。

①ミクさんに近づくと、消える
わーいみくさんだー、と近づくと・・・
見切れる_R
表示が…これでは至近距離に近づけない!
NearClip(ゲーム内で、これより近いところはうつさないよ、という距離設定)が原因だな、ということはわかったのですが
OVRCameraControllerのNearClip Plane値をいじっても、治りませんでした。
対処方法、詳しくは@CST_negi さんの記事を参照してください。
解決策:右カメラ/左カメラ[それぞれ]の設定を変える
僕はNearClip0.01~0.05くらいにしてます。


②.一人称視点カメラ
自分の分身としてキャラクターを用意すると、没入感が上がります。
キャラクターにカメラをくっつけて、
頭位置にカメラを移動すれば、一人称視点っぽくなるっだろう、とやってみると。。。
顔の中_R
周りを見回すと、顔の中が見える…こわい・・・
これはいわば、目玉(カメラ)だけが顔の中に浮いていて、
空の方向を向くので、頭蓋を見てしまっています。
また、キャラクターが座ったりするとカメラだけ宙に浮いてしまいます。

解決策:
つまり、キャラクターの目玉に当たる位置に、常にカメラがあればよいのです。
そのために、

A:カメラを、首を中心にオフセットをつけて回るようにする
B:カメラ(OculusRift)の回転に、キャラクター頭の回転を追従させる
の両方を実施します。


A:人間の頭の動きは、首を中心にオフセットがついて回っています。
目は、それに付随する形で動きます。OVRCameraControllerを、
キャラクタの、頭のJoint内に入れることで解決。凹みさんの記事①が詳しいですね。

追加としてカメラのポイントが目の位置にくるよう、オフセットとしてEyeCenterPositionをいじっています。
(Componentのtransrationをずらしてもいけます。)
カメラ設定_R
(もうちょっと目に近づけたいところですが、あまり近づけすぎると激しい動きをしたときに
また顔の中が見えます。カメラの姿勢更新に、キャラの頭姿勢更新が数フレーム追い付いてないようです。
なんで?)


B:凹みさんの記事②を参考にしました。
あちらでは「ミクさんの頭の向き」を「カメラに向けて」制御しているところを、
「自キャラの頭の姿勢」を「カメラの姿勢」で制御しています。
コードはこれを、自キャラにアタッチします。

using UnityEngine;
using System.Collections;

public class PilotBehaviourScript : MonoBehaviour {
private GameObject player_;
private GameObject head_; //pilot head
private GameObject camera_; //camera object

// Use this for initialization
void Start () {
//get Player Component
player_ = gameObject;

//get head component
head_ = gameObject.transform.FindChild("95.!Root/5.joint_HipMaster/10.joint_Torso/19.joint_Neck/20.joint_Head").gameObject;
Debug.Log (head_.name);

// Get main camera
camera_ = GameObject.FindWithTag("MainCamera");
Debug.Log (camera_.name);

}

// Update is called once per frame
void Update () {
Quaternion headRot = camera_.transform.rotation; //カメラの姿勢を、頭の姿勢に代入
head_.transform.rotation = headRot;
}
}

これで、頭の中が見えなくなりました。プレイビューで見ると、キャラの頭に合わせてカメラが回っていることが確認できました。凹みさん、ありがとうございます…!

③アニメーション
しかし、これにアニメーションをつけると、またキャラクタの頭が回らなくなりました。
アニメーションが、頭の姿勢を上書きしているようです。
凹みさんの記事のように、vmd書き出し時にMMDからの書き出しに頭は含めていないのですが、mecanimアニメーションの仕様か、mmd4mecanimの仕様か、アニメーションのない関節も0で上書きされるようです。

そのため、キャラクタに再生させるアニメーションで、首・頭の動きを再生させないようにマスクをかけます。
mask1_R.png
fbxファイルを選択、Animationタブから、マスクをかけたいアニメーション(今回はpilot001)を選択します。

mask2_R.png
下にスクロールしてMask->Transform ツリーを展開 (Definition:Create from This model )

mask3_R.png
下にスクロールして、neck_jointのチェックをクリックすると、neckジョイントの子ジョイントすべてのチェックが消えます。
チェックの消えた関節は「アニメーションで上書きしない」設定になります。


mask4_R.png
チェックを消したら、Applyボタンを押す。

これでようやく、アニメーション付きでも、頭を動かせるようになりました。
TwitterのUnity先達者の皆様、ご助言ありがとうございました。

④カメラの基本姿勢を、キャラクタに追従させる。
乗っている飛行機が回転したり、
FPSでキャラクターの向きをジョイパッドで変えた場合、
頭を動かさなくても、そちらの方向に向いてほしいですよね。
OVRCameraControllerをキャラクターのObject下に置いただけでは、これは実現されません。
装着者は真っ直ぐ座ったままで、飛行機が回転した場合、このような状態に…。
rotation2_5_R.png

OVRCameraControllerのFollowOrientation に、キャラクターのObjectを指定することで、
キャラクタの回転に合わせて、カメラも回るようになります。
rotation2_R.png



rotation3_R.png




ほかにもジョイパッドのアナログスティックで嵌ったこととか、
VR内でテレビを見るとかありますが、この辺で。
次のCalender担当は@n_yositaka さん、お願いいたします。

おまけ:
やってみたい だれかやってなネタ集:
a:スキージャンプ:スカイダイビングは遠景過ぎてスピード感・立体感が出にくいよね、
という話から派生。地表面近くを飛ぶスキージャンプならよいのでは?という話が出ました。

b:MikuMikuKotatsu:ミクさんとこたつで足がぶつかって、恥ずかしがる、そんなシチュエーション。
という発言にやられて製作開始。日本人の心の故郷、炬燵。こたつで初音ミクとVRまったり。
もうそこで世界終わるよね。
気が付いたらまた別のものが出来上がっていた…そのうち公開します。

c:HPASimForOculusRift:DXライブラリで製作中のゲーム、HPASimのOculus対応版。
特に鳥人間コンテストの飛び出しイメージをつかむとか、ついに500mを超えた滑空機
みたかもばらの視点・引き起こしタイミングのトレースとか、
突風後対応操作、操作インタフェースの配置検討など、
詰めていけば結構使えるんじゃないかな、と思っています。物理系を移植中。年内完成するとうれしい。


d:生体電位ネタ:筋肉のに力を入れるとエフェクトが光る、とか。
研究で筋電(生体電位)をやっていたので。低周波治療器のゲルパッド+計装アンプで作れます。
感電注意。電源は電池にしましょう。


本記事内で使用したモデルなどについて:

学ラン君 ver1.0a:作者 mato さま
Tda式初音ミク・アペンド:作者 Tdaさま
この作品はピアプロ・キャラクター・ライセンスに基づいてクリプトン・フューチャー・メディア株式会社のキャラクター「初音ミク」を描いたものです。

HPA_Naviを無線化する
@HirakuTOIDA さんの製作されたHPA_Navi
Bluetooth(BT)でPCと通信させるお話です。


HPA_Naviは標準でXBeeに対応しています。そのためランニングエレクトロニクスさんのSBXBT
と適当なBTドングルを使うと、HPA_NaviとPCがBTのSPP(Serial Port Profile)で通信できるようになります
BluetoothのSPPはペアリング済みのBT機器との通信を、シリアルポートと同じように扱えるお手軽なBT通信です。

やり方は簡単。
(PCにBT機能がない場合、あらかじめBTドングルをPCにさす)
①SBXBTにBTドングルを挿す
IMG_1931_R.png


②HPA_Naviに①を挿す。LEDの関係上、↓の写真のほうに挿すと確認しやすいのであすすめ。


③HPA_Naviの電源を入れる


④SBXBTの赤LEDが消え、SBXBTのオレンジLEDが点滅するまで待つ(SBXBT初期化完了)
IMG_1939_R.png
IMG_1953_R.png


⑤Bluetoothデバイスの追加->(デバイスを検索しています)->SBXBT-xxxxxx(xxxxxxはその機器のBTアドレス)をクリック
SSPSeek_R_R.png

xxx_R_R


⑥ペアリングのコードを聞かれるので、0000 と入力しOK(SBXBTの標準)
これでペアリングが完了する。

⑦割り当てられたCOMポートを調べる。
SSPCall_R_R.png
SSP_R_R.png


Ground station software for HPA_Naviを起動し、先ほど調べたSelect欄からCOMポートを選択し、Connectボタンを押す、

IMG_1965_R.png
接続に成功すると、HPA_NaviのLED5(赤)が点滅。
SBXBTの赤LEDも点滅。
これだけ。ペアリングしてポートを調べるところ以外、特に面倒なところはありません。

いちどペアリングしておけば、
次からはHPA_Naviの電源入れて、初期化の赤ランプが消えるのを待って、⑧でつなげます。

parityやstopbit、フロー制御などの設定を変更する必要は特になさそうです。
(ちなみにSBXBTは標準だとフロー制御有になっている。)
SBXBTはHPA_Naviの通信速度に合わせて、勝手にボーレート38400にしてくれます。便利。

試した環境:
OS:Windows8 64bit
HPA_Navi:Rev.A DipスイッチはON-ON(500mA制限) (HPA_Navi Ⅱではない)ファーム変更なし
BTドングル:BT-Micro3F2XおよびBSBT4D09BKで確認。
SBXBT:1.1(と基板に刻印されてる)

余談:
0:ペアリングができれば、設定とか特になくつながります。ペアリングできない人は、ランニングエレクトロニクスさんの取扱説明のpdfを読みましょう。
win8は新しいBTデバイスの検索時にヒットしないことがたまにあるので、
そのときはHPA_Naviの電源を入れなおして再度試しましょう。

1:BTなどの無線機器は本来、技適といって認証を通していない無線機器を所持しちゃいけない、という法律があり、認証を通す必要があるのですが、SBXBTは市販の認証のとれたBTドングルをそのまま使うことで解決しています。

2:割り当てられたシリアルポートの番号を変えたい場合、こんなやり方があります。
http://d.hatena.ne.jp/takinoya/20080505/1210001295

3:
ちなみに、はじめXbee-WifiでWifi化しようと思ったのですが、シリアル通信とTCP/IP通信は別物なので、
HPA_Naviファームウェアの書き換えが必要になるので保留しました。

mbedでMPU6050
mbedでジャイロ3軸、加速度3軸のMPU-6050(InvenSense)の乗ったボード
が動いたので報告。なんと買ったときはなんと600円。お安い。乗ってるセンサはこれ。

I2Cなので注意。

テストにはLPC1768とStarBoardOrangeを使用しました。

LPC1768(青mbed)の
9番ピンをsda
10番ピンをsclと結線。
ad0(アドレス指定用ピン)をGNDに接続。
VCCはmbedのVOut
GNDはmbedのGNDに接続。
IMG_1754_R.png
念のためsda,scl端子はプルアップ。

http://mbed.org/users/Sissors/code/MPU6050/docs/5c63e20c50f3/classMPU6050.html
このクラスを使用しますがアドレスが違うようなので書き直す。

MPU6050.hの

MPU6050_ADDRESS 0x69 を

MPU6050_ADDRESS 0x68 に変更。

コードはこんな感じ。
TextLCDMPU6050のライブラリは各自用意のこと。

#include "mbed.h"
#include "TextLCD.h"
#include "MPU6050.h"
#include < string >
#define N 3
TextLCD lcd(p24,p26,p27,p28,p29,p30);//rs,e,d0,d1,d2,d3
MPU6050 mpu(p9,p10);//sda,scl


void PrintFloatN(const float data[N],string name)
{
lcd.printf(name.c_str());
for(int i = 0; i < N ; i++ ) {
lcd.printf("%4.1f",data[i]);
}
lcd.printf("\n");
}

int main()
{
float acc[N];
float gyro[N];
//initialize

for(int i = 0; i < N ; i++ ) {
acc[i] = 0;
gyro[i] = 0;
}


while(true) {
//update
mpu.getAccelero(acc);
mpu.getGyro(gyro);

//draw
lcd.cls();
PrintFloatN(acc,"acc");
PrintFloatN(gyro,"gyro");
wait(0.1);
}
}

HPASim進捗
HPASimの進捗です。
・アップローダをbowlrollにしました。
・OculusRift版の開発を始めました




上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。