12/08/2018, 15:22

Unity - Talk Function

さて、今回からは学習したことをまとめて、便利な情報を数日に一個記事にしていきます。 「学習したこと」と言ってもC#のコードについてだけではなく 考え方やテクニックなど、いろいろな事がありました。 その中で、大体のゲームにあって僕が上手く実装出来なかった機能、アレにもう一度チャレンジしたいと思います。 Retry アレとは何か。 それは、会話機能です。 前回、UnityC#についての基礎も全くついていないまま実装しようとしたら めちゃくちゃ頭の悪いコードを書いてしまったのを今でも覚えています。 こちらの一番最後です。 IF文大好き人間かよ、って感じですね。 1個目の会話 ...

さて、今回からは学習したことをまとめて、便利な情報を数日に一個記事にしていきます。 「学習したこと」と言ってもC#のコードについてだけではなく 考え方やテクニックなど、いろいろな事がありました。

その中で、大体のゲームにあって僕が上手く実装出来なかった機能、アレにもう一度チャレンジしたいと思います。

Retry

アレとは何か。 それは、会話機能です。

前回、UnityC#についての基礎も全くついていないまま実装しようとしたら めちゃくちゃ頭の悪いコードを書いてしまったのを今でも覚えています。

こちらの一番最後です。

IF文大好き人間かよ、って感じですね。 1個目の会話をしたら1個目の会話中の判定を出して、2個目の会話に飛ぶ。しかも会話内容は全部スクリプト内に書いとく。

…一旦忘れて手を動かしましょう。

Recreate talk function

まずは設計図からです。

先日やったチュートリアルでの設計図がすっごい分かりやすかったので、それを参考にしたいと思います。 でも、動画にして設計図とか作ったりしてると時間がかかってしまうので 参考にするのは「書くコードがどういう動きを担っているのか?」をわかりやすく図にするという所ですね。

見た目的にはこんな感じで

画力は変わりませんね・・・ んで、僕のイメージしている内部的な動きはこんな感じです

何が書いてるか分からないという声が聞こえてきます。 いや、僕が伝えたいのは会話機能はコイツと似てるって事ですよ。

そう、だるま落としです。

だるま本体側は「会話内容の格納庫」で、一番下の会話内容を読み込んで画面へと表示させます。 そして、槌がクリック(場合によってはEnterキーなど)で、クリックしたらパコーーーンと現在の会話内容をぶっ飛ばします。 すると、新しい会話内容が下に落ちてくるので、画面には新しい会話内容が表示されます。

NPCに話しかけたら突然だるま落としを押し付けられてるのが内部処理ですね。…どういうことだよ 実際に作っていきます。

Let's do this

新しいプロジェクトを作成、TalkFunctionという名前をつけました。 その後、会話機能を作れるようになりたいだけなので、空の色とかそこらへんは単純な色に設定してあげます。

んで、テキトーに会話UIを作ってあげます。

ここのアウトラインは、コンポーネントからOutlineってのを追加してやれば簡単につけれました。

会話内容を代入可能なTextを追加。 これでUI側は完成です。

では、CreateからC# Scriptを作成します。「TalkController」って名前にしておきます。 とりあえず、書いたコードを載せておきます。

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

public class TalkController : MonoBehaviour {

    public string[] kaiwanaiyou;
    public Text textobject;

    private int nowtalknum;

    public void Start()
    {
        NextTalk();
    }

    public void Update()
    {
        if (nowtalknum < kaiwanaiyou.Length && Input.GetMouseButtonDown(0))
        {
            NextTalk();
        }
    }

    public void NextTalk()
    {
        textobject.text = kaiwanaiyou[nowtalknum];
        nowtalknum++;
    }
}

エラーが発生した時に、テラシュールブログのこの記事を参考にしました。 僕とほぼ一緒のコードを書いていたのでちょっと嬉しかったですね。

修正箇所などについても個々に解説していきます。

Variable declaration

public string[] kaiwanaiyou; // だるま落としのだるまの部分
public Text textobject; // 現在のテキストを表示するための場所

private int nowtalknum; // だるま落としが何回叩かれたかを確認

こちらは、変数の宣言部分です。

public string[] kaiwanaiyou; というように宣言すると、インスペクター上でこのように表示されます。

sizeの所は自由に数値を設定できて、数に応じて下のElementがどんどんと増えていきます。 長い会話を実装したい場合は大きな数値にして、短ければ小さい数になります。

Elementには表示したいテキストを入力します。

NextTalk関数

public void NextTalk()
{
    textobject.text = kaiwanaiyou[nowtalknum]; // 表示するテキストを現在の会話内容におきかえる
    nowtalknum++; // 次に表示するテキストは現在の会話内容の次の内容にする
}

次に、NextTalk関数です。 こちらは、インスペクター上でアタッチしたTextゲームオブジェクトに現在の会話内容を代入する関数です。

今回アタッチしたオブジェクトは

こちらのTextゲームオブジェクト。 んで、nowtalknum++;で次にNextTalk関数が実行された時に代入される会話内容が1個進んだものになります。

Update

public void Update()
{
    if (nowtalknum < kaiwanaiyou.Length && Input.GetMouseButtonDown(0)) // もし次の会話内容が存在して、クリックされたら
    {
        NextTalk(); // NextTalk関数を実行
    }
}

StartはNextTalk関数を起動時に実行しているだけなので解説は省略します。 で、UpdateではNextTalk関数を実行するのに条件を設けています。

それは、「次の会話内容が存在して、画面上をクリックしたら」実行されるという条件です。 で、ここが先程言っていた修正箇所です。

最初僕は画面上をクリックしたら次の会話内容に行くという条件式を設けていたのですが 画面上をクリックしまくってたら、なんかエラーメッセージが大量に出てきてうるさい状態に。

なんだよと思ってメッセージを読んでみたら string[] kaiwanaiyou内のインスペクター上で設定したsizeで出来た配列の数よりも大きな値を指定してしまった つまり、配列で会話内容が存在しない所にアクセスしていたからエラーが吐かれていたんですね。

んで、コイツを大人しくしてやるためにはそもそも会話内容が無いところにはアクセス出来ないようにしてやればOK。 そのための

nowtalknum < kaiwanaiyou.Length

ですね。 kaiwanaiyou.Lengthの.Lengthは「配列の長さ」を出すことができます。sizeが5だったら5ですね。 nowtalknumってのが何個目の会話かどうかの判定で、今回の場合「            </div>
            
            <div class=

0