20200208のUnityに関する記事は8件です。

Unity個人的な覚書

・versionは2018.4.16f1
・UIメニューはPanelオブジェクトを作成して、その下にUIオブジェクトを配置する
・Reference Resolution 1125*2001 or 1920*1080
・Canvasの[Canvas Scaler] > [Scale With Screen Size] > [Expand]

縦横フリースタイルで遊ぶ、スマホゲームの振り返り
https://www.slideshare.net/masayahamazaki/ss-91315339

CanvasにUIが表示されなくなったときの
チェックすべき13のポイント
http://kimama-up.net/unity-ui-non-display/

【Unity】Sceneビューで表示されるGameObjectがGameビューで表示されない時の対処法
https://redfreshet.com/2015/09/09/unity_sceneview_gameview_invisible/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】ARKit2で3Dマーカー認識をする際、出現させるオブジェクトを自由に配置したい時

下記の記事を読みながら、3Dマーカーに合わせてオブジェクトを発生させようとしたけれど、オブジェクト自体の座標やGameObjectの座標を変えても発生する場所が全く変わらなかった。

http://nn-hokuson.hatenablog.com/entry/2018/09/19/205354

どうやら、GameObjectやオブジェクト自体に設定されたパラメータに関係なく、マーカーに対して敷かれた座標系における原点に配置されるらしい。

そのため、ダミーとなるゲームオブジェクトを設定し、その中に発生させたいオブジェクトを配置するといい。
スクリーンショット 2020-02-08 21.16.03.png

ゲームオブジェクトを原点に設定し、そこから相対的に座標を指定すれば、オブジェクトを自由に配置できる。

スクリーンショット 2020-02-08 21.16.38.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】LESSON01.セリフの文字を一つひとつ表示させていって簡単にRPGチックにしちゃおう!【★★★✩✩】

入力した文字列をRPGのセリフ表示っぽくしよう

「UnderTale」や「ゼルダの伝説」のセリフって文字が一文字一文字テキストボックスに追加されて行きますよね?それを出来るだけ簡単に実装して行きます!

まずはUnityでやること

CanvasにTextを追加しよう

まずは文字を表示させる為にGameObject→UI→Textの順番でクリックしていき「Text」を出しましょう!01.png

▼Canvas
Text
↑みたいになります!

文字の大きさや、表示させたい位置を自分の好きな所に設定してね!

Textにスクリプトをアタッチしよう!

最初は「New Text」となってるはずなのでこれを変えます!Textに表示されてる文字列を変えるためのスクリプトの準備をします!

Projectのウィンドウで右クリック→Create→C# Scriptの順番に操作します!
02.png

そうするとスクリプトが生成されます。そのスクリプトに適当な名前をつけます。今回は「TextDisplay」としましょう!(Displayは表示という意味)

03.png

そうしたらTextDisplayスクリプトをTextにアタッチします。下の画像のどっちの操作でもアタッチできるので、好きな方のアタッチの方法でやってください!

アタッチ方法①
04.png

アタッチ方法②
05.png

(アタッチ方法①,②のどちらかやればいいよ!)

結果的に下の画像のように表示されたらオッケーです!
06.png

つぎはプログラミングの作業

では、TextDisplayスクリプトを開いてプログラミングの作業を始めます!ひとつひとつの機能を一緒に理解しながら作って行きましょう。
【注意!】プログラムに「 // 」←がついている行が新しい行です。その行を追加していってくださいね!

スクリプトから文字を手動で変える

まずは簡単な方法で文字を変えます。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//←これを追加

public class TextDisplay : MonoBehaviour
{
    void Start()
    {
    }
    void Update()
    {
        this.GetComponent<Text>().text = "文字を変える";//画面上にdisplayTextを表示
    }
}

このプログラムを書くとUnity上で生成したTextの内容が 「 "" 」で挟まれた文字列の内容に変化します。07.png

この機能を主に使ってシステムを作って行きます。

public変数を使ってUnityから文字入力

次はstring型の変数を使って文字列の内容を変えます。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string texts;//変数宣言
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts;//←変える
    }
}

書いたらUnity上ではこのように表示されるはずなので、ここに文字列の内容を書いてみましょう。08.png

実行するとUnityで入力した文字列に変更されましたね?

string型のpublic配列を作ろう

次はtextsを変数ではなく配列として宣言しましょう。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;//←変える
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[0];//←変える
    }
}

このように記述すると、文字列を複数個入力できるようになりますね?09.png

そして実行すると0番目に入力した文字列が表示されるようになったはずです。なぜかというと、

this.GetComponent<Text>().text = texts[0];

の数の文字列を表示するプログラムになっているからです。ここの数字を変えれば文字列が順番に表示されるようになります。

texts[0]←ここの数字を変数を使って増やしていく

Unity上で入力した文字列の順番に変えていくプログラムを作ります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;//追加
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];//←変える
        textNumber = textNumber + 1;//追加
    }
}

このように書くと内容が変わるようになりましたね?恐らくめちゃめちゃ速く。
このままだとまともにセリフが読めないので、クリックしたら変更するようにします。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];
        if (Input.GetMouseButtonDown(0))//追加
        {//追加
            textNumber = textNumber + 1;
        }//追加
    }
}

if文の条件をクリックしたら「(Input.GetMouseButtonDown(0))」にし、{}の中でtextNumberを1ずつ増やすプログラムにしました。これで好きなタイミングで変えることができるようになったはずです。

最後のセリフで止める

恐らく上のプログラムだと、クリックをし続けるとエラーが出てしまいますよね?それを防ぐプログラムを追加します。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];
        if (textNumber != texts.Length - 1)//追加
        {//追加
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }//追加
    }
}

この様なif文を追加すると最後の文章で止まるようになります。具体的には、textNumberがtexts配列の数-1以外ならクリックしたらという条件を追加しました。

一文字ずつ表示させるプログラム

次は一文字一文字表示させるプログラムですが、新たに二つの変数を追加で宣言します。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;//追加
    int textCharNumber;//追加
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = displayText;//変更
        if (textNumber != texts.Length - 1)
        {
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }
    }
}

今後はstring型の変数displayTextを表示させていくことにします。では、displayTextに文字データを一文字一文字プログラミングで入力していきましょう。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    void Start()
    {

    }
    void Update()
    {
        if (textCharNumber != texts[textNumber].Length) //追加
        {//追加
            displayText = displayText + texts[textNumber][textCharNumber];//追加
            textCharNumber = textCharNumber + 1;//追加
        }//追加
        else//追加
        {//追加
            displayText = "";//追加
            textCharNumber = 0;//追加
        }//追加

        this.GetComponent<Text>().text = displayText;
        if (textNumber != texts.Length - 1)
        {
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }
    }
}
displayText = displayText + texts[textNumber][textCharNumber];

この一行の説明をします。
変数displayTexttexts配列のtextNumber番目の文字列のtextCharNumber番目の文字を追加するというプログラムです。

if (textCharNumber != texts[textNumber].Length) 
{
     textCharNumber = textCharNumber + 1;
}

このif文の意味は、もしtextCharNumbertexts配列のtextNumber番目の一つ前の数じゃなければ、textCharNumberを1ずつ増やすというプログラムです。
このif文のあとに

else
{
     displayText = "";
     textCharNumber = 0;
}

を追加すると、もしtextCharNumbertexts配列のtextNumber番目の一つ前の数のときに、displayTextを""にしたり、textCharNumberを0に戻したりするというプログラムになります。
このプログラムのおかげでtextCharNumberの数が文字列の数を超えた時バグらなくなります。

今までのプログラムの統合

一文字ずつ表示させて、クリックしたら次のセリフに移行するプログラム

今までのプログラムを整理すると、

  1. displayTexttexts配列のtextNumber番目の文字列のtextCharNumeber番目の文字を最後の文字まで追加していく。
  2. 最後の文字になった時に、追加する文字を最初にする。displayTextを " " に戻す。
  3. クリックされたら、次のtexts配列を次の文字列にする。

という単純なプログラムです。
これの2と3を混ぜるだけでRPGチックになります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    void Start()
    {

    }
    void Update()
    {

        if (textCharNumber != texts[textNumber].Length) 
        {
            displayText = displayText + texts[textNumber][textCharNumber];
            textCharNumber = textCharNumber + 1;
        }
        else
        {
            if (textNumber != texts.Length - 1)
            {
                if (Input.GetMouseButtonDown(0))//移動
                {//移動
                    displayText = "";//移動
                    textCharNumber = 0;//移動
                    textNumber = textNumber + 1;//移動
                }//移動
            }            
        }

        this.GetComponent<Text>().text = displayText;

    }
}

うまくいきましたか?

Ex

文字表記をゆっくりに

文字表記をゆっくりにしたかったらこのようにすると文字のスピードが遅くなります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    int displayTextSpeed;//追加
    bool click;//追加
    void Start()
    {

    }
    void Update()
    {
        displayTextSpeed++;
        if (displayTextSpeed % 5 == 0)//追加
        {//追加
            if (textCharNumber != texts[textNumber].Length)
            {
                displayText = displayText + texts[textNumber][textCharNumber];
                textCharNumber = textCharNumber + 1;
            }
            else
            {
                if (textNumber != texts.Length - 1)
                {
                    if (click==true)
                    {
                        displayText = "";
                        textCharNumber = 0;
                        textNumber = textNumber + 1;
                    }
                }
            }

            this.GetComponent<Text>().text = displayText;
            click = false;//追加
        }//追加
        if (Input.GetMouseButton(0))//追加
        {//追加
            click = true;//追加
        }//追加
    }
}

最後のセリフでクリックしたら消したい

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    int displayTextSpeed; 
    bool click;
    bool textStop;//追加
    void Start()
    {

    }
    void Update()
    {
        if (textStop == false)//追加
        {//追加
            displayTextSpeed++;
            if (displayTextSpeed % 5 == 0)
            {

                if (textCharNumber != texts[textNumber].Length)
                {
                    displayText = displayText + texts[textNumber][textCharNumber];
                    textCharNumber = textCharNumber + 1;
                }
                else
                {
                    if (textNumber != texts.Length - 1)
                    {
                        if (click == true)
                        {
                            displayText = "";
                            textCharNumber = 0;
                            textNumber = textNumber + 1;
                        }
                    }
                    else//追加
                    {//追加
                        if (click == true)//追加
                        {//追加
                            displayText = "";//追加
                            textCharNumber = 0;//追加
                            textStop = true;//追加
                        }//追加
                    }//追加
                }

                this.GetComponent<Text>().text = displayText;
                click = false;
            }
            if (Input.GetMouseButton(0))
            {
                click = true;
            }
        }//追加
    }
}

まず、textStopがfalseの時だけこのプログラムが動くようにプログラミングします。そして
もし最後のセリフの文字列になった時にクリックしたら、表示を " " にしてtextStopをtrueにすることで全てのプログラムを止められるようにします。
そうするとメッセージが止まったようになります。

最後に全体のプログラム

TextDisplay.cs
TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;//Unity上で入力するstringの配列
    string displayText;//表示させるstring
    int textDisplayCount;//全体のフレームレートを落とす変数
    int textNumber;//何番目のtexts[]を表示させるか
    int textCharNumber;//何文字目をdisplayTextに追加するか
    int displaySpeed=5;//文字の表示スピード調整(0が最小)
    bool click;//クリック判定
    bool textStop;//テキスト表示を始めるか

    void Start()
    {

    }
    void Update()
    {
        if (textStop == false)//テキストを表示させるif文
        {
            textDisplayCount++;
            if (textDisplayCount % displaySpeed == 0)//displaySpeedに一回プログラムを実行するif文
            {// ↑の「 % 」はあまりって意味。 例)10➗3= 3あまり1 → if(10 % 3 == 1){}

                if (textCharNumber != texts[textNumber].Length)//もしtext[textNumber]の文字列の文字が最後の文字じゃなければ
                {// ↑の「 != 」は「じゃない」っていう意味
                    displayText = displayText + texts[textNumber][textCharNumber];//displayTextに文字を追加していく
                    textCharNumber++;//次の文字にする
                    click = false;//クリックされたを解除
                }
                else//もしtext[textNumber]の文字列の文字が最後の文字だったら
                {
                    if (click == true)//クリックされた判定
                    {
                        if (textNumber == texts.Length-1)//もしtexts[]が最後のセリフになったら
                        {
                            textStop = true;//セリフ表示を止める
                            textNumber = 0;//texts[]を最初に戻す
                            textCharNumber = 0;//文字の番号を最初にする
                            displayText = "";//表示させる文字列も消す
                        }
                        else
                        {//もしtexts[]が最後のセリフじゃないときは
                            textNumber++;//次のセリフにする
                            textCharNumber = 0;//文字の番号を最初にする
                            displayText = "";//表示させる文字列も消す
                            click = false;//クリックされた判定を解除
                        }
                    }
                }

                if (Input.GetMouseButton(0))//マウスをクリックしたら
                {
                    click = true;//次のセリフ表示
                }
            }
        }

        if(Input.GetKey(KeyCode.A)){//  例)もしAキーを押したら次のセリフにする
            textStop = false;//テキスト表示開始
            tekito();//新しいテキストを挿入
        }
        this.GetComponent<Text>().text = displayText;//画面上にdisplayTextを表示
    }

    void tekito(){//新しい文字列の配列宣言
        texts = new string[5];//何行の文字列配列にするか
        texts[0] = "zzzzz";
        texts[1] = "yyyyyyyyyy";
        texts[2] = "xxxxxxxxxx";
        texts[3] = "wwwww";
        texts[4] = "vvvvvvvvvvvvvv";
    }

}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】LESSON01. 一文字ずつ進むセリフの表示をして簡単にRPGチックなテキストボックスにしちゃおう!(解説付き)【★★★✩✩】

入力した文字列をRPGのセリフ表示っぽくしよう

「UnderTale」や「ゼルダの伝説」のセリフって文字が一文字一文字テキストボックスに追加されて行きますよね?それを出来るだけ簡単に実装して行きます!

①まずはUnityでやること

CanvasにTextを追加しよう(1/2)

まずは文字を表示させる為にGameObject→UI→Textの順番でクリックしていき「Text」を出しましょう!01.png

▼Canvas
Text
↑みたいになります!

文字の大きさや、表示させたい位置を自分の好きな所に設定してね!

Textにスクリプトをアタッチしよう!(2/2)

最初は「New Text」となってるはずなのでこれを変えます!Textに表示されてる文字列を変えるためのスクリプトの準備をします!

Projectのウィンドウで右クリック→Create→C# Scriptの順番に操作します!
02.png

そうするとスクリプトが生成されます。そのスクリプトに適当な名前をつけます。今回は「TextDisplay」としましょう!(Displayは表示という意味)

03.png

そうしたらTextDisplayスクリプトをTextにアタッチします。下の画像のどっちの操作でもアタッチできるので、好きな方のアタッチの方法でやってください!

アタッチ方法①
04.png

アタッチ方法②
05.png

(アタッチ方法①,②のどちらかやればいいよ!)

結果的に下の画像のように表示されたらオッケーです!
06.png

②つぎはプログラミングの作業

では、TextDisplayスクリプトを開いてプログラミングの作業を始めます!ひとつひとつの機能を一緒に理解しながら作って行きましょう。
【注意!】プログラムに「 // 」←がついている行が新しい行です。その行を追加していってくださいね!

スクリプトから文字を手動で変える(1/5)

まずは簡単な方法で文字を変えます。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//←これを追加

public class TextDisplay : MonoBehaviour
{
    void Start()
    {
    }
    void Update()
    {
        this.GetComponent<Text>().text = "文字を変える";//画面上にdisplayTextを表示
    }
}

このプログラムを書くとUnity上で生成したTextの内容が 「 "" 」で挟まれた文字列の内容に変化します。07.png

この機能を主に使ってシステムを作って行きます。

public変数を使ってUnityから文字入力(2/5)

次はstring型の変数を使って文字列の内容を変えます。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string texts;//変数宣言
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts;//←変える
    }
}

書いたらUnity上ではこのように表示されるはずなので、ここに文字列の内容を書いてみましょう。08.png

実行するとUnityで入力した文字列に変更されましたね?

string型のpublic配列を作ろう(3/5)

次はtextsを変数ではなく配列として宣言しましょう。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;//←変える
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[0];//←変える
    }
}

このように記述すると、文字列を複数個入力できるようになりますね?09.png

そして実行すると0番目に入力した文字列が表示されるようになったはずです。なぜかというと、

this.GetComponent<Text>().text = texts[0];

の数の文字列を表示するプログラムになっているからです。ここの数字を変えれば文字列が順番に表示されるようになります。

texts[0]←ここの数字を変数を使って増やしていく(4/5)

Unity上で入力した文字列の順番に変えていくプログラムを作ります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;//追加
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];//←変える
        textNumber = textNumber + 1;//追加
    }
}

このように書くと内容が変わるようになりましたね?恐らくめちゃめちゃ速く。
このままだとまともにセリフが読めないので、クリックしたら変更するようにします。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];
        if (Input.GetMouseButtonDown(0))//追加
        {//追加
            textNumber = textNumber + 1;
        }//追加
    }
}

if文の条件をクリックしたら「(Input.GetMouseButtonDown(0))」にし、{}の中でtextNumberを1ずつ増やすプログラムにしました。これで好きなタイミングで変えることができるようになったはずです。

最後のセリフで止める

恐らく上のプログラムだと、クリックをし続けるとエラーが出てしまいますよね?それを防ぐプログラムを追加します。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = texts[textNumber];
        if (textNumber != texts.Length - 1)//追加
        {//追加
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }//追加
    }
}

この様なif文を追加すると最後の文章で止まるようになります。具体的には、textNumberがtexts配列の数-1以外ならクリックしたらという条件を追加しました。

一文字ずつ表示させるプログラム(5/5)

次は一文字一文字表示させるプログラムですが、新たに二つの変数を追加で宣言します。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;//追加
    int textCharNumber;//追加
    void Start()
    {

    }
    void Update()
    {
        this.GetComponent<Text>().text = displayText;//変更
        if (textNumber != texts.Length - 1)
        {
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }
    }
}

今後はstring型の変数displayTextを表示させていくことにします。では、displayTextに文字データを一文字一文字プログラミングで入力していきましょう。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    void Start()
    {

    }
    void Update()
    {
        if (textCharNumber != texts[textNumber].Length) //追加
        {//追加
            displayText = displayText + texts[textNumber][textCharNumber];//追加
            textCharNumber = textCharNumber + 1;//追加
        }//追加
        else//追加
        {//追加
            displayText = "";//追加
            textCharNumber = 0;//追加
        }//追加

        this.GetComponent<Text>().text = displayText;
        if (textNumber != texts.Length - 1)
        {
            if (Input.GetMouseButtonDown(0))
            {
                textNumber = textNumber + 1;
            }
        }
    }
}
displayText = displayText + texts[textNumber][textCharNumber];

この一行の説明をします。
変数displayTexttexts配列のtextNumber番目の文字列のtextCharNumber番目の文字を追加するというプログラムです。

if (textCharNumber != texts[textNumber].Length) 
{
     textCharNumber = textCharNumber + 1;
}

このif文の意味は、もしtextCharNumbertexts配列のtextNumber番目の一つ前の数じゃなければ、textCharNumberを1ずつ増やすというプログラムです。
このif文のあとに

else
{
     displayText = "";
     textCharNumber = 0;
}

を追加すると、もしtextCharNumbertexts配列のtextNumber番目の一つ前の数のときに、displayTextを""にしたり、textCharNumberを0に戻したりするというプログラムになります。
このプログラムのおかげでtextCharNumberの数が文字列の数を超えた時バグらなくなります。

③今までのプログラムの統合

一文字ずつ表示させて、クリックしたら次のセリフに移行するプログラム(1/1)

今までのプログラムを整理すると、

  1. displayTexttexts配列のtextNumber番目の文字列のtextCharNumeber番目の文字を最後の文字まで追加していく。
  2. 最後の文字になった時に、追加する文字を最初にする。displayTextを " " に戻す。
  3. クリックされたら、次のtexts配列を次の文字列にする。

という単純なプログラムです。
これの2と3を混ぜるだけでRPGチックになります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    void Start()
    {

    }
    void Update()
    {

        if (textCharNumber != texts[textNumber].Length) 
        {
            displayText = displayText + texts[textNumber][textCharNumber];
            textCharNumber = textCharNumber + 1;
        }
        else
        {
            if (textNumber != texts.Length - 1)
            {
                if (Input.GetMouseButtonDown(0))//移動
                {//移動
                    displayText = "";//移動
                    textCharNumber = 0;//移動
                    textNumber = textNumber + 1;//移動
                }//移動
            }            
        }

        this.GetComponent<Text>().text = displayText;

    }
}

うまくいきましたか?

Ex

文字表記をゆっくりに(1/2)

文字表記をゆっくりにしたかったらこのようにすると文字のスピードが遅くなります。

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    int displayTextSpeed;//追加
    bool click;//追加
    void Start()
    {

    }
    void Update()
    {
        displayTextSpeed++;
        if (displayTextSpeed % 5 == 0)//追加
        {//追加
            if (textCharNumber != texts[textNumber].Length)
            {
                displayText = displayText + texts[textNumber][textCharNumber];
                textCharNumber = textCharNumber + 1;
            }
            else
            {
                if (textNumber != texts.Length - 1)
                {
                    if (click==true)
                    {
                        displayText = "";
                        textCharNumber = 0;
                        textNumber = textNumber + 1;
                    }
                }
            }

            this.GetComponent<Text>().text = displayText;
            click = false;//追加
        }//追加
        if (Input.GetMouseButton(0))//追加
        {//追加
            click = true;//追加
        }//追加
    }
}

最後のセリフでクリックしたら消したい(2/2)

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;
    int textNumber;
    string displayText;
    int textCharNumber;
    int displayTextSpeed; 
    bool click;
    bool textStop;//追加
    void Start()
    {

    }
    void Update()
    {
        if (textStop == false)//追加
        {//追加
            displayTextSpeed++;
            if (displayTextSpeed % 5 == 0)
            {

                if (textCharNumber != texts[textNumber].Length)
                {
                    displayText = displayText + texts[textNumber][textCharNumber];
                    textCharNumber = textCharNumber + 1;
                }
                else
                {
                    if (textNumber != texts.Length - 1)
                    {
                        if (click == true)
                        {
                            displayText = "";
                            textCharNumber = 0;
                            textNumber = textNumber + 1;
                        }
                    }
                    else//追加
                    {//追加
                        if (click == true)//追加
                        {//追加
                            displayText = "";//追加
                            textCharNumber = 0;//追加
                            textStop = true;//追加
                        }//追加
                    }//追加
                }

                this.GetComponent<Text>().text = displayText;
                click = false;
            }
            if (Input.GetMouseButton(0))
            {
                click = true;
            }
        }//追加
    }
}

まず、textStopがfalseの時だけこのプログラムが動くようにプログラミングします。そして
もし最後のセリフの文字列になった時にクリックしたら、表示を " " にしてtextStopをtrueにすることで全てのプログラムを止められるようにします。
そうするとメッセージが止まったようになります。

最後に全体のプログラム

最後に全ての行に意味をコメントアウトで書いときます

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;//Unity上で入力するstringの配列
    int textNumber;//何番目のtexts[]を表示させるか
    string displayText;//表示させるstring
    int textCharNumber;//何文字目をdisplayTextに追加するか
    int displayTextSpeed; //全体のフレームレートを落とす変数
    bool click;//クリック判定
    bool textStop; //テキスト表示を始めるか
    void Start()
    {

    }
    void Update()
    {
        if (textStop == false) //テキストを表示させるif文
        { 
            displayTextSpeed++;
            if (displayTextSpeed % 5 == 0)//5回に一回プログラムを実行するif文
            {

                if (textCharNumber != texts[textNumber].Length)//もしtext[textNumber]の文字列の文字が最後の文字じゃなければ
                {
                    displayText = displayText + texts[textNumber][textCharNumber];//displayTextに文字を追加していく
                    textCharNumber = textCharNumber + 1;//次の文字にする
                }
                else//もしtext[textNumber]の文字列の文字が最後の文字だったら
                {
                    if (textNumber != texts.Length - 1)//もしtexts[]が最後のセリフじゃないときは
                    {
                        if (click == true)//クリックされた判定
                        {
                            displayText = "";//表示させる文字列を消す
                            textCharNumber = 0;//文字の番号を最初にする
                            textNumber = textNumber + 1;//次のセリフにする
                        }
                    }
                    else //もしtexts[]が最後のセリフになったら
                    { 
                        if (click == true) //クリックされた判定
                        { 
                            displayText = ""; //表示させる文字列も消す
                            textCharNumber = 0; //文字の番号を最初にする
                            textStop = true; //セリフ表示を止める
                        } 
                    } 
                }

                this.GetComponent<Text>().text = displayText;//画面上にdisplayTextを表示
                click = false;//クリックされた判定を解除
            }
            if (Input.GetMouseButton(0))//マウスをクリックしたら
            {
                click = true; //クリックされた判定にする
            }
        } 
    }
}

あとは各々フォントなどをアレンジしてお好みのテキストボックスを作ってみてね!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】LESSON01.セリフ表示をRPGチックに【★★★✩✩】

入力した文字列をRPGのセリフ表示っぽくしよう

「UnderTale」や「ゼルダの伝説」のセリフって文字が一文字一文字テキストボックスに追加されて行きますよね?それを出来るだけ簡単に実装して行きます!

TextDisplay.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TextDisplay : MonoBehaviour
{
    public string[] texts;//Unity上で入力するstringの配列
    string displayText;//表示させるstring
    int textDisplayCount;//全体のフレームレートを落とす変数
    int textNumber;//何番目のtexts[]を表示させるか
    int textCharNumber;//何文字目をdisplayTextに追加するか
    int displaySpeed=5;//文字の表示スピード調整(0が最小)
    bool click;//クリック判定
    bool textStop;//テキスト表示を始めるか

    void Start()
    {

    }
    void Update()
    {
        if (textStop == false)//テキストを表示させるif文
        {
            textDisplayCount++;
            if (textDisplayCount % displaySpeed == 0)//displaySpeedに一回プログラムを実行するif文
            {// ↑の「 % 」はあまりって意味。 例)10➗3= 3あまり1 → if(10 % 3 == 1){}

                if (textCharNumber != texts[textNumber].Length)//もしtext[textNumber]の文字列の文字が最後の文字じゃなければ
                {// ↑の「 != 」は「じゃない」っていう意味
                    displayText = displayText + texts[textNumber][textCharNumber];//displayTextに文字を追加していく
                    textCharNumber++;//次の文字にする
                    click = false;//クリックされたを解除
                }
                else//もしtext[textNumber]の文字列の文字が最後の文字だったら
                {
                    if (click == true)//クリックされた判定
                    {
                        if (textNumber == texts.Length-1)//もしtexts[]が最後のセリフになったら
                        {
                            textStop = true;//セリフ表示を止める
                            textNumber = 0;//texts[]を最初に戻す
                            textCharNumber = 0;//文字の番号を最初にする
                            displayText = "";//表示させる文字列も消す
                        }
                        else
                        {//もしtexts[]が最後のセリフじゃないときは
                            textNumber++;//次のセリフにする
                            textCharNumber = 0;//文字の番号を最初にする
                            displayText = "";//表示させる文字列も消す
                            click = false;//クリックされた判定を解除
                        }
                    }
                }

                if (Input.GetMouseButton(0))//マウスをクリックしたら
                {
                    click = true;//次のセリフ表示
                }
            }
        }

        if(Input.GetKey(KeyCode.A)){//  例)もしAキーを押したら次のセリフにする
            textStop = false;//テキスト表示開始
            tekito();//新しいテキストを挿入
        }
        this.GetComponent<Text>().text = displayText;//画面上にdisplayTextを表示
    }

    void tekito(){//新しい文字列の配列宣言
        texts = new string[5];//何行の文字列配列にするか
        texts[0] = "zzzzz";
        texts[1] = "yyyyyyyyyy";
        texts[2] = "xxxxxxxxxx";
        texts[3] = "wwwww";
        texts[4] = "vvvvvvvvvvvvvv";
    }

}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】タップした画面の色を取得する方法(UniRx使用)

やりたいこと

やえがしさんのTwitterで
画面に映った色を取得してるのを見かけたので、
どうやればいいか調べてみました。
(ちょっとご本人にヒントももらいました。ありがとうございます)

デモ

こんな感じで触った色が球体に反映されています。
GetColor.gif

今回はスマホの外部カメラの映像ではありませんが、
ARCoreなどのカメラをシーンに置けば
スマホの画面の映像から色を抽出できます。

コード

もうほぼ答えですが、下記リンクを参考にしました。

【参考リンク】:Unityで、クリックしたピクセルの色を取得したい

リンク先にもありますが、描画処理が終わってからピクセルを取得する必要があるので、
WaitForEndOfFrameでそのフレームの最後に取得するようにしてます。

適当なオブジェクトにアタッチ
using UnityEngine;
using UniRx;
using UniRx.Triggers;
using CustomInput; //自分で定義したやつ
using System.Collections;

public class GetPixelColor : MonoBehaviour
{
    Coroutine runCoroutine;
    Texture2D screenTex;

    readonly public ColorReactiveProperty touchPosColorProperty = new ColorReactiveProperty();

    void Start()
    {
        screenTex = new Texture2D(1,1, TextureFormat.RGB24, false);

        this.UpdateAsObservable()
            .Where(_ => SimpleInput.GetTouchDown())
            .Subscribe(_ => 
            {
                if(runCoroutine == null)
                {
                    runCoroutine = StartCoroutine(GetColorTouchPos());
                }
            })
            .AddTo(this);
    }

    IEnumerator GetColorTouchPos()
    {
        yield return new WaitForEndOfFrame();
        Vector2 touchPos = SimpleInput.GetTouchDownPos();
        screenTex.ReadPixels(new Rect(touchPos.x, touchPos.y,1,1), 0, 0);
        touchPosColorProperty .Value= screenTex.GetPixel(0,0);
        Debug.Log(touchPosColorProperty.Value);

        runCoroutine = null;
    }
}

色が変化したことを検知するために
ReactivePropertyを利用しています。

検知の監視側はこんな感じです。

色を変えたいオブジェクト(MeshRenderer有り)にアタッチ
using UnityEngine;
using UniRx;

public class ChangeColor : MonoBehaviour
{
    [SerializeField]
    GetPixelColor getPixelColor;

    MeshRenderer thisObjMeshRenderer;

    void Start()
    {
        thisObjMeshRenderer = this.gameObject.GetComponent<MeshRenderer>();

        getPixelColor.touchPosColorProperty
            .SkipLatestValueOnSubscribe()
            .Subscribe(_ =>
            {
                thisObjMeshRenderer.material.color = getPixelColor.touchPosColorProperty.Value;
            })
            .AddTo(this);
    }
}

SkipLatestValueOnSubscribe

SkipLatestValueOnSubscribeは発行された最初の値を無視できるやつです。

ObserveEveryValueChangedReactivePropertyを利用した際、
Subscribe(実行したい関数を登録)した時点で初期値が発行されてしまうようで、
始まっていきなりSubscribe内の登録した処理が走ってしまっていました。

例として下記のようなコードでObserveEveryValueChanged
Color型の変数を監視した場合、
Start関数内で初期値が発行されてしまい、
まだ色が変化してないにもかかわらず"Color Change"が表示されました。

例)touchPosColorはただのColor型
        GetColor
            .ObserveEveryValueChanged(_ => _.touchPosColor)
            .Subscribe(_ =>
            {
                Debug.Log("Color Change");
            })
            .AddTo(this);

SkipLatestValueOnSubscribe
ReactivePropertyのオペレータとして用意されているので、
ObserveEveryValueChangedではなく、
Color型の変数をReactivePropertyに変えて利用しました。

【参考リンク】:Unityにおけるコルーチンの省メモリと高速化について、或いはUniRx 5.3.0でのその反映

CustomInput

今回はInputがタッチなのでオレオレInputを定義してます。

タッチ系は毎回書くのが面倒なので、一回作って使い回すか
EventSystemを利用するのがセオリーっぽいです。
(もっと楽なのあったら教えてください)

using UnityEngine;

namespace CustomInput
{
    /// <summary>
    /// Custom InputKey
    /// </summary>
    public static class SimpleInput
    {
        /// <summary>
        /// Being touched return true
        /// </summary>
        public static bool GetTouch()
        {
            if (0 < Input.touchCount)
            {
                Touch touch = Input.GetTouch(0);

                if (touch.phase == TouchPhase.Moved && touch.phase == TouchPhase.Stationary)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Touching return true only 1 frame
        /// </summary>
        public static bool GetTouchDown()
        {
            if (0 < Input.touchCount)
            {
                Touch touch = Input.GetTouch(0);

                if (touch.phase == TouchPhase.Began)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Releasing return true only 1 frame
        /// </summary>
        public static bool GetTouchUp()
        {
            if (0 < Input.touchCount)
            {
                Touch touch = Input.GetTouch(0);

                if (touch.phase == TouchPhase.Ended)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Return touching position only 1 frame. Not being touched return Vector.zero
        /// </summary>
        public static Vector2 GetTouchDownPos()
        {
            if (0 < Input.touchCount)
            {
                Touch touch = Input.GetTouch(0);

                if (touch.phase == TouchPhase.Began)
                {
                    return touch.position;
                }
            }
            return Vector3.zero;
        }
    }
}

100

やっと100記事書きました。
中身が微妙なので「だからなんやねん」って感じですが、
継続力だけは自分で自分を評価します。

逆に言うと私のレベルで継続できなくなったらオワリなので
これからもノンストップ牛歩で頑張ります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】DOTSを少し試そうとしただけなのに2時間無駄にしないための備忘録

序文

Unityを2019.3に上げたこともあり、噂のDOTS(ECS?)とやらを試そうとしました。
しかし、なぜかオブジェクトが消えるなー、重力で落ちてるんかなー、うまくいかんなーと2時間くらい詰まったので、同じ轍を踏む人が減ることを願って記事化しました。

結論

Package Manager から Hybrid Renderer をインストールしてください。
image.png

Entities や Unity Physics だけインストールして満足しないでください。

そのおかげで、公式チュートリアルの通りにやっても実行と同時に画面上ではオブジェクトが消えてしまい、色々調べたりで彷徨ってしまいました。

最初は Physics 的な設定が出来ておらず、オブジェクトが奈落の底に落ちて消えていると勘違いしてしまいました。実際のところは従来のUnity EditorにはDOTSの描画機能が備わっておらず、別途packageのインストールが必要だったという訳です。

一応やったことも記す

環境は Windows10/Unity 2019.3.0f6 です。

UnityのシーンにDOTS的なオブジェクトを配置して Unity Physics で物理演算させます。

packageのインストール

  • [Windows]->[Package Manager]からPackage Managerを開き、[All packages] として [Advanced] から Show preview packages をonにします。

image.png

  • Entities を選択し、[Install]します。

    • 当時のバージョンは 0.5.1 でした
  • Unity Physics を選択し、[Install]します。

    • 当時のバージョンは 0.2.5 でした
  • Hybrid Renderer を選択し、[Install]します。

    • 前述のとおり、本記事の肝です
    • 当時のバージョンは 0.3.3 でした

シーンに配置する

staticな Cube に落ちてきた Sphere が衝突して軌道を変えるという何の面白みもないシーンを作ろうと思います。

physics.gif

内容はほぼ公式チュートリアルに準拠しています。

static なオブジェクトの配置

  • Hierarchy から右クリックで[3D Object]->[Cube]で Cube を生成します。
  • Cube を選択し、Inspector から Box ColliderRemove Component します。
    • image.png
  • Physics Shape を Add Component します
    • image.png
  • この時、警告ぽい表示が出ますが、 Convert To EntityAdd Component すると消えます。
    • image.png

ここで配置したCubeは動かない静的なオブジェクトになります。床などを配置したいときはこのように設定すると良いようです。

dynamic なオブジェクトの配置

  • Hierarchy から右クリックで[3D Object]->[Sphere]で Sphere を生成します。
  • Sphere を選択し、Inspector から Sphere ColliderRemove Component します。
  • Physics ShapeAdd Component します。以下の様に、Shape Type を Sphere とします。
    • image.png
  • Physics BodyAdd Component します。以下の様に、Motion Type を Dynamic とします。
    • image.png
  • Cube と同様に Convert To EntityAdd Component します。

あとはいつも通り再生すると Sphere が落ちて Cube に衝突します。例では少し Cube を傾けてます。
なお、再生中は Hierarchy から Cube と Sphere が消えて DebugStream.DrawComponent なるものが代わりに現れます。
Cube と Sphere の情報が見たければ、[Windows]->[Analysis]->[Entity Debugger] から情報が見れます。
image.png
(見方がわからん...)

まとめ

チュートリアルも前提情報を省いてたりするので油断なりませんね。
引き続き勉強しようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity2017.4 x macOS Catalina でUnityScript入りのプロジェクトを動かしたい

現状

表題の通りのプロジェクトを開くと↓のエラーが出る
https://forum.unity.com/threads/macos-catalina-blank-error-appears-with-no-info.761903/?_ga=2.265238415.1470200052.1581090958-2087677913.1557302560

対応中のにおいがするので、待つのが正しいでしょう

モチベーション

  • もう2020年なのにUnity2017を使わないといけない
  • UnityScriptもつかってる、もしくは何かが使っている
  • でも本当はもうすぐ2018へ移行する予定がある
  • だから2017のパッチバージョンもあまり上げたくない
  • そしてUnityScriptもC#へコンバートしたくない
  • しかし Macが壊れたため 新調して、Catalinaになってしまった
    • もしくは不意にCatalinaに上げてしまった
  • なのでなんとかして新しいMacで動かしたい

まさかこんな人いないと思いますが、世の中にはいるかもしれない。そんな気持ちです。

こうするといいかもしれません

くそみたいな解決方法なので、本当に困っている人以外はマネしないでください

これを

/Applications/Unity/Hub/Editor/2017.4.xxx/Unity.app/Contents/Mono/bin/mono

これで

/Applications/Unity/Hub/Editor/2018.4.xxx/Unity.app/Contents/Mono/bin/mono

で上書きしてみましょう

注意

間違っても↑をしたマシンでビルドするのはやめましょう

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む