Worldでのギミック：一定時間後に何かを有効にするギミック(3種類)

一定時間経過してからワールドの何かを操作したい場合などの処理方法です。
# SendCustomEventDelayedSecondsを使用する場合
**SendCustomEventDelayedSeconds(nameof(メソッド名),秒数)**
で、「メソッド名」の処理を「秒数」後に実行できます。
これからスクリプトを書いていきますが、**U#のスクリプトの作成方法は前々回の記事あたりを参考に作成**してください。
ファイル名は「seconds.cs」とでもしておきましょう。
**(ファイル名を変えると微妙にスクリプトも変わるので慣れない人はこの名前で作成してください)**
~~~C#
    using UdonSharp;
    using UnityEngine;
    using VRC.SDKBase;
    using VRC.Udon;

    public class seconds : UdonSharpBehaviour
    {
        void Start()
        {
            SendCustomEventDelayedSeconds(nameof(Sample), 5);
        }
        public void Sample()
        {
            this.gameObject.transform.localScale = new Vector3(2, 2, 2);
        }
    }
~~~
ファイル名が一緒の人は全部コピペで大丈夫です。
このスクリプトをつけたオブジェクトがアクティブになった10秒後に、`Sample`という処理を実行します。
`Sample`という処理は、このスクリプトをつけたオブジェクトのサイズを2倍にします。

わかりにくい書き方をしましたが、**ワールドに入って10秒経ったらこのオブジェクトが2倍の大きさになるよということです。**

実際にこのスクリプトの動作を確認してみましょう。

![VC6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708808/be6707f3-c2b3-7ab2-63d5-c812aa44973f.png)

1. Cubeを作成する
1. Cubeをクリックして選択し、Transform(右上)の値を画像の値にする。(しなくてもいいです、どうなるかやってみてもOK)
1. 右側ウィンドウの一番下より、Add Componentをクリックして検索欄にudonと入力し、
候補に出てきた「Udon Behaviour」を追加する。
1. 追加した「Udon Behaviour」の「Program source」に、赤枠で囲んだseconds.assetをドラッグ＆ドロップする。

では、上部の再生ボタンを押して動作を確認してみましょう。

![VCC_Test-s-PC_-Mac-_-Linux-Standalone-Unity-2019.4.31f1-Personal_-_DX11_-2023-02-21-20-58-11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708808/ab09ba15-fbb0-c853-fef4-97c49dacafa4.gif)

## SendCustomEventDelayedSecondsの長所と短所
長所　指定秒数後の処理が簡単に行える点。
短所　途中で処理を止めることが出来ない点。

短所の部分も対象のメソッドに条件式組み込んだらどうにかできなくはないですけどね。

# Updateとint型の変数を使ってゴリ押しする方法
数値を加算または減算などで変化させていき、閾値に達したら条件式で処理を行うという方法です。
同じようにスクリプトを書いていきましょう。先程作成した**seconds.cs**をそのまま使います。
~~~C#
    using UdonSharp;
    using UnityEngine;
    using VRC.SDKBase;
    using VRC.Udon;

    public class seconds : UdonSharpBehaviour
    {
        private int count = 1000;
        private bool changed = false;
        void Start()
        {
            SendCustomEventDelayedSeconds(nameof(sample), 10);
        }
        public void sample()
        {
            this.gameObject.transform.localScale = new Vector3(2, 2, 2);
        }
        void Update()
        {
            if (count == 0 && !changed)
            {
                this.gameObject.transform.localScale = new Vector3(5,5,5);
                changed = true;
            }
            if (count > 0)
            {
                count--;
            }
        }
    }
~~~
面倒な方は全部消して上のコードをコピペでOKです。

`void start()`の前に、以下のコードを追加しました。

        private int count = 1000;
        private bool changed = false;

また、以下のメソッドUpdateが追加されました。

        void Update()
        {
            if (count == 0 && !changed)
            {
                this.gameObject.transform.localScale = new Vector3(5,5,5);
                changed = true;
            }
            if (count > 0)
            {
                count--;
            }
        }


`if (count == 0 && !changed)`
`count`の値が0で且つ、変数`changed`の値が**Trueで無いなら**次の処理へ進みます。(!は否定演算子)  

`this.gameObject.transform.localScale = new Vector3(5,5,5);`
上の**SendCustomEventDelayedSeconds**でやった部分。今度はサイズをもとの5倍にします。
`changed = true;`
今回はつけなくてもいいけどつけないと無限に処理が行われるので重くなります。場合によってはとんでもないことになります。
ここで変数`changed`の値をTrueにしているので、上の条件に当てはまらなくなり、処理を一度だけ行わせることが出来ます。

            if (count > 0)
            {
                count--;
            }
`count`が0より大きいなら1減らす。

では保存したら実行してみましょう。
スクリプトを書き直しましたが、そのまま実行可能です。

![VCC_Test-s-PC_-Mac-_-Linux-Standalone-Unity-2019.4.31f1-Personal_-_DX11_-2023-02-21-21-40-11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708808/e8cbbf15-8d60-6972-e642-334c97daf73a.gif)

10秒後にサイズがもとの2倍になり、そのあとにさらに大きくなっているのが確認できますね。

## Updateとint型変数で処理する場合の長所と短所
長所　秒数の増減を恣意的に、個別に行うことができるため応用が可能。
短所　条件式が間違っていると処理が重くなる。
　　　条件が煩雑になるのでデバッグが面倒。

**条件が煩雑になりそうなときは別のメソッドを作成してそちらに処理を分けましょう。**

# 現在時刻から逆算する方法

現在時刻を取得して、そこに指定の秒数を加算して実行する方法です。

    using UdonSharp;
    using UnityEngine;
    using VRC.SDKBase;
    using VRC.Udon;
    using System;

    public class seconds : UdonSharpBehaviour
    {
        private int count = 1000;
        private bool changed = false;
        
        private string str1;
        private DateTime dt1;
        private bool modified=false;

        void Start()
        {
            dt1 = DateTime.Now;
            dt1 = dt1.AddSeconds(20);
            str1 = dt1.ToString();
            SendCustomEventDelayedSeconds(nameof(Sample), 10);
        }
        public void Sample()
        {
            this.gameObject.transform.localScale = new Vector3(2, 2, 2);
        }
        void Update()
            {
            dt1 = DateTime.Now;
            if (count == 0 && !changed)
            {
                this.gameObject.transform.localScale = new Vector3(5,5,5);
                changed = true;
            }
            if (count > 0)
            {
                count--;
            }

            if(str1 == dt1.ToString()&&!modified)
            {
                this.gameObject.transform.localScale = Vector3.one;
                modified = true;
            }
        }
    }


軽く解説を入れます。

        using System;

DateTime関数(現在時刻などにつかうもの)を使用する場合は一番上にこれを記載しておいてください。
書かないと動きません。

        private string str1;
        private DateTime dt1;
        private bool modified=false;

文字列を取得するための文字列型の変数`str1`、
日付を取得するためのDateTime型の変数`dt1`、
処理が一度だけ行われるようにするためのBool型の変数`modified`
を宣言します。

        dt1 = DateTime.Now;
        dt1 = dt1.AddSeconds(20);
        str1 = dt1.ToString();

1. 現在時刻を取得する
1. 取得した現在時刻に20秒加算する
1. 加算した後の時刻を文字列にして、str1に保存する


            dt1 = DateTime.Now;

Updateメソッドの中でもう一度呼びます。
dt1の中身を現在時刻で上書きします。


        if(str1 == dt1.ToString()&&!modified)
            {
                this.gameObject.transform.localScale = Vector3.one;
                modified = true;
            }


20秒後の時間の文字列と現在時刻の文字列が一致してて、`modified`がtrueでないならば
このオブジェクトのサイズをもとのサイズにして、`modified`をtrueにする。

`Vector3.one`は`New Vector3(1,1,1)`と一緒です。

追加した文章の意味はそれぞれそんな感じです。
では、動かしてみましょう。
スクリプトは更新されていますが、今回も特に何もしなくても起動します。

![VCC_Test-s-PC_-Mac-_-Linux-Standalone-Unity-2019.4.31f1-Personal_-_DX11_-2023-02-21-21-40-11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708808/b0a6dfbf-f341-b0fd-9af7-491a441ec6ee.gif)

無事に動いていますね！

## 現在時刻から逆算する方法の長所と短所
長所　1時間などの長時間を加算するのが楽、時刻でのいろいろな処理が可能
短所　コードがめんどくさい


今回は一定時間後に何らかの処理をする方法を3種類記載しました。
次回もギミック系の記事を書いていきたいと思います。
(見づらいので後で修正すると思います)

※メソッド→method,処理を書いた部分。`void`とか`public void`で始まってる部分。