Obi - Advanced Rope Simulationで滑車をシミュレーション

# はじめに

[Obi - Advanced Rope Simulation](Obi - Advanced Rope Simulation) は2016年に発売された、紐のような構造を物理演算するための有料Unityアセット($30)です。

![image.jpeg](https://qiita-image-store.s3.amazonaws.com/0/58503/cb31845c-bb4e-f5e2-d791-84f0e63fc586.jpeg)


同じようなアセットはすでにアセットストアに幾つかあります（Ultimate Rope Editorなど）が、このアセットは紐と他のゲームオブジェクトとの衝突や変形時の力学計算がより正確で、他のアセットでは難しい滑車のような複雑な構造も作ることが可能です。

Obiは物理演算に（他のアセットではしばしば用いられる）RigidbodyやJointを使わず、パーティクルシステムを使って手続き的にメッシュを生成しています。そのため、紐の設定がやや独特になっています。この記事では、滑車を例にとって使い方を簡単に説明します。詳しいことは[公式マニュアル](http://obi.virtualmethodstudio.com/tutorials.htm)をご覧ください。

**注意：現状ではAndroid, iOSでのビルドがうまくいきません。今後のバージョンアップに期待しましょう。**

# 基本設定とサンプルシーン

Obiパッケージをインポートしたら、まず**/Obi/Gizmosと/Obi/Editor Default Resources フォルダをAssetsフォルダをの直下に移動する必要があります**.。これをやらないとエラーになります。移動したら、Sample ScenesのPulleyシーンを開きましょう。実行すると、以下のような動きが見られます。

![GifAnim1.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/3afee0d9-a4b8-2d56-cbe6-45b01030424c.gif)

ここでのポイントは以下の３つです:Obi Handle, Obi Pin Constraints, Obi Curve Components

## Obi Handle

Obiの一部をゲームオブジェクトとして移動させたり位置を固定するのに使います。Pulleyシーンでは、ロープの右端を固定するのに使っています。ゲームオブジェクトなので、Editor上で移動できます。位置の変更は、実行時に反映されます。

![GifAnim2.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/1a5c2724-08ce-7388-b5c8-403251ed1cdb.gif)

## Obi Pin Constraints

Obiの一部を他のゲームオブジェクトに固定するために使います。この例ではキューブ(Cube(1))とロープの左端をつなげるのに使っています。設定するには、RopeゲームオブジェクトのObi RopeコンポーネントのEdit Particleを起動します。すると、各パーティクルをクリックして設定を確認できます。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/f37c2ffb-8cc3-ce39-0a54-202d2f01214d.png)

ロープ左端のParticleをクリックするとObi Pin Constraintsコンポーネントに設定が表示され、Cube(1)にPinされていることが分かります。OffsetはCube(1)の中心からどれくらい離れたところにRopeの左端のParticleとの接合部を設けるかを決めます。PinするゲームオブジェクトはColliderを持ち、SolverゲームオブジェクトのCollider Groupeに含まれていることが必要なので注意してください。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/9fea09c0-3638-16ac-d778-0bf439d071e9.png)

他の注意点は[マニュアル](http://obi.virtualmethodstudio.com/pinconstraints.html)を参照してください。

## Obi Curve Components

Obiでは、初期状態のロープの形状をCurve Componentで決めます。Curve ComponentにはObiBezierとObiCatmullRomの二種類があり、Pulleyサンプルシーンでは後者を使っています。シーンのCurve(1)を選択すると、ロープ上に白い点が表示され、それをクリックすることでロープの形状を変更できます。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/cb75a145-429c-dcb2-0d19-d3e2846837ab.png)

変更したら、RopeゲームオブジェクトのObi RopeコンポーネントのInitializeボタンを押して変更を反映します。

![GifAnim3.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/83e3b16a-a9c3-4f33-cb82-8259d572a0a0.gif)

どうやら、Curveを変更すると、Obi Handleの設定が消えてしまうようですので注意してください。


# 自分で作ってみる

自分で作る場合は、以下の手順になります

- Obi Ropeオブジェクトの設置
- Rope Pathの設定
- Obi RopeのMeshのマテリアルの設定
- Ropeにつくオブジェクトの設定
- 車輪の設定
- Colliderの設定とlayerの設定
 
## Obi Ropeオブジェクトの設置

メニューからGameObject -> 3D Object -> Obi -> Obi Ropeを選択すると、Obi RopeとRope Pathが作られます。Rope PathゲームオブジェクトのObiCatmullRomコンポーネントで、Add Control Pointを押してコントロールポイントを増やし、それっぽい形を作ってください。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/c3d0f7de-2c06-8e85-e4c2-e93e32b1a869.png)

## Obi RopeのMeshのマテリアルの設定

Obi RopeのMesh Rendererコンポーネントで、Materialを選択します。とりあえずは、付属のGreen Ropeにしておきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/ce18d709-ac54-fa11-0f79-522d39202467.png)

この状態でObi RopeコンポーネントのInitializeボタンを押せば、ロープが作られます。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/a744522a-a3a4-e49a-e524-b5421c8fbe54.png)

## Ropeにつくオブジェクトの設定

ここでは、Ropeの両端にCubeをつけることにします。Cubeを二つ作って、両端近くに配置します。各々にRigidbodyコンポーネントもつけておいてください。つぎに、Obi RopeコンポーネントのEdit Particleボタンを押してParticle Editorを起動し、両端のパーティクルのそれぞれに対し、パーティクルをクリックして、Obi Pin ConstraintsのAdd Pin Constraintsを押します。そして、Pinned toのところに、該当するCubeを選択します。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/e0d6a1ce-9a3f-f190-e7f7-9ddf38648d3e.png)

## 車輪の設定

車輪はめんどくさいのでただのCylinderで代用します。ロープが引っ掛かるように置いておきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/93de7bbd-d68a-d096-2310-a4ef80ab9850.png)

rigidbodyも設定して、massを500くらいにしてください（mass = 1だと、なぜかコリジョンがうまくいかずロープがすり抜ける）ConstraintsのFreeze position, Freeze rotationをすべてオンにします。

## Colliderとlayerの設定

ロープと相互作用するゲームオブジェクトはObi RopeのObi Collider Groupに登録する必要があります。３つオブジェクトがあるので、Collidersのリストのサイズを3にして、登録します。

さらに、ロープ本体衝突するオブジェクト（今回はCylinder）とロープ本体は別のレイヤーである必要があります。新しいレイヤー（ここではRope）を設定して、Obi RopeオブジェクトをRope Layerに配置します。

## テスト

これで実行すると、以下のようになります

![GifAnim4.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/8635d21d-e02c-c8a7-5428-ce32f85617b2.gif)

一応ロープがCylinderに引っかかっているものの、すぐにずり落ちてしまいます。

それを調節するには、Obi RopeコンポーネントのMaterialを設定します。HighFrictionを設定すると、ひもが車輪を滑りにくくなります。

![GifAnim5.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/dd1c437d-108d-0c46-fb2c-10d369665bb8.gif)

## Cylinderが回るようにする

先ほどは、簡略化のためにCylinderはRigidbodyのFreeze position, Freeze rotationで固定しましたが、そうすると、ロープとの摩擦に応じた車輪の回転は起こりません。それを実装するには、Cylinderにhinge jointを設定し、Anchorを(0,0,0), Axisを(0,1,0)にします。Freeze position, Freeze rotationのチェックはすべて外してください。

![image](https://qiita-image-store.s3.amazonaws.com/0/58503/323085a7-d9f9-4a79-6d7b-f58f652b1b52.png)

この状態で実行すると、RopeとCylinderの摩擦によりCylinderが回転し、Ropeが移動します（回転が見えやすいようにSceneビューを動画にしてます）。

![GifAnim6.gif](https://qiita-image-store.s3.amazonaws.com/0/58503/48f7e036-cc5f-c91e-a409-57b77fe87cf7.gif)

ちなみに、この回転は、Obi RopeコンポーネントのMaterialを設定していないと起きません。

## 最後に

私もObiを使い始めて日が浅いので基本的な機能しか使っていませんが、それでもかなり高機能なRopeシミュレーションアセットだと思います。もし、不足している点がありましたらご指摘いただければ幸いです。