はじめに
unityでロープ部分を掴める表現をハンドトラッキングで作成する機会があったので作り方を紹介します。
ロープといえばObiRopeというアセットが有名ですが、今回はRope Toolkitを使用して作成しました。
https://assetstore.unity.com/packages/tools/physics/rope-toolkit-154662?locale=ja-JP
Oculus Integrationの後継であるMETA XR SDKを使用するので、掴む処理はMETA XR SDKの機能を使用して作成します。
META XR SDKの導入はこちらの記事をどうぞ
https://qiita.com/noritsune/items/24005df368f4154e9806
ここで紹介されている
- Meta XR Core SDK
- Meta XR Interaction SDK
- Meta XR Interaction SDK OVR Integration
を導入します。
unityバージョンは 2022 3.6f1です。
ObiRopeとRope Toolkitの比較
ObiRopeを採用しなかった理由は、Quest単騎でアプリを動かした際に処理が重く、フレームレートが落ちてしまうことが多かったからです。
多機能なため採用したかったのですが、本件では使用を見送りました。
それに対して、Rope ToolkitはBurstコンパイラを使用することで高速で処理することができ、モバイルデバイスでの使用も考慮された設計になっているため今回はこちらを採用しました。
作成手順
1. 準備
- Burstコンパイラの導入
まず、Rope Toolkitを動かすためにPackageManagerより、Burstをインストールします。
(Unity Registryに存在します。)
- RopeToolkitの導入
unity Assets StoreからRope Toolkitを導入します。
Burstを導入していればインポート後、エラーを吐きません。
2. ロープを作成
ここでは、必要最低限の設定のみ紹介します。
まず新しくゲームオブジェクトを追加して「Rope」と「RopeConnection」のコンポネントを追加します。
SpawnPointsにElementsを2つ追加して以下のように設定します。
次に、Cubeを2つ用意します。Scaleを (x,y,z)=0.05 にします。このCubeがロープの両端に追従する部分です。
これらをRopeConnectionのTransformにアタッチします。
また、RopeConnectionコンポネント内のRopeLocationが追従する場所を指定する設定項目です。片方のRopeLocationを1にします。
これでロープの設定は完了です。
3.プレイヤーの作成
次にプレイヤーの設定をします。
META XR SDKのBuildingBlocksで「CameraRig」、「HandTracking」、「GrabbableItem」「Synthetichands」を追加します。
次に、今回は右手で掴みたいので掴めるCubeとの接触を判定するコライダーを右手の位置に配置して、ColliderのIsTriggerをONにします。
Positionを右手にかぶるように配置して、Scaleは(x,y,z)=(0.05~0.1)に調整します。
4. ロープを掴む処理作成
ロープを掴む処理の作成に入ります。
まずは以下のスクリプトを作成します
using RopeToolkit;
using UnityEngine;
using UnityEngine.Serialization;
public class RopeHandGrab : MonoBehaviour
{
[SerializeField] GameObject _targetObject;
[SerializeField] Rope _rope;
[SerializeField] GameObject _hand;
[SerializeField] int _ropeIndex;
bool _isGrab;
void Update()
{
if (_isGrab)
{
// 手がコライダーの範囲に入ったら、ロープのJointの位置を手の位置に追従
_rope.SetPositionAt(_ropeIndex, _targetObject.transform.position);
}
else
{
// 常にロープの指定したインデックスのJointを取得して、掴むキューブをその位置に追従
Vector3 ropePosition = _rope.GetPositionAt(_ropeIndex, false);
_targetObject.transform.position = ropePosition;
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject == _hand)
{
_isGrab = true;
}
}
void OnTriggerExit(Collider other)
{
if (other.gameObject == _hand)
{
_isGrab = false;
}
}
}
_ropeIndexで指定した関節部分に掴めるCubeを常に配置しておいて、これを掴むことで追従するロープも動かすという作りです。
次に掴めるCubeの設定です。
先程追加した[BuildingBlock] Grabbable Itemの名前をHandGrabPointとします。
コンポネントに「RopeHandGrab」を追加して適切なものをアタッチします。
加えて、Scaleをつかみやすいように(x,y,z=0.1)に変えておきます。
5. ロープが荒ぶる場合
4.作成完了時点でロープを掴むことができるようになっています。
しかし、掴んだ時にロープが荒ぶってしまう現象が起きていると思います。
この対処法として、Ropeコンポネントの値を変更して挙動を調整する必要があります。
私が作成したロープは以下のように設定を行いました。
これで掴んだときもロープが荒ぶること無く掴めるようになりました。
お知らせ
弊社は現在、xRエンジニアを募集しています。
その他の職種も随時募集中です。