© Unity Technologies Japan/UCL
概要
Oculus Quest2, Unity, VRIK を使用して、最低限3Dモデルを動かせるようにしました。
VRIKの調整が若干手間だったので記録として残しておきます。
- やったこと(IK などのモデル操作周りは既存のライブラリや OSS 頼りです
- Oculus + VRIK での上半身操作
- OculusFinger で指の操作
- 移動、モデルの向き変更(x軸)、ジャンプ
- やってないこと
- Animationの適用( WALK や JUMP )
1. Hierarchy構成
① | ・OVRCameraRig と3Dモデルをwrapするオブジェクト ・モデルとカメラの向きの変更や高さの変更(ジャンプするとき)を一緒に行うので親要素を用意しました。 |
② | ・VRIKにHeadTargetとして設定するオブジェクト。 |
③ | ・左手のPosition調整用のオブジェクト。 ・RotationとPositionを同一オブジェクトで設定してしまうとPositionを任意の位置に移動しづらくなる(後述)ので親オブジェクトでPosition, 子オブジェクトにRotationを設定するようにしました |
④ | ・左手のRotation調整用のオブジェクト ・VRIKのLeftArmのTargetとに設定する。 |
⑤ | ・右手のPosition調整用のオブジェクト ・③に同じ。 |
⑥ | ・右手のRotation調整用のオブジェクト ・VRIKのRightArmのTargetに設定する。 |
⑦ | ・腰の位置の調整用のオブジェクト ・VRIKのPrevisのTargetに設定する。 |
⑧ | ・VRIKに設定する両足のオブジェクトの親オブジェクト ・足の間の距離を変えずに位置調整する用に作成。 |
⑨ | ・右足 ・VRIKのRightLegのTargetに設定する。 |
⑩ | ・左足 ・VRIKのLeftLegのTargetに設定する。 |
↓3Dモデル(unity chan)にアタッチしているVRIK
2. VRIKの調整
2-1 ②頭、⑦腰、⑨右足、⑩左足
これらに関しては VRIK の公式Tutorealを参考に、単純に Position, Rotation を調整していく方法で問題ありませんでした
2-2 ⑥右手、⑧左手の調整
これらも 2-1 の手順である程度対応可能ですが、2点問題がありました。
問題1 OVRCameraRigのLeftControllerAnchorとRightControllerAnchorの位置が3Dモデルの手の位置と遠すぎてうまく調整できない
この問題を Right/LeftHandTarget のPosition修正で対応できればいいですが、
それだけだとOVRCameraRigの Right/LeftHandAnchor の位置は遠いままであり、
コントローラーを回転させたときAnchorの位置を起点にTargetが回転してします。
いろいろいじった挙句、最終的には OVRCameraRig のScaleを0.5にする(OVRCameraRigを小さくする)ことで解決しました。
(一応unitychanのスケールを変更しても解決できますが、全てのオブジェクトのスケールに影響してしまうので↑の方が無難です
(他解決策があれば教えてください🙏
2-2-2 Positionで調整しようとしてもRotationを指定した後だと任意の位置に動かしづらい
Hierarchy 構成の説明でも触れましたが Rotation をかけてしまっている状態だと Position も回転がかかっている状態になってしまいます。
なので親要素を用意してそちらでPositionを調整しました。
3.指の操作
指の操作ですが下記で公開されているコードを使用させていただきました。🙏
各指の第一ジョイント(ボーン)にアタッチすれば使用できます。
https://eyln.hatenablog.com/entry/2016/12/19/003435
4.移動・回転・ジャンプ
こちらは下記で簡単に対応しました。
移動
キャラクターを回転させるので Position ではなく現状の向き( transform.forward, transform.right )に対して値を加算しています。
// gameObject = unitychan と OVRCameraRig をwrapしているオブジェクト
void Walk()
{
Vector2 stickR = OVRInput.Get(OVRInput.RawAxis2D.RThumbstick);
if (!stickR.Equals(Vector2.zero))
{
Vector3 changeForward = gameObject.transform.forward * -(stickR.y / 20);
Vector3 changeEight = gameObject.transform.right * -(stickR.x / 20);
gameObject.transform.Position += changeForward + changeEight;
}
}
回転
unitychan と OVRCameraRig を同時に回転させる必要があるのと
カメラを unitychan の頭に埋もれないようにしたり、 HeadTarget の位置調整をしているため、
unitychan と OVRCameraRig の親要素 = GameObject を unitychan のy軸を中心に回転させています。
(上下左右に視点を回転できると一瞬で酔うので左右のみに限定しました…
// character = unitychan
void Rotate()
{
Vector2 stickL = OVRInput.Get(OVRInput.RawAxis2D.LThumbstick);
if (!stickL.Equals(Vector2.zero))
{
Vector3 center = character.transform.Position;
gameObject.RotateAround(center, Vector3.up, stickL.x);
}
}
ジャンプ
落下速度とかを考えず単純にyを加算・減算してます。
void Jump()
{
float height = gameObject.transform.Position.y - initialHeight;
bool isOverLimit = height >= jumpHeight;
// isJumping flag change
if (isOverLimit)
{
isJumping = false;
}
if (height <= 0 && OVRInput.Get(OVRInput.RawButton.Y))
{
isJumping = true;
}
// jumping
if (isJumping && !isOverLimit)
{
gameObject.transform.Position += new Vector3(0, 0.05f, 0);
}
// falling
if (!isJumping && height > 0)
{
gameObject.transform.Position -= new Vector3(0, 0.05f, 0);
}
}
おわりに
改善点としてはやはり移動時、ジャンプ時の動きが微妙なのでアニメーションを追加で解決したいです。
(今回はVRIKの設定を中心に最低限の動きをさせることを目指しました。)
参考にさせていただいた記事・サイト
- https://www.youtube.Rightcom/watch?v=6Pfx7lYQiIA
- https://eyln.hatenablog.com/entry/2016/12/19/003435
- https://qiita.com/nyu___nS/items/b4658afc849f8906afb0
- https://unity-chan.com/
使用させていただいたモデル