U＃でオブジェクトを動かす

目次
１．スクリプトを作成する
２．オブジェクトが回転する処理を書く
３．動作確認する
４．解説
５．ちょっとスクリプトを改変する
？．おまけ（deltaTimeについて）

VCCバージョン2.1.3、Unityバージョン2019.4時の状況で解説してます。
VCCの大規模アプデやSDK3→SDK4とかにならない限り大して変わらないと思います。
大きな変更あったら書き直します。

Udon Sharpの準備がまだの人は下記の記事を参考に下準備をしてみてください。
常日頃アバター改変をしている皆さんなら数分でできると思います。（分からない箇所あったらコメントしてください。気づいたら返します。）

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

# １．スクリプトを作成する

Projectウィンドウで`右クリック`→`Create`→`U# Script`を選択してください。
![U#Create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/4863cfa3-1d5f-4ec3-7308-6eeac80bf473.png)
エクスプローラーが開きます。今回はファイル名は`MoveObject`にしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/d2fd2489-795a-f4bd-c4e6-acba5bec5f36.png)
保存を押して数秒待つとProjectウィンドウの中に`MoveObject`という名前のファイルが２つ作成されていたらOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/b2165f9a-bc43-665f-e328-2356f9c94b47.png)

# ２．オブジェクトが回転する処理を書く
２つある内、下の方の`MoveObject`をダブルクリックで開きます。

中身はこうなっているはずです。
```C#:MoveObject.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class MoveObject : UdonSharpBehaviour
{
    void Start()
    {
        
    }
}
```
ここにオブジェクトを回転させる処理をぶち込んでいきます。
コピペで構いません。解説は後程。
```C#:MoveObject.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class MoveObject : UdonSharpBehaviour
{
    // 最初の一回だけ実行される
    void Start()
    {
        
    }
    
    // 毎フレーム実行される
    private void Update()
    {
        // このオブジェクトをY軸回転させる
        this.gameObject.transform.Rotate(0, 1, 0);
    }
}
```
書き終わったら、`Ctrl + Sキー`で内容を保存しましょう。絶対です。癖付けてください。

保存がおわったらUnityに戻ります。
数秒間硬直しますが問題ないです。待ちましょう。

# ３．動作確認する
### 回転させるオブジェクトを設置する
ヒエラルキーで`右クリック`→`3D Object`→`Cube`でキューブを設置しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/0ccdfe27-7ca5-dd63-1b10-03361726ae83.png)

### 書いた処理をキューブに反映させる
`Cube`を選択してインスペクターを確認します。
![AddComponent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/0fbf8f75-5a4b-94b9-be2d-f978439c72f0.png)
画像の赤枠で囲っている、`Add Component`を押して、検索欄に`Udon`と入れると`Udon Behaviuor`が出てくるので選択しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/887d9f67-d9b3-a238-a9a8-a7fb4a10df1c.png)
Cubeのインスペクターに`Udon Behaviour (Script)`が追加されました。
Projectウィンドウにあるもう一つの`MoveObject`を、`Udon Behaviour`の`Program Source`にドラッグ＆ドロップでアタッチしましょう。
![ScriptAtach.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884829/e84e86b3-6e24-6105-200e-2a245b8bafbe.png)
再生ボタンを押すと、キューブがY軸で回転し続けることが確認できると思います。

# ４．解説
コピペした内容を簡単に説明にしたいと思います。
```C#
    // 毎フレーム実行される
    private void Update()
    {
        // このオブジェクトをY軸回転させる
        this.gameObject.transform.Rotate(0, 1, 0);
    }
```
Update()の下にある{}内に書かれた内容は、毎フレーム実行されます。
transform.Rotate()は、X,Y,Z軸によりそのオブジェクトを回転させることができます。
つまり、Z軸で回転させたければ
```C#
    // このオブジェクトをZ軸回転させる
    this.gameObject.transform.Rotate(0, 0, 1);
```

逆回転させたかったらマイナスの値を入れます。
```C#
    // このオブジェクトをZ軸回転させる
    this.gameObject.transform.Rotate(0, 0, -1);
```

ちなみに、Rotate()はローカル軸を使って回転します。
ワールド軸で回転させたい人は「Unity Transform Rotate World軸」とかで検索かけてください。

transformには回転だけじゃなく移動できる関数もあります。
次の項目で追加してみます。

# ５．ちょっとスクリプトを改変する
### 回転に合わせて前進させる
追加するコードは１行です。
```C#
    // 毎フレーム実行される
    private void Update()
    {
        // このオブジェクトをY軸回転させる
        this.gameObject.transform.Rotate(0, 1, 0);

        // このオブジェクトを前進させる
        this.gameObject.transform.Translate(0, 0, 0.1f);
    }
```
:::note
小数点以下が含まれる値を入れる時は、値の最後に`f`を入れます。
この値がfloat型であることをPCに教えてあげる必要がある為です。
詳しい説明は難しいので省きますが、どうしても気になる人は「float double 違い」などで検索してみてください。
:::

Rotateと同じくTranslateもローカル軸で動くので、ちゃんと動けば 回転→前進→回転→前進→...と繰り返します。
コピペができたら、`Ctrl + S`で保存してUnityに戻りましょう。癖付けてください。
実行してキューブが床の上をグルグルと回っていればOKです！

動かすオブジェクトを増やしたり、値を入れ替えてみたりして遊んでみてください。
今回の内容がもっと気になる人は、「Unity Transform」とかで検索したら収穫があるかも。

# ？．おまけ
### Time.deltaTime
「４．解説」で、Update()の内容は`毎フレーム`実行されると説明しました。
つまりVRC上で、60F出ているプレイヤーと30Fしか出ていないプレイヤーではUpdate()の実行数が違うので、オブジェクトの動くスピードに倍近くの差がうまれます。
これはあまりよろしくないです。

以下のような書き方をすることで、FPSに差があっても同じような動きをさせることができます。
```C#
        // このオブジェクトをY軸回転させる
        this.gameObject.transform.Rotate(0, 1 * Time.deltaTime, 0);

        // このオブジェクトを前進させる
        this.gameObject.transform.Translate(0, 0, 0.1f * Time.deltaTime);
```
:::note warn
このままコピペして実行すると、さきほどと比べてオブジェクトの動きがゆっっくりになりますが正常です。
:::

数字とTime.deltatimeの間にある`*`は掛け算を表しています。
角度と何かの時間を掛けた結果でオブジェクトを動かしています。

では`Time.deltaTime`とは何の時間かというと、**前のフレームから今のフレームまでにかかった時間**です。
FPSが低いほど、前のフレームから今のフレームまでにかかった時間は大きくなっていくので、その時間で計算してあげればFPSによる動作の違いを埋めることができます。