今回のお話
- UnityAdventCalender2013 9日目の記事です。
- http://www.oculusgamejam.jp/blog/?p=13
- あまりUnityは関係ない
- RazerHydraの入力をなんとなく扱いやすくした時の話。
使ったもの
- Oculus Rift
- RazerHydra
- Unity3d
今回の走り調整はどういうものか
RazerHydraのx,y,zの移動量を数フレーム分保持しておいて保持している移動量の平均によって移動量が決まる。
なんとなく今回のコード
走ってよいかどうかを返す関数
// 最終的な走る時の計算に使う値
float averageVelocity = 0;
// 変化量保持用リスト
Queue<foat> velocityCache = new Queue<float>();
// RazerHydraの前回の入力を保持する為の配列
Vector3[] lastPosition = new Vector3[2];
bool IsMove()
{
float velocity = 0;
for ( uint i = 0; i < 2; i++ )
{
if ( SixenseInput.Controllers[i] != null )
{
if ( SixenseInput.Controllers[i].Enabled )
{
// rhVelocityFilter 入力A、B の差分がしきい値未満あるいはあまりにも大きな変化料の場合は0を、そうじゃない時は差分をそのまま返す
var diff = rhVelocityFilter (SixenseInput.Controllers[i].Position, lastPosition[i]);
velocity += Mathf.Abs (diff.magnitude);
}
lastPosition[i] = SixenseInput.Controllers[i].Position;
}
}
// RazerHydraは入力2つなので1つ分の入力として扱うために2で割る。
velocity = velocity / 2.0f;
// ※ノイズの除去
// しきい値以上の値の場合のみ変化量保持キューに追加。そうじゃない場合は何もしない。
if (velocity > velocityLowBorder)
{
velocityCache.Enqueue(velocity);
deltaTime = 0;
}
else
{
deltaTime += Time.deltaTime;
}
// キューが保持する予定の最大数を超えたら一番古いのを消す。
if (velocityCache.Count > cacheCapacity)
velocityCache.Dequeue();
// もしも一定時間しきい値以上の入力がなかった場合は変化量保持キューの中身を空っぽにする。
if (deltaTime > queueResetTime)
velocityCache.Clear();
// ※ 現在保持している変化量達の平均を出す。
float total = 0;
foreach(var vel in velocityCache)
{
total+= vel / cacheCapacity;
}
averageVelocity = total;
// 変化量の平均がしきい値以上だったら動いてよし!
if (averageVelocity > velocityLowBorder)
return true;
else
return false;
}
自分はこんな感じで移動して良いかどうかの中でそのまま移動の際に使う値も計算してますがきっと行儀悪い…
最終的にはaverageVelocityを実際のプレイヤーが移動する部分で更に各ゲームに合わせた感じで直してやると良いのかも
(自分はここの値を更に計算で変えている)
大事そうな所
ずらずら並べた割にはそこまで重要な所は多くなくて
大きく2点
- ノイズの除去
- 一定フレーム分保持されたデータの利用。
この2つなんじゃないかと思います。
ノイズの除去は入力していないつもりの時に勝手になにかしたりするのを防いだりあらぬ操作の元を断つ為に
(どんなゲーム、デバイスでも同じことだと思う)
後者の一定フレーム分保持されたデータの利用は今回は数フレーム分の平均を今回のフレームの移動量の係数にする形を撮っていたけどゲームによってはきっと平均にしなくてもいいと思う。
と、こんな感じで係数はこんな感じで出していたよというお話でした。
ゲームによって様々だと思いますがなんかちょっとした参考になれば幸いです(;´Д`)
以上ありがとうございました。m(_ _)m