【14】配列の使用と作成

とは、複数の値をグループ化する方法です。ひとつの数字や文字列を格納する変数と比較して、表はサイズが固定されておらず、様々な種類の値を含めることができます。表を使えば、ゲーム内アイテムのステータスをグループ化したり、数千人のプレイヤー名のリストを作成したりすることができます。

テーブル(表)は、複数の値をグループ化する方法です。単一の値を格納する変数とは異なり、テーブルは固定サイズではなく、異なるタイプの値を混在して格納することができます。テーブルを使用すると、ゲーム内アイテムの統計情報をグループ化したり、何千ものプレイヤー名のリストを作成したりすることができます。

テーブルにはさまざまなタイプがあります。1つのタイプは配列で、値のリストを特定の順序で格納します。

配列の例

配列を作成するには、配列に名前を付けて中括弧 { } を使用します。括弧内の値は、以下のようにカンマで区切ってください。

local myArray = {“item1”, “item2”, 10, Workplace.Part, myVariable}

話すNPCの作成

配列を学習するために、NPCキャラクターを使ってみます。NPCをクリックすると、配列に格納されたセリフが次々と表示されるようにします。

プロジェクトの設定

このプロジェクトでは、既成のNPCモデルを使用します。これには、スクリプトとClick Detectorが含まれますが、ダイアログは含まれていません。

  1. 既成のNPCダウンロードします。

ダウンロード

  1. Explorer ウィンドウで、Workspace > Insert From File> からStarter_NPC.rbxmを選択します。NPCをインポートします。(ダウンロードしたファイルをそのままワークスペース内にドラッグしてもOK)

ダイアログの配列を作成する

配列に個別の文字列を格納し、NPC用のダイアログを作成します。NPCがクリックされると、各行がチャット吹き出しとして表示されます。

  1. Explorerウィンドウで、NPC を展開し、DialogueScript を開きます。
  1. 変数と speak() の間に、空の配列を作成し、local dialogueArray = {} と入力することで、ダイアログを格納します。
local Chat = game:GetService("Chat")
 
local npc = script.Parent
local characterParts = npc.CharacterParts
local head = characterParts.Head
local clickDetector = npc.ClickDetector
 
--Add table below
local dialogueArray= {}
 
local function speak()
    local dialogue = "This is dialogue!"
    Chat:Chat(head, dialogue)
end
 
clickDetector.MouseClick:Connect(speak)
  1. 中カッコ { } の中に、3つ以上の文字列のダイアログを入力し、カンマで区切ります。
local dialogueArray= {"Hi!", "Today's a great day!", "Good bye!"}

配列の内容を取得する

配列を作成したので、次に配列の中に含まれる値を表示する方法が必要です。

print(dialogueArray) と入力しても、配列は出力されません。一連の数字が表示されるだけです。この方法は使えません。

配列から何かを取得するためには、配列内の値の場所をスクリプトが把握している必要があります。値が配列に追加されると、数字が割り当てられます。この番号はインデックスと呼ばれます。インデックスは1から始まり、値が追加されるたびに1大きい番号が割り当てられます。例えば、"Hi"のインデックスは1で“Good bye!”のインデックスは 3です。

配列から何かを取得するには、スクリプトはその値が配列内でどの位置にあるかを知る必要があります。配列に値が追加されるたびに、インデックスと呼ばれる番号が割り当てられます。Luaでは、インデックスは1から始まり、値が追加されるごとに1ずつ上がっていきます。例えば、“Hi” のインデックスは1で、“Good bye!” のインデックスは3になります。

“Hi!”“Today’s a great day!”“Good bye!”
インデックス123

インデックスが0から始めるプログラミング言語もある
Lua は1から始まりますが、インデックスが1から始まるプログラミング言語はまれです。C言語やJavaなどは0から始まります。

ひとつの配列の値を取得する

特定のインデックスの値を使用するには、dialogueArray[1] のように配列の名前の後にスペースを入れずに角カッコを付け、数字を指定します。

  1. 配列から値を取得するには、= dialogueArray[2] と入力することで、dialogue変数に2つ目のインデックスの値が代入されます。
local dialogueArray= {"Hi!", "Today's a great day!", "Good bye!"}
 
local function speak()
    local dialogue = dialogueArray[2]
    Chat:Chat(head, dialogue)
end

インデックスエラーを防ぐ
存在しないインデックスを使用した場合、nil エラーが表示されます。例えば、上の配列は3までになっているので、dialogueArray[4] を取得しようとするとエラーが発生します。

  1. プロジェクトをプレイして、NPCをクリックすると2つ目の配列値がチャットの吹き出しに表示されることを確認します。コードを変更して、表内の各値をテストします。

変数で配列を処理する

コードをより柔軟にするため、インデックス番号のかわりに変数を使用することができます。例えば、変数を使用してランダムなインデックス番号を取得したり、関数が呼び出されるたびに番号を大きくすることで配列内の次の値を取得したりすることができます。

この場合、プレイヤーがNPCをクリックすると dialogueIndex という名前の変数により番号が1大きくなり、次のダイアログ行を表示します。

local dialogueArray = {"Hi!", "Today's a great day!", "Good bye!"}
local dialogueIndex = 1
  1. speak() で、dialogueArray[2] に含まれるインデックス番号を先ほど作成した変数に置き換えます。
local function speak()
    local dialogue = dialogueArray[dialogueIndex]
    Chat:Chat(head, dialogue)
end
  1. 関数の最後で、dialogueIndex に1を足します。これにより、次に speak() が呼び出されると、NPCにより配列内の次の文字列が表示されます。
local function speak()
    local dialogue = dialogueArray[dialogueIndex]
    Chat:Chat(head, dialogue)
 
    dialogueIndex = dialogueIndex + 1
end
  1. プロジェクトをプレイします。NPCをクリックして、配列内の各ダイアログ文字列が表示されることを確認します。

スクリプトが配列の最後に到達すると、Outputウィンドウにエラーが表示されます。この場合では、4回目のクリックで表示されます。次のセクションではこの問題を修正し、最後の文字列を表示した後にまた最初から繰り返されるようにします。

配列サイズを使用してコードを繰り返す

インデックス番号のかわりに変数を使用することの利点は、配列の最後に到達したか確認できることです。最後に到達したことが分かれば、最初のインデックス番号に戻すことができます。

配列のサイズを確認するには、その配列の変数名の前にスペースを入れずに#と入力します。
 例:#dialogueArray
配列内に存在する要素の数が分かれば、現在の値と照合して、最初に戻るタイミングを判断することができます。

  1. dialogueIndex が #dialogueArray と同じであるか確認するため if 文を使用します。この文で 1 に設定し直すことにより、dialogueIndex を最初から繰り返すことができます。
local function speak()
    local dialogue = dialogueArray[dialogueIndex]
    Chat:Chat(head, dialogue)
 
    if dialogueIndex == #dialogueArray then
        dialogueIndex = 1
    end

    dialogueIndex = dialogueIndex + 1
end
  1. dialogueIndex が最後でなくても、dialogueIndex には1を足すようにしなくてはなりません。そのためには、下のようにelse文を追加して行を移動させます。
local function speak()
    local dialogue = dialogueArray[dialogueIndex]
    Chat:Chat(head, dialogue)
 
    if dialogueIndex == #dialogueArray then
        dialogueIndex = 1
    else
        dialogueIndex = dialogueIndex + 1
    end
end
  1. プロジェクトをプレイします。エラーが発生することなく、配列のサイクルを実行することができるか確認します。

問題解決のヒント
ダイアログが最後に到達した後、最初に戻らない場合
・if文で、dialogueIndex が1に戻しているのかを確認します。else 文で、dialogueIndex に1が足されていることを確認します。
・配列のサイズを取得する際には、#dialogueArray# の後にスペースが入力されていないことを確認します。

完成したスクリプト

local Chat = game:GetService("Chat")
 
local npc = script.Parent
local characterParts = npc.CharacterParts
local head = characterParts.Head
local clickDetector = npc.ClickDetector
 
-- Stores a list of dialogues to say
local dialogueArray= {"Hi!", "Today's a great day!", "Good bye!"}
local dialogueIndex = 1
 
-- Shows a new dialogue whenever the NPC is clicked
local function speak()
    local dialogue = dialogueArray[dialogueIndex]
    Chat:Chat(head, dialogue)

    -- If the increment is at the end of the array, set it back to the start
    if dialogueIndex == #dialogueArray then
        dialogueIndex = 1
    -- Else, just add 1 to the increment to keep moving up in the array
    else
        dialogueIndex = dialogueIndex + 1
    end
end
 
clickDetector.MouseClick:Connect(speak)

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です