U#でプレイヤーをテレポートさせる

目次
１．準備
２．処理を書く
３．動作確認する
４．解説
５．少し改変

Udonの準備がまだだったり、一度もU#触ったことがないという方は是非こちらから・・・

https://qiita.com/sabamame_vrc/items/4e263d532162e4f915c0

https://qiita.com/sabamame_vrc/items/0252df9ca228743693c6

# １．準備

今回はプレイヤーを指定した場所、向きにテレポートさせるギミックをつくります。

### オブジェクトの配置
まずはいつも通り、`Plane`で床を、Projectウィンドウから`VRCWorld`プレハブを置きます。

次に今回のギミックに必要な、テレポート装置とテレポート先を配置します。
#### テレポート装置
Cubeを配置します。
高さを0.2、Y座標を0.1にして後は適当で良いです。
![TeleportSystemObj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/ceca2d7a-c050-4401-f7e3-546eb60fc2b3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/83a94e87-3b00-3656-7343-6602932d5de5.png)
ギミックであることが分かりやすいように、マテリアルの色を変えるよ良いです。

また、Cubeのインスペクターを開き、`BoxCollider`の`Is Trigger`を有効にしましょう。
![ColliderIsTrigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/0e758b43-4c10-cd1d-4876-667b4b97e9c2.png)

:::note
Is Triggerを有効にすると、プレイヤーとこのCubeが重なり合うようになります。
重なり合った時に、テレポート処理を行うようにします。
:::

分かりやすいように、オブジェクトの名前をCube→`TeleportSystem`などに変えておきましょう。

#### テレポート先
先ほどのCubeと同じように、`右クリ`→`CreateEmpty`でオブジェクトを配置します。
![EmptyObject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/2e26cc57-8b1c-e989-71f3-1f11b7cc0680.png)
これはTransformしか持たない __空のオブジェクト__ です。
このオブジェクトの先にテレポートするので、Cubeや初期スポーン地とは少し離しましょう。

同じくオブジェクト名を、`Destination`など分かりやすい名前に変えておきましょう。

### スクリプトの作成
今回のスクリプトは `TeleportSystem` などの名前で良いです。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/e1cc6e0b-a6a2-45fc-f446-0aaf87da7b0c.png)

# ２．テレポート処理を書く
いままでと同じくコピペで良いです。

```C#:TeleportSystem.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class TeleportSystem : UdonSharpBehaviour
{
    [SerializeField] private Transform _toTeleport = null;


    // プレイヤーが触れた時に実行
    public override void OnPlayerTriggerEnter(VRCPlayerApi player)
    {
        if (_toTeleport == null) {
            Debug.Log("テレポート先がアタッチされてません。");
            return;
        }

        // テレポートする
        player.TeleportTo(
            _toTeleport.position,   // 座標
            _toTeleport.rotation    // 向き
        );
    }
}
```
`Ctrl + S` で保存。絶対。

# ３．動作確認する

### スクリプトをアタッチする
いつも通り、オブジェクトにUdonをアタッチしていきます。
テレポート用のキューブに`Add Component`で`Udon Behaviour`を追加します。
追加したUdon Behaviour の `Program Source` に、`Teleport System`をアタッチします。
![UdonAtach.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/4f030a29-c7f3-59e2-eaa8-c9d6a5fa4a95.png)


### テレポート先（空オブジェクト）をアタッチする
アタッチした`Teleport System`に `To Teleport` という項目があるので、そこにテレポート先であるオブジェクト、`Destination`をアタッチします。
![ToTeleport.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/f61a3511-c4ee-6066-873d-0c5236f4b9eb.png)

これで準備完了です。

### 実行
再生ボタンを押して確認してみましょう。
青いオブジェクトに触れると、`Destination`と同じ場所・同じ向きにテレポートしているはずです。

:::note warn
触れてもテレポートしないが、以下のようなログが出る人は、`Destination`のアタッチができていないと思います。
先ほどの手順を確認してみましょう。
![DebugLog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/41644915-1e27-b29a-24e4-9d00e77c5639.png)
:::

# ４．解説
### OnPlayerTriggerEnter
```C#
    // プレイヤーが触れた時に実行
    public override void OnPlayerTriggerEnter(VRCPlayerApi player)
    {
        ...
    }
```
OnPlayerTriggerEnter()は、プレイヤーがこのオブジェクトに触れた時に実行されます。

:::note
オブジェクトの IsTrigger がオンになっていないと実行されません。
:::

()の中にある `player` には、オブジェクトに触れたプレイヤーの情報が詰まっていたり、そのプレイヤーに指示を与えたりすることができる関数が入っています。

### player.TeleportTo()
```C#
        // テレポートする
        player.TeleportTo(
            _toTeleport.position,   // 座標
            _toTeleport.rotation    // 向き
        );
```
TeleportTo()の中に、座標・向きの２つの情報を入れてあげることで、そのプレイヤーをテレポートさせることができます。
今回は、_toTeleportの座標と向きを入れてあげているので、そのオブジェクトと同じ座標と向きにテレポートしています。

# ５．少し改変

### プレイヤーの向きを反映させる
player には、オブジェクトに触れたプレイヤーの情報が入っていると言いました。
そこで、player.TeleportTo()の中身を以下のように変えてみましょう。
```C#
        // テレポートする
        player.TeleportTo(
            _toTeleport.position,   
            player.GetRotation()    // ←ここが変わった
        );
```
player.GetRotation()で、プレイヤーの向きを取得することができます。

この書き方をすると、_toTeleport の向きではなくプレイヤーの向きを変えずにテレポートさせることができます。

ギミックの目的によってどちらにするか決めましょう。