Programming in VRChat

VRChat でのプログラミングについて調べたことの書き溜め

CyanClimbing スタートアップ・ガイド

VRChat ワールドでクライミング(壁登り)動作を実現するプレハブ CyanClimbing が公開されました。

その使用方法についての利用開始にあたっての手引きを私がツイートしていたものを、読みやすいように一つの文章にまとめました。


概要

CyanClimbing は、クライミング動作を行える VRChat ワールドを作れるようにするプレハブです。

この文章は naqtn が CyanClimbing を使用した経験を基に、このプレハブを使い始める手引きとして書いたものです。 正確なところは readme.txt を参照してください。 (この文章だけでワールド作成に必須な情報は得られると思いますが、readme.txt の内容すべては反映していません。 特に Custom Trigger Events の部分は応用的な使い方になるため省きました。)

readme.txt の冒頭の部分だけ謝辞が含まれているので訳出します:

HardLight と Phasedragon へ。ありがとう。

このプレハブを使ってワールドを公開したら、作者 CyanLaser に Discord で DM を送ってください。それを見てみたいです。

ライミングシステムは、4つの Climbing Trials (Rapunzel, The Depths, Sky Temple, Collosus) と VRCPrefabs ディスコードのゲームジャム Climbjam で使われました。 耳のところを握ってから壁を保持して登ります。

このシステム全体は player base tracking ( http://vrchat.wikidot.com/worlds:guides:player-tracking ) に基づいています。

(訳ここまで)

セットアップ

動かすには Standard Assets に含まれる Utility と Cameras のパッケージも合わせてインポートする必要があります。 (Unity メニュー > Assets > Import Package > Utility および Cameras を実行します。あるいは Asset Store から導入でも構いません) サンプルシーンが含まれているのでまずはこれを動かしてみると良いでしょう。クライミング動作が出来たら開発準備は完了です。 通常のVRChatワールド作成手順でシーンを作った後に、CyanClimbing プレハブを加えるだけでクライミングできるようになります。

動作の基礎(レイヤーによるオブジェクト識別)

オブジェクトが登れるかどうかは GameObject に設定するLayerによって決まります。 シーンに置いた「CyanClimbing」を見ると「ClimbingSetup」というコンポーネントが含まれています。 ここで、シーン中のオブジェクトをどう扱うかを設定します。 デフォルトでは「Environment」と「Walkthrough」レイヤーが登れるようになっています。

f:id:naqtn:20190723062718p:plain

(このコンポーネントは Unity エディタ中でだけで動作します。 設定値を変更すると「子オブジェクトやレイヤーで探したシーン中のオブジェクトなどの必要なプロパティを書き換える」 というようにして動作しています。)

プロジェクト作成直後は ClimbingSetup コンポーネントに "Add Climbing Hand Layer" ボタンが表示されます。 これはプロジェクトのレイヤー定義に「ClimbingHand」を加えます。 このようにして、レイヤー毎のコライダーの衝突を基礎として設定や動作を行うようになっています。 (必須ではないですが Tag も使います)

f:id:naqtn:20190723071352p:plain

("Cannot find VRChat layers! Please setup VRChat layers in the Build Control Panel!" という表示のみの場合は、VRChat の通常のレイヤー設定がまだできていません。まずは VRChat の Build Control Panel でレイヤーの設定を済ませてください。)

サンプルシーンによる理解(特に jitter 現象について)

サンプルシーンには設定が異なるオブジェクトが並んでいます。 まずは実際にプレイしてみて違いや動作を体感してみるのをお勧めします。

f:id:naqtn:20190723070442p:plain

「Climbable but Jitter」と書いてある所は、登っている途中で自分自身を壁の中に引き入れると視点がガクガク揺れるのが分かると思います。 (デスクトップモードでは身を入れられないので同じことを試せませんが、 代わりに壁を下に伝って床に体をめり込ませると jitter 現象自体は体験できます。)

Jitter は

1. プレハブの動作によってめり込み位置に移動する
2. プレイヤーのコライダとオブジェクトのコライダが衝突してプレイヤーが飛び出る

という動作を繰り返すために発生します。 (衝突の有無は Unityメニュー > Edit > ProjectSettings > Physics で確認できます。 https://docs.unity3d.com/ja/current/Manual/LayerBasedCollision.html

設定値

ここまでを把握すると ClimbingSetup コンポーネントの設定項目の意味がスムーズに理解出来るようになると思います。 以降、簡単に説明と注意点を書いてみたいと思います。(正確なところはプレハブ付属の readme.txt を参照してください)

f:id:naqtn:20190723062718p:plain

Climbing Enabled At Start

Climbing Enabled At Start はワールドに入った時からクライミング出来るようにする場合に有効にします。 開始を制御したい場合は無効にし、ClimbingSetup の並びに VRC_Trigger が在るので、これの "TurnOn" カスタムトリガを呼びます。 (並びにある "TurnOff" は動作停止、"ForceStopClimbing" は掴みの強制解除です)

f:id:naqtn:20190723062738p:plain

Climbable Layers

Climbable Layers は登れるレイヤーの指定です。 登れるオブジェクトのレイヤーはここで指定するいずれかに設定します。 また登れる条件として、オブジェクトは有効なコライダーを備えている必要があります。

  • 注1:コライダを無効化すると登れなくなくなります。これは動作時に切り替え可能です。無効化してもすでに掴んでいる手は保持されます。
  • 注2:コライダは IsTrigger 有効であっても構いません。この場合プレイヤーはすり抜けます。 デスクトップでは掴むところを表している球がオブジェクトにめり込むので、状況を把握しにくい事にはなります。
  • 注3:コライダは TerrainCollider でも動作します。地面も Tree も登れます。Tree に登れるようにするには:
    1. Tree に Capsule Collider を付けます。 (https://docs.unity3d.com/Manual/terrain-Trees.html)
    2. Enable Tree Colliders を有効にします。 (https://docs.unity3d.com/Manual/terrain-OtherSettings.html)

Climbing Hand Layer

Climbing Hand Layer は登る時に手に付ける球のレイヤーです。(この球は climbing orb と呼ばれています) 先に述べたようにプロジェクトで初めて使う場合に"Add Climbing Hand Layer"ボタンでレイヤーを追加します。以降はそれが表示されています。

(ClimbingSetup はこのレイヤー値に従って種々の設定を自動的に書き換えます。 ですので ProjectSettings で関係する値を書き換えてはいけません。)

Desktop Reach

Desktop Reach はデスクトップモードでの掴める場所までのプレイヤーからの限界距離です。 (多分視点位置からの距離。長くすると離れた所にびよーんと移動できて、ちょっと楽しい。 VRモードではアバター次第なので長い腕のアバターを用意していただければと。)

Enable Movable Object Settings

Enable Movable Object Settings は動くオブジェクトにプレイヤーを追従させる設定です。 設定しないと掴めるもののプレイヤーはその場にとどまります(空を掴んでいるように見えます)。 (オブジェクトを動かす方法は何でも構いません。物理計算、アニメーション、Standard Asset、いろいろあります動かし方)

動くオブジェクトかどうかを CyanClimbing に伝えるには GameObject に設定できる Tag を使います。典型的には

  1. "Create Default Moving Object Tag" ボタンを押す。「MovingClimbableObject」Tag がプロジェクト設定に追加される。
  2. 動くオブジェクトの Tag 選択を、この「MovingClimbableObject」にする
  3. "Setup Moving Climbable Objects" ボタンを押す

というように使います。動くオブジェクトを追加削除したら 2 と 3 を再び行います。

  • 注1:既に同じプロジェクトの別のシーンで操作をしてあれば 1 のステップは不要です。ボタンは表示されません
  • 注2:タグづけは動くオブジェクト個々に行わずに、祖先オブジェクトでひとまとめに行うこともできます。 (タグが該当するオブジェクトの子孫から、登れる設定になっているオブジェクトが拾われます)
  • 注3:この操作を行うと子オブジェクトとして MovingClimbDetector が追加されます。 またここにコライダがコピーされます。元のオブジェクトのコライダ設定を変更した場合には、反映するために再度 Setup します。
  • 注4:追加した MovingClimbDetector は CyanClimbing オブジェクトの中で把握しています。 このため CyanClimbing をシーンから削除したりプレハブの Revert をすると追跡できなくなり、 再セットアップした時に取り残されて(過剰に追加されて)しまいます。 こうなった場合は Hierarchy でオブジェクトの名前 MovingClimbDetector で検索し、全て削除した後に再度 Setup します。

Enable Swap Layers Settings

Enable Swap Layers Settings は先に述べたjitterを防ぐための設定です。 クライミング動作中にオブジェクトの Layer を PlayerLocal と衝突しない値に一時的に変更することで振動を防ぎます。 チェックボックスを有効にするとこの機能が働くようになります。

(ワールドの演出上(何かをクリアしないと次に行けないなど)通り抜けられてはいけないオブジェクトには、 適用してはいけないことに注意してください。)

Climbable Layers Swap

Climbable Layers Swap は登れる Layer についての swap 設定です。 Initial にはこの処理の対象にする Layer 、Final には一時的な変更先を指定します。 (Final には「衝突しない登れるレイヤー」を選んでください)

Nonclimbable Layers Swap

Nonclimbable Layers Swap は登れない Layer について前記と同様の事をします。 これは「そのオブジェクト自身は登れないけれども、登れるものが近くに在るために体をめりこませられてしまう場合」に有効にします。 (こちらの場合は Final には「衝突しない登れないレイヤー」を選んでください)

Setup Climbing Layer Swapping ボタン

それぞれの Layer を選択したら Setup のボタンを押します。 (MovingClimbDetector の所で述べたのと同様に)該当するオブジェクトを CyanClimbing オブジェクト内部で保持しているので、 対象となるオブジェクトを追加削除した場合には、適宜再度Setupを押す必要があります。

既知不具合(Version 1.0)

「Default」 layer を layer swapping で指定しないようにしてください。 そうすると手に付ける球(climbing orbs)を落としてしまう不具合が見つかったとのことです。