原文では「Dictionaries」と呼ばれていますので、直訳で「辞書」としました。他のプログラミング言語では、連想配列と呼ばれているものもあります。つまり配列の延長線上に位置するものになります。配列にはインデックスという順番がありましたが、辞書にはそれがありません。その代わりにキーと呼ばれるものがあります。キーは名札のようなものです。そのキーを使って、要素にアクセスするということになります。
local pet = {
Name = "Bobbie",
Type = "Dog",
}
配列のように値を順番にリストするだけでなく、値にラベルを付ける必要がある場合は辞書を使用します。このチュートリアルでは、プレーヤーに関連付けられた値を操作して辞書を使用する練習をしてください。
辞書の構文
配列と同様に、辞書は中括弧 {} で変数に割り当てられます。キーと値のペアは、カンマが後に続く別の行に保存されます。キーと値には、文字列、数値、変数名など、任意のデータ型を使用できます。
local playerNames = {
player1 = "Zap",
player2 = "Kel",
}
print(playerNames["player1"])
パーツまたは他のインスタンス化されたオブジェクトをキーとして参照するには、括弧を使用します。
local greenPart = workspace.GreenPart
local redPart = workspace.RedPart
local partList = {
[greenPart] = true,
[redPart] = false,
}
print(partList[redPart])
辞書のキーには一貫したデータ型を使用します。キーに文字列と変数の両方を使用するなど、データ型を混在させると、配列の操作時に一貫性のない結果が生じ、他のプログラマーが混乱する可能性がありますので注意しましょう。
辞書の作成
辞書の日常的な用途の 1 つは、プレーヤーまたはキャラクターの情報を整理することです。これらの手順では、理論上の敵キャラクターの情報をどのように保存してアクセスできるかを検討します。
- 新しいスクリプトで、 emoneという名前の辞書を作成します。
local enemy = {
}
- 辞書の最初のキーは、nameという変数を使用して敵の名前を追跡します。
local enemy = {
Name
}
- キーに敵の名前を割り当て、その後にカンマを付けます。
local enemy = {
name = "Spike",
}
- 敵の体力を表す 2 番目のキーと値のペアを追加します。キーは常に同じデータ型を使用する必要がありますが、値はバラバラで構いません。
local enemy = {
Name = "Spike",
Health = 1000,
}
辞書の値の使用
辞書の値にアクセスするには 2 つの方法があります。
(A) tableName[“keyName”] — この書き方の場合はキーを変数にできる
(B) tableName.keyName — この書き方の場合はキーを変数にできない
local enemy = {
Name = "Spike",
Health = 1000,
}
print("The villain " .. enemy["Name"] .. " approaches!")
print("The villain " .. enemy.Name .. " approaches!")
どのスタイルを使用するかは、通常、テーブルの目的によって異なります。サーバー内のプレーヤーのリストなどの値のコレクションを保持するテーブルの場合、プログラマーは通常、tableName[“keyName”] を使用します。オブジェクトを記述するために使用される辞書の場合、プログラマーは tableName.keyName を使用する可能性が高くなります。
辞書の値の変更
キーの値の変更は、他の変数の変更と同じです。等号=演算子を使用します。
- 敵のテーブルの下で、敵の名前を別の名前に変更します。
local enemy = {
Name = "Spike",
Health = 1000,
}
enemy.Name = "Rana"
print("The enemy's name is " .. enemy.Name)
- テストプレイを行い、出力ウィンドウを確認します。
キーとしての既存の変数
辞書は、スクリプトの他の部分で宣言された既存の変数と対話できます。次のコーディング例では、プレーヤーがエクスペリエンスに参加するときに変数を使用してプレーヤーの名前をキーとして追加し、ポイント値を 0 に設定します。
- ServerScriptServiceで、PlayerPoints という名前の新しいスクリプトを作成します。スクリプトで、Players Service を取得し、playerPointsという名前の空のディクショナリを作成します。
Players = game:GetService("Players")
local playerPoints = {
}
- 新しいプレーヤー変数のパラメーターを使用してプレーヤー ポイントを設定するローカル関数をコーディングします。関数をPlayers.PlayerAddedイベントに接続します
local playerPoints = {
}
local function setPoints(newPlayer)
end
Players.PlayerAdded:Connect(setPoints)
- 関数に、プレーヤーのName 、すべてのPlayerオブジェクトのプロパティ、およびテスト用の print ステートメントを取得する変数を追加します。
local function setPoints(newPlayer)
local name = newPlayer.Name
print("hello " .. name)
end
- 名前をplayerPointsディクショナリにキーとして挿入し、値 (プレイヤーのポイント) を 0 に設定します。
local function setPoints(newPlayer)
local name = newPlayer.Name
print("hello " .. name)
playerPoints[name] = 0
end
nameは変数として作成されているので、実際の変数名でアクセスできます。name が単なるキー名だった場合は、他の文字列と同じようにアクセスする必要があります ( playerPoints["name"] )。
- nameを使用してプレーヤーの名前を出力し、playerPoints[name] を使用して変数に一致するキーの値を出力します。
local function setPoints(newPlayer)
local name = newPlayer.Name
print("hello " .. name)
playerPoints[name] = 0
print( name .. " has " .. playerPoints[name] .. " points.")
end
- プロジェクトを実行し、出力ウィンドウを調べます。
完成したスクリプト
Players = game:GetService("Players")
local playerPoints = {
}
local function setPoints(newPlayer)
local name = newPlayer.Name
print("hello " .. name)
playerPoints[name] = 0
print( name .. " has " ..playerPoints[name] .. " points.")
end
Players.PlayerAdded:Connect(setPoints)
オプションのチャレンジ
以下に、さまざまな方法で辞書を使用する場合に当てはまるいくつかの課題を示します。これらのコードを構築できるかどうかを確認してください。
- プレイヤーに時間の経過とともにダメージを与えるトラップパーツを作成します。プレイヤーがトラップに触れたら、ダメージを与え、待ってから再びダメージを受けるようにします。
- 辞書にアクセスして、2 人のプレーヤーのうちどちらが最も多くのポイントを持っているかを確認する関数を作成します。
- 暗号、つまり、ある単語を別の単語に交換して「秘密」コードを作成するシステムを作成します。たとえば、文字「A」を「G」に交換する方法や、リンゴという単語をオレンジという単語に交換する方法などです。
辞書とpairs
pairs() は、辞書を反復処理するためによく使用される関数です。以下に例を示します。
local myDictionary = {
["Blue Player"] = "Ana",
["Gold Player"] = "Binh",
["Red Player"] = "Cate",
}
for key, value in pairs(myDictionary) do
print(key .. " is " .. value)
end
pairs() は、辞書要素のキー、値、またはその両方を操作するために使用できます。以下の for ループでは、最初の変数がキーです。2 番目の変数は値です。操作したい辞書は、pairs()に渡されます。
local inventory = {
["Gold Bricks"] = 43,
Carrots = 3,
Torches = 2,
}
print("You have:")
for itemName, itemValue in pairs(inventory) do
print(itemValue, itemName)
end
プログラムを実行すると、次の内容が出力されます。
You have:
43 Gold Bricks
3 Carrots
2 Torches
プレイヤーデータの管理
辞書の中に、さらに辞書を入れることができますので、管理しなくてはならないプレイヤーデータが複数ある場合は、下記のようなプログラムを実現可能です。なお、このプログラムは一般的に、次の第6章で学ぶ「モジュールスクリプト」にしてどこからでも呼べるようにすると良いでしょう。
下記の initData() はプレイヤー入室時に呼びます。initData() 内の 辞書 data の要素を増やすことで、複数のデータを管理することが可能です。
local playerData = {} -- キーはユーザID
function initData(player)
local data = {
Point = 0,
Hp = 100,
}
local userId = player.UserId
playerData[userId] = data
end
function setData(player,variable,value)
local userId = player.UserId
local data = playerData[userId]
data[variable] = value
end
function getData(player,variable)
local userId = player.UserId
local data = playerData[userId]
return data[variable]
end
setData() でデータが保存でき、getData() で取得できます。
local point = getData(player,"Point") + 1
setData(player,"Point",point)
setData(player,"Hp",200)
print( getData(player,"Point") )
local hp = getData(player,"Hp")
1つの辞書にプレイヤーデータをすべて入れると、DataStoreService を使用してのサーバーへのデータのロードやセーブが一度にできます。SetAsync/GetAsync は辞書データもサポートしています。
[ 5-3 配列の変更 ]
7 thoughts on “5-4 辞書の概要”
コメントを残す コメントをキャンセル
コメントを投稿するにはログインしてください。
こんにちは、いつも ありがとうございます。
辞書とpairsの最初の例題を実行すると 以下のエラーがでました。
Expected identifier when parsing expression, got Unicode character U+2003 (did you mean ‘ ‘?)
私自身 辞書の理解が乏しいので、エラーの意味が咀嚼できません。コメントいただけるでしょうか。
〜〜〜
local myDictionary = {
[“Blue Player”] = “Ana”,
[“Gold Player”] = “Binh”,
[“Red Player”] = “Cate”,
}
for key, value in pairs(myDictionary) do
print(key .. ” is ” .. value)
end
〜〜〜〜
自己レスです。英語をよく読めばよかったです。
下から2行目のprintの前に 全角スペースが2つ潜んでいました。
RobloxStudioの設定で全角スペースを発見しやすくする設定など無いのでしょうか。。。。
お騒がせしました。
全角スペースはよくありますよね。
Studio上では、文法エラーになりますので、赤いアンダーラインが表示されるかと思います。
こんにちは、お世話になります。
最後の「プレーヤーの管理」の前後を自力で埋めて、実行しようとしましたが、以下のエラーがでました。
サポートいただけるでしょうか。よろしくお願いいたします。
〜〜〜エラーコード
ServerScriptService.Script:20: attempt to index nil with ‘UserId’ – サーバー – Script:20
〜〜〜自作コード
local Players = game:GetService(“Players”)
local playerData = {} — キーはユーザID
function initData(player)
local data = {
Point = 0,
Hp = 100,
}
local userId = player.UserId
playerData[userId] = data
end
function setData(player,variable,value)
local userId = player.UserId
local data = playerData[userId]
data[variable] = value
end
function getData(player,variable)
local userId = player.UserId
local data = playerData[userId]
return data[variable]
end
— このイベントはゲーム入室時に1度だけ呼ばれる
local function onPlayerAdded(player)
print(player.Name..”が入室しました”)
player.CharacterAdded:Connect(onCharacterAdded)
player.CharacterRemoving:Connect(onCharacterRemoving)
initData(player)
end
— このイベントはゲーム退室時に1度だけ呼ばれる
local function onPlayerRemoved(player)
print(player.Name..”が退室しました”)
end
local point = getData(player,”Point”) + 1
setData(player,”Point”,point)
setData(player,”Hp”,200)
print( getData(player,”Point”) )
local hp = getData(player,”Hp”)
Players.PlayerAdded:Connect(onPlayerAdded)
Players.ChildRemoved:Connect(onPlayerRemoved)
local point = getData(player,”Point”) + 1
ここで実行すると、player は nil になりますよね。それがエラーの原因です。
player が取得できる場所で実行してください。
playerが追加されたときのイベントの発生順序などが 理解できていないようです。
このサイトの中に、それを解説するようなコンテンツがあれば、お教えいただけないでしょうか。
いそがないので、よろしくお願い致します。
イベントは登録された後に、発生可能な状態になります。
つまり、
Players.PlayerAdded:Connect(setPoints)
を実行した後から、setPoints が呼ばれるようになるということです。