VRChatワールド作成メモ【VRC_Trigger編】

# VRChat個人的メモ

つい先日VRChatデビューを果たし、もっとこういうことができるようになればいいのに
→自分でワールド作っちゃえばいいんじゃね？
という思想からワールド作成してみようとなったので
VRChatのお作法を調べてわかったことをメモがてら書いていきます。
試せてない部分もあって予測で書いている部分もあるので、皆さん自身で試してみてください。
実験してわかったものは追記予定です。

## 本記事の対象者

・VRChatでワールド内にギミックを仕込みたい方
・ある程度Unityの操作に慣れている方

## 環境
- Unity2018.4.20f1
- VRCSDK2(v2020.1.1)

## 本記事の概要

VRChatのワールドを作る上で様々なギミックを動かすために
一番よく使うであろうVRC_Triggerについて書きます。
VRC_Triggerを使えば、「ボタンを押したら花火が上がる」みたいなことが可能になります。

## 参考
公式ドキュメント↓
[Triggers](https://docs.vrchat.com/docs/trigger-triggers)

日本語で書いてくれている記事↓
[VRchat 日本wiki](https://vrchatjp.playing.wiki/)
[VRC_Trigger - VRChat 技術メモ帳 - VRChat tech notes](https://vrcworld.wiki.fc2.com/wiki/VRC_Trigger)

## VRC_Triggerとは
VRChatのワールド内で、様々な動作の起点となるコンポーネントです。
「使うボタンを押したとき」や「アバター(プレイヤーのキャラクター)がオブジェクトに触れたとき」などのタイミングで特定の処理を実行することができます。

上記の「使うボタンを押したとき」などはVRC_Triggerではトリガーという括りになっています。
まずはそのトリガーの種類を羅列します。

## トリガー

### トリガーとは
特定の条件で発火する起点となるものです。

![VRC_Trigger_Actions.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212329/e66ae6cb-b222-a2be-9a6c-345bca514677.png)

**記述規則**
  
- **トリガー名**  
	- パラメータ名(型)：説明  
	- ︙

**共通しているパラメータ**  
※基本は以下パラメータが設定できますが、一部設定できないトリガーもあります。

- Delay in Seconds(float)：トリガーが発火してからアクションを実行するまでの時間(秒)。
- Actions(List<Action>)：トリガーが発火たときに実行するアクションリスト。
	- Receivers：Actionsのいずれかを選んだときに表示される。選んだトリガーが発火したときにどのコンポーネントにどんな値を設定するかなどを設定する。  
例:AnimationBool:Animatorの指定した変数を指定した値に変更する。

### トリガー一覧

- **Custom(Unnamed)**
	- Name(string)：トリガー名。他のイベントから発火させるときに識別するのに使用する。  

参考記事
[Custom Trigger - Programming in VRChat](http://vrcprog.hatenablog.jp/entry/trigger-custom)
上記参考記事を読んでみるとCustomTriggerはActiveCustomTriggerというアクションで発火させるらしい。
他のトリガーを介して呼び出す形になるようです。これは応用で使いそうです。  

- **Relay**
	- Targets(VRC_Trigger)：トリガーを発火させる他のVRC_Trigger  

Relayが存在するVRC_Triggerの別のトリガーのいずれか(TriggerAとする)が発火したとき、
Relayも発火します。
発火したときに指定した別のVRC_TriggerのTriggerAを発火させることができる。  

- **OnEnable**
オブジェクトが有効(SetActive(true)やワールド生成時？)になったときに発火する。  

- **OnDestroy**
オブジェクトが破棄(Destroy)されたときに発火。  

- **OnSpawn**
オブジェクトが生成されたときに発火。  

- **OnNetworkReady**
プレイヤーがルームに完全に入った(おそらくアバターが表示されてプレイヤーの入力を受けつけられる状態になった)ときに発火。
入室時の演出とかができそう？入室したユーザーにだけ反応しそう  

- **OnPlayerJoined**
プレイヤーが入室したときに発火。OnNetworkReadyと違い、すでに入室しているプレイヤーにもイベントが発火しそう  

- **OnPlayerLeft**
プレイヤーが退室したときに発火。  

- **OnPickupUseDown**
	- Interaction Text(string)：使える状態のときに表示する文字列
	- Proximity(float)：有効な距離(PickUpしているので意味があるか不明)  

VRC_PickupでPickupしている状態でUseボタンを押したときに発火。
ペンを持ち、使うボタンを押したときに書くなどで使用。
Downという名前がややこしいが、ボタンが押された(押し下がった)という解釈をするとよい。  

- **OnPickupUseUp**
	- Interaction Text(string)：使える状態のときに表示する文字列
	- Proximity(float)：有効な距離(PickUpしているので意味があるか不明)  

VRC_PickupでPickupしている状態でUseボタンを離したときに発火。
ペンを持ち、使うボタンを押したときに書くなどで使用。
Upという名前がややこしいが、ボタンを離したという解釈をするとよい。  

- **OnTimer**
	- Repeat(bool)：繰り返しの有無。trueでタイマーをリセットし、何度もアクションを実行する。
	- ResetOnEnable(bool)：このコンポーネントがアタッチされているオブジェクトがEnableになったタイミングでタイマーをリセット
	- LowPeriodTime(float)：タイマーの最短期間
	- HighPeriodTime(float)：タイマーの最長期間

このOnTimerはLowPeriodTime~HighPeriodTimeの間でランダムな時間にアクションが実行されます。
ランダムが嫌な場合はLowとHigh両方同じ値にすると良いでしょう。  

- **OnEnterTrigger**
	- Trigger Individuals(bool)：trueの場合、オブジェクトが範囲内に入ったときいつでも発火します。  
falseの場合、すでに別のオブジェクトが範囲内に入っていた場合は発火しません。  
	- Layers(enum(Flag))：Triggerが有効になるオブジェクトのレイヤーを指定。 

Triggerを持つVRC_TriggerがColliderを持ち、ColliderのisTriggerがtrueの場合に、
他のisTriggerがオンになっているColliderが触れると発火します。  

- **OnExitTrigger**
	- Trigger Individuals(bool)：trueの場合、オブジェクトが範囲外に出たときいつでも発火します。falseの場合、別のオブジェクトが範囲内に入っていた場合は発火しません。  
	- Layers(enum(Flag))：Triggerが有効になるオブジェクトのレイヤーを指定。 

Triggerを持つVRC_TriggerがColliderを持ち、ColliderのisTriggerにチェックが入っている場合に、他のisTriggerがオンになっているColliderが触れた後に範囲外に出ると発火します。  

- **OnKeyDown**
	- Key(UnityEngine.KeyCode)：反応するキー(ゲームパッドのキーも反応可能)  

キーボードのキーを押したときに発火する。  

- **OnKeyUp**
	- Key(UnityEngine.KeyCode)：反応するキー(ゲームパッドのキーも反応可能)  

キーボードのキーを離したときに発火する。  

- **OnPickUp**
	- Interaction Text(string)：拾える状態のときに表示する文字列
	- Proximity(float)：有効な距離

同オブジェクトのVRC_PickupでPickupされると発火する。  

- **OnDrop**
	- Interaction Text(string)：離した状態のときに表示する文字列
	- Proximity(float)：有効な距離  

同オブジェクトのVRC_PickupでPickupされていたオブジェクトが離されると発火する。  

- **OnInteract**
	- Interaction Text(string)：使える状態のときに表示する文字列
	- Proximity(float)：有効な距離  

プレイヤーが有効範囲内にいて、使用ボタンを押すと発火する。
PickupUseと違い、拾わない状態で使うものに使用する。  

- **OnEnterCollider**
	- Trigger Individuals(bool)：trueの場合、オブジェクトが範囲外に出たときいつでも発火します。  
falseの場合、別のオブジェクトが範囲内に入っていた場合は発火しません。  
	- Layers(enum(Flag))：Triggerが有効になるオブジェクトのレイヤーを指定。  

TriggerではなくCollider(物理的な当たり判定)が当たったときに発火する。
プレイヤー(PlayerLayer)が当たっても発火しないので、
プレイヤーが当たったのを判定したい場合はOnAvaterHitを使用しましょう。  

- **OnExitCollider**
	- Trigger Individuals(bool)：trueの場合、オブジェクトが範囲外に出たときいつでも発火します。falseの場合、別のオブジェクトが範囲内に入っていた場合は発火しません。  
	- Layers(enum(Flag))：Triggerが有効になるオブジェクトのレイヤーを指定。  
  
TriggerではなくCollider(物理的な当たり判定)が離れたときに発火する。
プレイヤー(PlayerLayer)では発火しないので、
プレイヤーを判定したい場合はOnAvaterHitを使用しましょう。  
↑と公式に書いてありますが、OnAvaterExitはないんですよね。

- **OnDataStorageChange**
	- Data Element(enum(VRC_DataStorage内のDataにある値名))：監視するデータを選択

VRC_DataStorageコンポーネントを同じオブジェクトに追加する必要がある。
そのVRC_DataStorage内で宣言されているデータを監視して変更があったときに発火する。  

- **OnAvatarHit**
プレイヤー(Avatar)がColliderに当たったら発火する。

- **OnVideoStart**
※公式に解説なし
おそらくVRC_VideoPlayerでビデオが開始されたときに発火する。

- **OnVideoEnd**
※公式に解説なし
おそらくVRC_VideoPlayerでビデオが停止したときに発火する。

- **OnVideoPlay**
※公式に解説なし
おそらくVRC_VideoPlayerで再生されたときに発火する。

- **OnVideoPause**
※公式に解説なし
おそらくVRC_VideoPlayerで一時停止されたときに発火する。

- **OnDisable**
オブジェクトが無効(SetActive(true)やワールド生成時？)になったときに発火する。

- **OnOwnershipTransfer**
オブジェクトのオーナーが変更されたときに発火する。  

- **OnParticleCollision**
※公式に解説なし
おそらくパーティクルの当たり判定に入ったときに発火する。
OnCollisionのパーティクル用版かと。

## アクション

### アクションとは
トリガーが発火したときに行う処理のこと。

**Basic Events**
![VRC_Action_BasicEvents.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212329/22b9da0a-0a82-b8b9-3ef2-67e73eb23ea9.png)

**Events from Scene**
![VRC_Action_EventsFromScene.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212329/83a649df-3a2e-e4de-e48b-a3247edff87f.png)

**記述規則**
  
- **アクション名**  
	- パラメータ名(型)：説明  
	- ︙

**共通しているパラメータ**  

- Receives(型)：アクションを受け取るコンポーネントを指定する。指定するコンポーネントの種類はアクションにより異なる。

#### Basic Events
- **ActiveCustomTrigger**
	- Receives(VRC_Trigger)：
	- Name(string)：呼び出すカスタムトリガー名(自分で指定している名前)

- **AddAngularVelocity**
	- Receives(Rigidbody)：角速度を加えるRigidbody
	- AngularVelocity(Vector3)：加える角速度の強さ
	- UseWorldSpace(bool)：加える角速度の向きが絶対方向(true)か相対方向か(false)

※公式に解説なし
角速度を与える。

- **AddDamage**
	- Receives(GameObject)：ダメージを与えるゲームオブジェクト
	- Damage(float)：与えるダメージ量

- **AddForce**
	- Receives(Rigidbody)：力を加えるRigidbody
	- Force(Vector3)：加える力の強さ
	- UseWorldSpace(bool)：加える力の向きが絶対方向(true)か相対方向か(false)

※公式に解説なし
物体に力をかける。
AddVelocityとは違い、重さなども計算されて物体を動かす。

- **AddHealth**
	- Receives(GameObject)：回復させるゲームオブジェクト
	- Health(float)：回復量

- **AddVelocity**
	- Receives(Rigidbody)：加速度を加えるRigidbody
	- AngularVelocity(Vector3)：加える加速度の強さ
	- UseWorldSpace(bool)：加える加速度の向きが絶対方向(true)か相対方向か(false)

※公式に解説なし
こちらは加速度を与えるアクションです。
重さなどは加味せず、加速度がそのまま加えられる。

- **AnimationBool**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(enum(true, false, toggle))：どれをセットするか

- **AnimationFloat**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(float)：セットする値

- **AnimationInt**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(int)：セットする値

※公式に解説なし

- **AnimationIntAdd**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(int)：加える値

※公式に解説なし

- **AnimationIntDivide**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(float)：割る数の値

※公式に解説なし

- **AnimationIntMultiply**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(float)：掛ける数の値

※公式に解説なし

- **AnimationIntSubtract**
	- Receives(Animator)：Animatorコンポーネント
	- Variable(string)：セットする値の名前
	- Operation(float)：引く数の値

※公式に解説なし

- **AnimationTrigger**
	- Receives(Animator)：Animatorコンポーネント
	- Trigger(string)：セットする値の名前

- **AudioTrigger**
	- Receives(AudioSource)：音声を再生するAudioSource
	- Clip(enum)：再生する音声

- **CallUdonMethod**

※公式に解説なし
※Unsupported event type

- **DestroyObject**
	- Receives(GameObject)：削除するゲームオブジェクト

- **PlayAnimation**
	- Receives(Animation)：再生されるアニメーションコンポーネント
	- Clip(string)：再生するアニメーションクリップ

- **SendRPC**
	- Receives(GameObject)：実行されるGameObject
	- Targets(enum)：対象となるプレイヤーの種類

- **SetAndularVelocity**
	- Receives(Rigidbody)：角速度をセットするRigidbody
	- AngularVelocity(Vector3)：角速度
	- UseWorldSpace(bool)：加える角速度の向きが絶対方向(true)か相対方向か(false)

※公式に解説なし

- **SetComponentActive**
	- Receives(GameObject)：対象のGameObject
	- Component(enum(MonoBehaviour))：対象GameObjectにアタッチされてるコンポーネント
	- Enable(enum(true, false, toggle))：セットするコンポーネントの状態

- **SetGameObjectActive**
	- Receives(GameObject)：対象のGameObject
	- Enable(enum(true, false, toggle))：セットするコンポーネントの状態

- **SetLayer**
	- Receives(GameObject)：対象のGameObject
	- Layer(enum)：セットするLayer

- **SetMaterial**
	- Receives(GameObject)：対象のGameObject
	- Material(Material)：セットするマテリアルアセット

- **SetParticlePlaying**
	- Receives(GameObject)：対象のGameObject
	- Operation(enum(true, false, toggle))：セットするコンポーネントの状態

- **SetUIText**
	- Receives(Text)：対象のテキスト
	- Text(string)：セットする文字列

※公式に解説なし

- **SetVelocity**
	- Receives(Rigidbody)：加速度をセットするRigidbody
	- AngularVelocity(Vector3)：セットする加速度
	- UseWorldSpace(bool)：セットする加速度の向きが絶対方向(true)か相対方向か(false)

- **SetWebPanelURI**
	- Receives(VRC_WebPanel)：対象のVRC_WebPanel
	- URI(string)：閲覧するURI文字列

- **SetWebPanelVolume**
	- Receives(VRC_WebPanel)：対象のVRC_WebPanel
	- Volume(float(Slider))：音量0~1

- **SpawnObject**
	- Prefab(GameObject)：生成するGameObjectプレハブ
	- Locations(Transform)：生成する位置

- **TeleportPlayer**
	- Receives(GameObject)：プレイヤーの移動先


### Events from Scene
VRC_ObjectSyncを持つオブジェクトがシーン上にあるときのみ有効。
というのも、SendRPC経由でGameObjectを対象に各アクションが行われるため。

- **EnableKinematic**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：CustomMethod(固定でよい)
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
RigidbodyのIsKinematicがオンになるかと思われる。

- **DisableKinematic**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：CustomMethod(固定でよい)
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
RigidbodyのIsKinematicがオフになるかと思われる。

- **EnableGravity**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：CustomMethod(固定でよい)
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
RigidbodyのUseGravityがオンになると思われる。

- **DisableGravity**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：CustomMethod(固定でよい)
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
RigidbodyのUseGravityがオフになると思われる。

- **ReapObject**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：CustomMethod(固定でよい)
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
Reap=刈り取る？
謎である。

- **TakeOwnership**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：VRC_ObjectSync.TakeOwnership
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
オブジェクトの所有権を取得する。

- **TeleportTo**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：VRC_ObjectSync.TeleportTo
	- Targets(enum)：対象となるプレイヤーの種類
	- targetLocation(Transform)：テレポート先

※公式に解説なし
指定したテレポート先にテレポートする。

- **Respawn**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：VRC_ObjectSync.Respawn
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
オブジェクトをスポーンさせる。
複製か元あった場所に移動するだけかは不明。

- **FlagDiscontinuity**
	- Receives(GameObject)：実行されるGameObject
	- Method(enum(実行する関数))：VRC_ObjectSync.FlagDiscontinuity
	- CustomMethod(string)：実行する関数名(アクション名がデフォルトで入る)
	- Targets(enum)：対象となるプレイヤーの種類

※公式に解説なし
謎。