Roblox コース mission04
レッツ・ショッピング!(後編)
■Chapter1 NPC と会話できるようにしよう
■Chapter2 コインがランダムに出るようにしよう
■Chapter3 GUI を作ろう
■Chapter4 GUI をプログラムでコントロールしよう
■Chapter5 デバッグをしよう
■【応用編】 買い物をする GUI を作ろう
■完成コード
1
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chapter1 NPC と会話できるようにしよう
NPC と会話できるようにする
前回の mission03 で作った NPC と会話で きるようにしていきます。NPC をクリック したら、NPC がしゃべりかけてくれるよう に作っていこうと思います。
NPC をクリックできるようにする
まずは NPC をクリックできるようにして いきます。
自動販売機と同じように ClickDetector を NPC に追加します。追加するときは NPC を Explorer から選択して、プラスボタン を押して追加するのでしたね。さらに Scri pt を追加して、NPCScriptという名前に しておきます。
クリックしたときに処理ができるように、
自動販売機と同様のコードを書いていきま す。クリックされたときに clicked という
関数が実行されるようにしていきます。 NPCScript 1
2 3 4 5 6 7 8
local npc = script.Parent local click = npc.ClickDetector
function clicked()
end
click.MouseClick:Connect(clicked)
2
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chat 機能を使う
NPC と会話できるように
Chat
という機能 を使います。Roblox Studio の Chat など の機能をコードから使う場合、game:GetService
という関数で取得して使います。続いて NPC がしゃべる内容を変数に入れ ておきます。今回は連想配列というものを 使ってみたいと思います。
連想配列
連想配列とは、Scratch や micratch のリ
ストのような機能です。今回のコードだと words という変数に文章を2つ入れて管理 してみたいと思います。リストは、リストに入れた順番で取得して いましたが、連想配列の場合はキーと呼ば れる文字で取得することができます。
まず、4 行目では変数 words をカラの配列 にしているコードです。{}と書きます。
5,6 行目でそれぞれ help1,help2 という キーで文章を入れています。こうすること で、リストのように数字ではなく、help1, help2 という文字でそれぞれの文章を取得 できるようになります。
連想配列の内容を取得する場合も値を入れ る場合も words[“help1”]のような書き方 で行います。
それでは次のページから実際に連想配列の 文章を表示させてみましょう。
NPCScript
1 2 3 4 5
6
7 8 9 10 11 12
local npc = script.Parent local click = npc.ClickDetector
local chat = game:GetService("Chat") local words = {}
words["help1"] = "誰かビルの上の宝を取ってき て!"
words["help2"] = "自動販売機でいいものが買える かも!"
function clicked()
end
click.MouseClick:Connect(clicked)
連想配列は、キーである文字か ら取得できる内容が予測できる というメリットがあります。
3
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chat で文章を出す
今回はクリックされるごとに内容を交互に 変えてみます。7 行目で count という変数 を作り、11 行目でクリックされた回数を 数えていきます。
文章を表示する場所を指定する必要がある ので 8 行目で NPC の頭のパーツである He ad を変数に入れておきます。
13 行目からの if の部分を見ていきます。if の条件で使っている「%」は、割った余り という意味の記号です。つまり、count を 2 で割った余りが1だったらという意味に なります。
if と end の間に
else
という文字が新しく 入っていますね。これは「もし~なら~で なければ~」というパーツの「でなけれ ば」という意味と同じです。count を 2 で 割った余りが 1 だったら 14 行目、でなけ れば 16 行目が実行されます。14,16 行目では Chat 機能を使って文章を 出す関数です。1つ目の引数で出す位置、
2つ目の引数で文章を指定します。
この時、連想配列を使っているので、wor ds[“help1”]のように書けば、文字である キーで表示したい文章を取得することがで きます。
NPCScript
6
7 8 9 10 11 12 13 14 15 16 17 18 19 20
words["help2"] = "自動販売機でいいものが買える かも!"
local count = 0 local head = npc.Head
function clicked() count += 1
if count % 2 == 1 then
chat:Chat(head, words["help1"]) else
chat:Chat(head, words["help2"]) end
end
click.MouseClick:Connect(clicked)
4
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
実際に実行して試してみましょう。NPC を クリックするたびに表示される文章が変わ るようになりました。
もしも自動販売機も会話できるようにした い場合は、自動販売機の一番上のオブジェ クトから Chat させることで実現できま す。このとき、あらかじめ名前を Top など 分かりやすい名前にしておくといいでしょ う。
5
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chapter2 コインがランダムに出るようにしよう
コインをランダムに置く
前回のミッションでコインを作りました。
このコインをランダムにいくつも置かれる ようにしていきましょう。
コインを複製する準備
ゲームの中にいくつもランダムに出すため には、コインを複製(クローン)してコイ ンをいっぱい出す必要があります。
そのための準備として、Coin を Workspac e から
ServerStorage
に移動します。Coi n をクリックしながら移動させて、Server Storage の場所でマウスを離すと移動でき ます。すると Coin がゲームから消えたと思いま す。ゲームの中からは消えますが、いつで も使えるように保存しておける場所が Ser verStorage という場所の役割です。
このようにオブジェクトを複製して使いた い場合は ServerStorage という場所にオ リジナルを入れておいて使います。
コードから ServerStorage の Coin を複製 してゲームの世界に出すように命令するこ とで、Coin のコピーがゲームの世界に出て くるようになります。
コインを複製するコードの追加
コインを複製するコードを書いていきまし ょう。複製するコードはゲーム全体に関わ るようなコードなので、ServerScriptSer
vice
にコードを書いていきます。ServerS criptService にCreateCoinScript
という 名前で Script を追加します。6
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
複製(クローン)するコード
それでは Coin を複製するコードを書いて いきましょう。
1 行目では ServerStorage にアクセスする ために GetService という関数で取得して います。2 行目では ServerStorage の中に 入れた Coin を変数に入れています。
ゲーム中は 2 秒ごとにコインが出続けるよ うにするため、while と wait を使います。
5 行目では、Coin を複製する関数を呼びま す。Clone()という関数を呼び出すと、複 製されたオブジェクトが作られるので変数 に入れておきます。Scratch の「クローン を作る」というブロックと同じ意味です。
複製したオブジェクトは Workspace に入 れてあげることでゲームの世界に出すこと ができるので、Parent を workspace にし ます。
ランダムな位置に出す
Coin が出てくる位置をランダムに出るよう にしていきましょう。
準備として 7 行目の
Random.new()でラ
ンダムな値を作れるようにします。Scratc h や micratch でもありましたね。8,9 行目で X 方向、Z 方向に対してランダ ムな値を作ります。NextIntegerという 関数は、例えば 8 行目だと-180 から 100 までのランダムな整数を作ってくれる関数 です。範囲は皆さんにお任せします。高さ は固定でいいので Y 方向は作りません。
CFrame で位置を指定します。位置を指定 するときは CFrame.new で新しい CFram e を作って代入すると指定することができ ます。
CreateCoinScript 1
2 3 4 5 6 7 8
local storage = game:GetService("ServerStora ge")
local coin = storage.Coin
while true do
local clone = coin:Clone() clone.Parent = workspace wait(2)
end
CreateCoinScript 1
2 3 4 5 6 7 8 9 10 11 12
local storage = game:GetService("ServerStora ge")
local coin = storage.Coin
while true do
local clone = coin:Clone() clone.Parent = workspace local random = Random.new()
local x = random:NextInteger(-180,100) local z = random:NextInteger(-180,200) clone.CFrame = CFrame.new(x,2,z) wait(2)
end
7
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
では実行して確かめてみましょう。する と、2 秒ごとに Coin がゲームの中に出て くるようになります。
8
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chapter3 GUI を作ろう
GUI とは
Chapter3 では
GUI
を作っていきましょ う。その前に GUI とは何でしょうか。GUI とは Graphical User Interface の略 です。RPG の会話や買い物をするときにア イテムを選ぶ画面が出てくることがありま すよね。このようにゲームに関する情報を 表示するものが GUI です。
GUI を作る
GUI を作る場合は Explorer の中にある
St arterGui
という場所に作っていきます。S tarterGui を選択し、プラスボタンからSc reenGui
を選択します。ScreenGui はゲ ーム画面に表示するための GUI です。さらに ScreenGui を選択し、プラスボタン から
TextLabel
を選択します。TextLabel は文字を表示するパーツです。すると画面左上に白い四角が出てきたと思 います。これで文字の表示ができました。
クエストの GUI を作る
今回は GUI を使って、今プレイヤーにやっ てほしい事、つまりクエストの内容を表示 する GUI を作っていきましょう。
まずは表示する文字を変えていきます。Ex plorer から TextLabel を選択して Properti es を見てみます。
その中の
Text
という項目を「NPC に話しかけよう!」に変えてあげます。すると表
示される文字が変わります。9
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
他のプロパティも設定していきます。
TextSize
というプロパティを 14 から 20 に変えましょう。すると文字が大きくなり ます。BackGroundColor3というプロパ ティとTextColor3
というプロパティも好 きな色に変えましょう。それぞれ背景と文 字の色が変わります。位置の調整
GUI を表示する位置を調整しましょう。直 接マウスでクリックして移動することもで きますが、プロパティから設定すると、さ らに細かく設定が可能です。
Position
というプロパティを設定してい きます。左にある矢印をクリックしていく とさらに表示されていきます。10
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Position は X と Y の 2 つの方向が設定でき ます。ゲームの中のオブジェクトは x,y,z の 3 方向でしたが、GUI は画面の縦(Y)
方向と横(X)方向の2つで表現します。
一番左上が 0 で、右側に行くほど X が大き くなり、下側に行くほど Y が大きくなりま す。
X,Y の中にさらに Offset と Scale というプ ロパティがあります。
Offset
は左上の位置からどれだけ移動させ るかを指定できます。例えば X の offset を 50 にすると、ゲーム画面の大きさに関係 なく、50 だけ右に移動して表示します。Scale
は画面の大きさに対しての相対的な 位置を指定することができ、0~1 の値で指 定します。例えば X の scale を 0.5 にする と、画面の横方向の半分の位置に出てきま す。画面の大きさを変えると、半分の位置 に移動していることが分かります。例では図のような Position に指定してみま す。
offset は画面の大きさに関わら ず指定できる値、scale が画面に 対してどの位置にするかを指定 できる値です。
Y
X
11
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
大きさを指定する
大きさを指定する場合は
Size
というプロ パティを設定します。こちらも Position と 同じように X,Y それぞれに Offset と Scale を設定できます。例では図のような設定にします。すると、
左上に細長く表示されました。
この GUI は最初に表示する GUI なので、S creenGui の名前を
StartGui
という名前 に変えて分かりやすくしておきましょう。さらに GUI を追加する
NPC に話しかけた後に違うメッセージを表 示するために、もう1つ GUI を追加しま す。StartGui を右クリック→Duplicate を クリックして複製します。複製した GUI は
QuestGui
という名前にしておきます。QuestGui の方の TextLabel を選択しま す。先ほどのように Text プロパティを書 き換える方法もありますが、ゲーム画面に 表示されている文字をダブルクリックして も文字の編集ができます。
どちらの方法でも大丈夫なので、「コイン
を集めてパワーアップした宝を取りにいこ う!」という文章に変えます。
2 つの GUI の位置が被っていますが、今は そのままでOKです。StartGui、QuestGui の
Enabled
というプロパティを変更する と表示非表示を切り替えられます。(TextL abel ではなく親のオブジェクトなので注 意!)TextLabel ではなく StartGui もしくは
QuestGui を選択
12
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
クリアしたときの GUI も作る
クリアしたときに表示される GUI も作りま す。今度は新しく ScreenGui を作り、名前 を
ClearGui
にしておきます。また TextLa bel も追加しておきましょう。TextLabel を選択してプロパティを変えて いきます。
Text を「Clear!」にします。大きさを変え る場合、TextScaledという項目にチェッ クを入れることで変えることもできます。
チェックを入れると、GUI の大きさに応じ て文字の大きさが自動的に変わるようにな ります。
Size と Position も設定します。例では画 面の横幅いっぱいに出るようにしてみまし た。例のように offset と scale を組み合わ せて指定することもできます。
13
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
図のような GUI になったかと思います。
この GUI はクリアしたときだけ出したいの で、ClearGui の Enabled プロパティのチ ェックを外しておきましょう。
14
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chapter4 GUI をプログラムでコントロールしよう
GUI の管理について
GUI をコードから管理したいと思います。
その前に GUI について少し解説します。
今の状態でゲームを実行すると、Explorer を見てみると GUI は Players の各プレイヤ ーの中に作られていることが分かります。
Players というのは各プレイヤーに関する 情報を管理する所です。なぜ GUI がこの中 にあるかというと、GUI はプレイヤーごと
に表示を管理する必要があるからです。
ゲーム全体に影響するコードではなく、特
定のプレイヤーにだけ影響するコードを書
いていく必要があります。この時、ゲーム全体を管理するサーバー側 とプレイヤーのそれぞれの環境(クライア
ント側)で通信をすることで実現していき
ます。これは Roblox Studio の仕様上そう しないと GUI の管理ができませんので、そ ういうものだと思ってください。実際にコードを書いてみる
実際にコードを書いてみてみましょう。ま ずは StartGui と QuestGui の表示を切り替 えてみたいと思います。
最初は StartGui が表示されていて、NPC に話しかけたら QuestGui に切り替えるよ うにしてみます。なので、最初は QuestGu
例えばクリアする GUI を出した い場合、クリアしたプレイヤー にだけ GUI を出したいですよ ね。このようにプレイヤーごと に GUI の管理が必要です。
サーバー
(ゲームの世界)
プレイヤーA プレイヤーB
プレイヤーA がクリアしたよ!
GUI を表示! こっちは関係が無い
15
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
i の Enabled をオフにして StartGui だけ表 示されている状態にしておきましょう。
NPC のコードに追加する
NPC に話しかけたときに GUI の表示を変 えていきます。まずは NPCScript に追加し ていきます。
今まで書いてきた Script は、ゲーム全体に 関わるサーバー側で動作するコードです。
NPCScript もサーバー側のコードなので、
クライアント側に NPC に話しかけたこと を教えてあげる必要があります。このとき 使うのが
Event
という機能です。Scratch のメッセージに似ています。実はこの Event は今までにも使っていま す。NPCScript でもクリックされたときに MouseClick という Event に clicked とい う関数を登録していました。このように特 定の何かが起こったときに、登録していた 動作を実行できるのが Event です。
Event は自分でオリジナルのものを作るこ とができます。
Event を作る
まずはオリジナルの Event を作っていきま す。サーバー側からクライアント側に送る ためには
RemoteEvent
という専用のイ ベントを作ります。RemoteEvent は
ReplicatedStorage
と いうものを親にする決まりがあるので設定 します。これについてはそういう決まりだ と思っておきましょう。Event の名前を
Name
で設定します。Qu estEvent という名前にしておきます。NPCScript
7 8 9 10 11 12
local count = 0 local head = npc.Head
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "QuestEvent"
16
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
サーバー側からどのプレイヤー(クライア ント)に Event を教えてあげればいいのか を指定してあげる必要があります。
VendingMachineScript の PlayerSetup の 内容をそのままコピーして、プレイヤーの 情報を取得しておくようにします。今は 1 人用前提で作っているので、このコードで 大丈夫です。マルチプレイに対応する書き 方は他のミッションで解説します。
続いて clicked 関数です。
話しかけた回数が 2 回になれば NPC との 会話が終わったことになるので count==2 を if 文で使います。
このとき、event:FireClinentという関数 でクライアント側に作った Event が起きた ことを教えてあげることができます。
先ほど取得しておいたプレイヤー情報を引 数にすることで、どのプレイヤーに教えて あげるのかを指定してあげています。
NPCScript
10 11 12 13 14 15 16 17 18 19 20
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "QuestEvent"
local players = game:GetService("Players") local player
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
NPCScript
22 23 24 25 26 27 28 29 30 31 32 33 34
function clicked() count += 1
if count % 2 == 1 then
chat:Chat(head, words["help1"]) else
chat:Chat(head, words["help2"]) end
if count == 2 then event:FireClient(player) end
end
クライアント QuestEvent が起きたよ!
オリジナルの Event を作ると特 定のタイミングで特定の Event が起きたことを通知することが できます。
サーバー
17
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Event を受け取る
Event を作って通知することができまし た。次にクライアント側で Event を受け取 ってみましょう。
そのために QuestGui に LocalScript を追 加します。LocalScriptは今まで書いてい た Script とは違い、クライアント側でのみ
動作するコード、つまり特定のプレイヤー
にだけ影響するコードです。GUI のように プレイヤーごとに管理してあげる処理を書 く時に使います。名前を
QuestLocalScript
にしておきま す。では早速中身を書いていきましょう。
2,3 行目で先ほど NPCScript で作った Que stEvent を取得します。WaitForChild は Q uestEvent という子供が見つかるまで待つ 関数です。FindFirstChild と似ています。
onFired という関数は、QuestEvent が起 きたときに実行したい関数です。今回は親 である QuestGui の Enabled を変えて、表 示するようにします。ですので Enabled を true にしてあげます。
9 行目では Touched や MouceClick の時と 同じように OnClinentEvent に onFired 関 数を登録します。こうすることで、Quest Event が起きたら onFired 関数が実行され るようになります。
QuestLocalScript
1 2
3
4 5 6 7 8 9
local quest = script.Parent
local replicatedStorage = game:GetService("Re plicatedStorage")
local event = replicatedStorage:WaitForChild("
QuestEvent")
function onFired() quest.Enabled = true end
event.OnClientEvent:Connect(onFired)
18
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
StartGui を非表示にする
StartGui は逆に話しかけたときに非表示に してあげたいですよね。
StartGui にも同様に LocalScript を追加 し、名前を
StartLocalScript
にします。QuestLocalScript と違う点は Enabled を f alse にする点だけなので、コピー&ペース トして 6 行目を false 変えておきます。
また、1 行目で変数を作るときの名前も合 わせて変えておくと、より丁寧ですね。
実行すると、2 回クリックしたら GUI が切 り替わってくれます
クリアしたときに GUI を表示
もう1つ GUI を作っていました。ClearGu i です。こちらをクリアしたときに出すよ うにしてみましょう。
このゲームは何をしたらクリアになるかと いうと、宝を取ったときでしたね。宝を取 ったときのコードは TreasureScript に書 いていました。
StartLocalScript
1 2
3
4 5 6 7 8 9
local start = script.Parent
local replicatedStorage = game:GetService("Re plicatedStorage")
local event = replicatedStorage:WaitForChild("
QuestEvent")
function onFired() start.Enabled = false end
event.OnClientEvent:Connect(onFired)
NPCScript と同じように、TreasureScript に宝を取ったときに ClearEvent が通知され るように自分で書いてみよう!
?
19
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
TreasureScipt を書いてみましょう。
実はほとんど NPCScript に書いた内容と同 じです。Event の名前を ClearEvent に し、FireClient を呼ぶ位置を 20 行目にし てあげればいいですね。
このとき、4 行目で Event を作っています が、このコードは onTouched 関数よりも 上に書くようにしましょう。上から順に実 行されるので、変数を使う前に変数を作っ ておく必要があります。関数も同様です。
TreasureScript
1 2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26
local treasure = script.Parent
local sound = workspace["Turn Around (sting b)"]
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "ClearEvent"
local players = game:GetService("Players") local player
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
function onTouched(hit)
local humanoid = hit.Parent:FindFirstChild("H umanoid")
if humanoid then event:FireClient(player) sound:Play()
treasure.Parent:Destroy() end
end
treasure.Touched:Connect(onTouched) 変数や関数は呼び出す行の上で
作っておく必要があります。
20
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
ClearGui で Event を受け取るコードを書 きます。これも QuestLocalScript とほぼ 同じです。
LocalScript を
ClearLocalScript
という 名前で作ります。QuestLocalScript の内容をコピー&ペース トし、変数名と Event の名前だけを変えて おきましょう。
こうすることで、宝を取ったときに Clear!
という GUI が表示されるようになりまし た。
ClearLocalScript
1 2
3
4 5 6 7 8 9
local clear = script.Parent
local replicatedStorage = game:GetService("Re plicatedStorage")
local event = replicatedStorage:WaitForChild("
ClearEvent")
function onFired() clear.Enabled = true end
event.OnClientEvent:Connect(onFired)
21
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
Chapter5 デバッグをしよう
デバッグとは
Chapter5 ではデバッグの方法について解 説します。デバッグとは、エラーなどが起 きてゲームが動かないときに、エラーの原 因を探して直すことです。
デバッグの方法を解説するために、適当な 位置に Block を追加して、名前を
ErrorPa rt にします。そして ErrorScript
という S cript を追加します。このオブジェクトは、この Chapter が終わ ったあとに消します。
エラーの見つけ方
例えば、図のように 2 行目で変数の名前を 打ち間違えたとします。
このようなときは図のように青い線が引か れて、ここが間違っていると教えてくれま す。
この状態で実行すると、Output に赤い文 字でエラーを教えてくれます。ただし、エ ラーメッセージはすべて英語なので、なか なか意味が分からないと思います。
そういう時は、エラーメッセージの行をク リックしてみましょう。すると、エラーが 出ている場所に自動的に移動してくれま す。
このように Output にエラーが出たとき は、メッセージをクリックしてエラーが出 ている場所に移動してエラーの原因を探す ようにしましょう。
ErrorScript
1 2
local test = 1 testt += 1
22
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
print を使う
print という関数があります。これを上手 く使うと、エラーの原因を探しやすくなり ます。
例えば、VendingMachineScript を見てみ ます。Clicked という関数は if がたくさん 出てきてコードの流れが分かりづらいの で、エラー探しが難しいです。
こういうときは、print を色々なところに 入れることで、どの処理まで実行されたか を確認することができます。
実行して自動販売機をクリックすると、
Output は図のようになります。このよう に print を仕込んでおくと、複雑なコード でもどこまでの処理が実行されているかを 確認することができます。
今回はコインが 0 枚のときにクリックした ので、15 行目の if 文は通りません。です ので 16 行目で入れた print が実行されて いないのが正しいです。
チェック用に入れた print は、用がなくな ったら消しておくと Output がきれいに保 たれますので、print は消しておきましょ う。また、ErrorPart,ErrorScript も消して おいて大丈夫です。
print で出す文字はゲームを公開 するときは出てきませんので、
どんどん使って大丈夫です。
VendingMachineScript
7 8 9 10 11
12 13 14 15 16 17 18 19 20 21 22 23 24
function clicked()
local leaderstats = player.leaderstats print("leaderstats")
if leaderstats then
local coinValue = leaderstats:FindFirstChild("
coin")
print("coin") if coinValue then
print("coinValue")
if coinValue.Value > 0 then print("character")
local character = player.Character character.Humanoid.JumpPower *= 2 coinValue.Value = 0
sound:Play() end
end end end
エラーでは出ない、ゲームのロ ジックの確認をするのに print は とても使えます。
23
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
【応用編】 買い物をする GUI を作ろう
買い物をする GUI の作成
買い物をするときに、どれを買うか選べる ような GUI を作っていきましょう。
新しく ScreenGui を追加し、名前を
Vend ingMachineGui
にします。今回はアイテムを選べる、つまり表示する 項目が複数あります。このようなときは、
Frame
というパーツで管理します。いろ いろなパーツを入れておく枠のイメージで す。VendingMachineGui を選択し、プラスボ タンから Frame をクリックします。
Frame の Position と Size を設定して、買 い物をする GUI をどこに出すかを設定しま す。例ではそれぞれ図のように設定しま す。
24
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
表示する枠の部分ができたので、次は中身 を作っていきます。
Frame を選択し、プラスボタンから TextL abel を追加します。すると、Frame の左 上に表示されました。このように Frame の中に作ったパーツは、Frame の左上が
Position(0,0)の位置になります。
TextLabel の Size を図のように設定しま す。Position はそのままで OK です。
さらに BackGoundColor3 を黒に、TextCo lor3 を白にします。文字の大きさは TextS caled にチェックを入れて自動的に調整さ れるようにします。
文字の内容も「買い物リスト」に変えてお きましょう。
Frame の子供のパーツは、画面 の左上ではなく Frame の左上が 0 の位置になります。
scale も同様に最大の大きさが Frame の右側下側になります。
25
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
ボタンの作成
次に、アイテムを3つ表示するパーツを作 っていきます。アイテムはクリックすると 買えるようにしたいので、今回は TextLab el ではなく
TextButton
というボタンのパ ーツを使います。TexButton はマウスクリ ックができる文字を表示するパーツです。TextButton のプロパティを設定していき ます。Position は、Y の offset を 50 にし ます。さきほど作った「買い物リスト」と 表示する TextLabel の縦の大きさが 50 だ ったからです。
Size は TextLabel と同様の設定にします。
文字の大きさは TextSize を 30 にします。
ボタンの文字は左から詰めて表示したいの で、TextXAlignmentという項目を Cent er から Left に変えます。
まったく同じやり方で、TextButton を 4 つ並べます。Position の Y だけ 50 ずつず らすと図のようになります。4つ目は買い 物をせずに Gui を閉じるボタンにする予定 です。
さらに表示する文字も変えていきます。図 のように必要なコインとパワーアップする 内容を書いてみました。
パーツが増えてきたので、それぞれ名前を 上から図のように変えておくと分かりやす いです。
最後に、VendingMachineGui の Enabled をオフにして非表示にしておきましょう。
26
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
GUI を表示するコード
それでは自動販売機をクリックしたときに 買い物をする GUI が表示されるようにして いきましょう。
VendingMachineScript に追加していきま す。
VendingMachineEvent
という Event を 新たに作り、クリックされたときに FireCli ent を呼んであげます。すると自動販売機 をクリックしたときに Event が通知される ようになります。続いて、VendingMachineGui に LocalScri pt を追加します。名前は
VendingMachi neLocalScript
にしておきましょう。VendingMachineLocalScript は StartGui のときとほぼ同じなのでコピー&ペースト してしまいましょう。変数名や Event の名 前、Enabled の値だけ注意して変えておき ます。
VendingMachineScript
1 2 3 4 5
6 7 8 9 10 11
local vendingMachine = script.Parent local click = vendingMachine.ClickDetector local players = game:GetService("Players") local player
local sound = vendingMachine["\"Goldrush \"
\"Win\"\"\""]
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "VendingMachineEvent"
function clicked()
event:FireClient(player)
VendingMachineLocalScript
1 2
3 4 5 6 7 8 9
local vending = script.Parent
local replicatedStorage = game:GetService("Re plicatedStorage")
local event = replicatedStorage:WaitForChild("
VendingMachineEvent")
function onFired()
vending.Enabled = true end
event.OnClientEvent:Connect(onFired)
27
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
ボタンを押して閉じるコード
次に、「さようなら」をクリックしたら GU I を閉じるようにしてみます。
ByeTextButton に LocalScript を
ByeLoc alScript
という名前で追加し、コードを書 いていきます。このボタンがクリックされたときの Event は MouseButton1Click という Event を使 用します。
この Event に clicked という関数を登録し ます。この関数はボタンの親の親、つまり VendingMachineGui の Enabled を false にするコードです。
ここまでで1度実行して確認してみましょ う。自動販売機をクリックすると買い物リ ストが出てきて、「さようなら」をクリッ クすると閉じれば OK です。
ボタンを押して買い物をする
閉じるボタンはできたので、ほかのボタン を押したときにパワーアップできるように していきしょう。
今まではサーバーからクライアントに Eve nt を通知していましたが、ボタンを押した ときの処理はクライアント、買い物の処理 はサーバー側で書いていました。なので今 度はクライアント側である Gui からサーバ ー側に Event を通知してみます。
買い物をするコードは VendingMachineSc ript に書いてきましたが、ゴチャゴチャし てきたので、買い物の処理は別に分けてお きます。
ServerScriptService に Script を
ShopSc ript
という名前で追加します。VendingMachineLocalScript
1 2 3 4 5 6 7
local button = script.Parent
function clicked()
button.Parent.Parent.Enabled = false end
button.MouseButton1Click:Connect(clicked)
28
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
サーバー側の処理
ShopScript を書いていきます。3行目ま では今までと同じです。
9行目はクライアント側からサーバー側に 通知する Event なので、OnServerEvent という関数を使って Event に登録できるよ うにします。
登録する関数は onFired です。このとき、
どのプレイヤーからの Event なのか(playe r)と、必要なコインの枚数 (cost)の情報 を受け取るために引数をそれぞれ追加しま した。
このように、Event は引数をつけて情報を 付け加えることが可能です。
クライアント側の処理
ボタンを押したときに Event を通知しまし ょう。
EffectButton に LocalScript を
EffectLoc alScript
という名前で追加します。中身は今までとほとんど同じです。ShopE vent を作り、クリックされたタイミングで 通知します。
今回はクライアント側からサーバー側に通 知するので
FireServer
という関数を使い ます。さきほどサーバー側では player と cost と いう2つを引数にとるようにしていまし た。プレイヤーに関する情報は書かなくて も最初から引数に入っているので、必要な コインの枚数である5を引数に入れるだけ で大丈夫です。
このボタンを押したときも GUI を閉じたい ので8行目も書いておきましょう。
ShopScript
1 2 3 4 5 6 7 8 9
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "ShopEvent"
function onFired(player, cost)
end
event.OnServerEvent:Connect(onFired)
EffectLocalScript
1 2
3 4 5 6 7 8 9 10 11
local effect = script.Parent
local replicatedStorage = game:GetService("Re plicatedStorage")
local event = replicatedStorage:WaitForChild("
ShopEvent")
function clicked() event:FireServer(5)
effect.Parent.Parent.Enabled = false end
effect.MouseButton1Click:Connect(clicked)
29
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
他のボタンにも同じことをする
スピードアップもジャンプ力アップも同じ なので、同じように作っていきます。
EffectLocalScript の内容をコピー&ペース トして、必要なコインの枚数だけ 10 と 30 に変えておきましょう。
図では省略しますがコードは最後のページ の完成コードに載っています。
買い物をするコードの移動
それでは買い物をする処理を書いていきま しょう。VendingMachineScript の clicke d 関数に書いていた、買い物をする処理を ごっそり ShopScript の OnFired の中に貼 り付けます。FireClinet の所だけ残してお きましょう。
このとき、変数 sound が取得する音は Ve ndingMachine の子供にあるので、4行目 のように書き直しましょう。
onFired という関数は、cost という引数に 買い物に必要なコインの枚数が入ってくる ようにしました。
この枚数分持っていたら、その枚数だけコ インを使ってパワーアップするように書い ていけばよさそうですね。
ShopScript
1 2 3 4
5 6 7 8 9
10 11
12 13 14 15 16 17 18 19 20
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "ShopEvent"
local sound = workspace.VendingMachine["\"G oldrush \"\"Win\"\"\""]
function onFired(player, cost) local leaderstats = player.leaderstats if leaderstats then
local coinValue = leaderstats:FindFirstChild("
coin")
if coinValue then
if coinValue.Value > 0 then local character = player.Character character.Humanoid.JumpPower *= 2 coinValue.Value = 0
sound:Play() end
end end end
event.OnServerEvent:Connect(onFired)
30
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
VendingMachineScript を整理します。
VendingMachineScript の clicked 関数 で、Event を通知する箇所以外全部持って いきました。また、音を鳴らす処理も買い 物をしたときするので、変数 sound を作っ ている箇所も削ります。
かなりスッキリしましたね。
VendingMachineScript
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20
local vendingMachine = script.Parent local click = vendingMachine.ClickDetector local players = game:GetService("Players") local player
local sound = vendingMachine["\"Goldrush \"
\"Win\"\"\""]
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "VendingMachineEvent"
function clicked() event:FireClient(player)
end
click.MouseClick:Connect(clicked)
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
31
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
買い物をする処理を書く
いよいよ最後です。コインの枚数に応じた 処理を書いていきます。
cost が 5 のときは、エフェクトを作るよう にしています。このとき、コインを5枚以 上持っていないと買い物ができないですよ ね。
このようなとき11行目のように2つの条 件が正しいときだけ実行されるようにする には、andで2つの条件をつなげることが できます。Scratch や micratch の「か つ」というブロックと同じです。
cost が 5 かつ、5枚以上コインを持ってい たら 12~14 行目のコードでエフェクトが 作られるようになるわけです。エフェクト は何となく頭につけるようにしてみました ので、Parent を character.Head にしてい ます。
このときに、15 行目で5枚だけコインが 減るように変更しましょう。「-=」と書け ば、左の値を右の値だけ引く計算ができま す。16 行目で音を鳴らしておきます。
同じように10枚、30枚のときにそれぞ れスピードアップとジャンプ力アップをす るコードを書きます。「*=」と書くと、右 の値の分だけ左の値にかけ算できます。
ShopScript
6 7 8 9
10 11
12 13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 32 33 34
function onFired(player, cost)
local leaderstats = player.leaderstats if leaderstats then
local coinValue = leaderstats:FindFirstChild("
coin")
if coinValue then
if cost == 5 and coinValue.Value >= 5 the n
local effect = Instance.new("Fire") local character = player.Character effect.Parent = character.Head coinValue.Value -= 5
sound:Play() end
if cost == 10 and coinValue.Value >= 10 t hen
local character = player.Character character.Humanoid.WalkSpeed *= 2 coinValue.Value -= 10
sound:Play() end
if cost == 30 and coinValue.Value >= 30 t hen
local character = player.Character character.Humanoid.JumpPower *= 2 coinValue.Value -= 30
sound:Play() end
end end end
32
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
実際に実行してみましょう。
確認するためにコインを集めるのが面倒な 場合は、LeaderboardScript の 10 行目で 設定している、最初のコインの枚数を一時 的に増やすと確認が楽です。
エフェクトを選ぶと、5枚使って頭が燃え ます。他のボタンもスピードアップした り、ジャンプ力が上がったりするか確認し ましょう。
最後に BGM をアスレチックゲームと同じ ように追加しておくといいですね。Playin g と Looped のチェックを忘れないように しましょう。また、Leaderboard の値を変 えていたら 0 に戻しておきましょう。
LeaderboardScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14
local players = game:GetService("Players")
function leaderboardSetUp(player)
local leaderstats = Instance.new("Folder") leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local coin = Instance.new("IntValue") coin.Name = "coin"
coin.Value = 50
coin.Parent = leaderstats end
players.PlayerAdded:Connect(leaderboardSetU p)
コードの確認をしたい場合に一 時的に数字をいじって楽をする といいですね。
33
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
お疲れ様でした!
今回のミッションは特に GUI の表示非表示を切り替えるコードが大変でした ね・・・。でも GUI を作ることができるとゲームの面白さがグン!と上がり ます!Roblox Studio の仕様の話もあるので細かいことは置いておいて、何と なく分かっていれば OK ですよ。
次のミッションから新しいゲームを作ります!
それでは次のミッションでまた会いましょう!
34
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
完成コード
TreasureScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
local treasure = script.Parent
local sound = workspace["Turn Around (sting b)"]
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "ClearEvent"
local players = game:GetService("Players") local player
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
function onTouched(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid") if humanoid then
event:FireClient(player) sound:Play()
treasure.Parent:Destroy() end
end
treasure.Touched:Connect(onTouched)
35
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
LeaderboardScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14
local players = game:GetService("Players")
function leaderboardSetUp(player)
local leaderstats = Instance.new("Folder") leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local coin = Instance.new("IntValue") coin.Name = "coin"
coin.Value = 0
coin.Parent = leaderstats end
players.PlayerAdded:Connect(leaderboardSetUp)
36
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
CoinScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
local coin = script.Parent
local players = game:GetService("Players") local sound = workspace["Blap 2"]
function onTouched(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid") if humanoid then
--コインの値を 1 増やす
local player = players:GetPlayerFromCharacter(hit.Parent) local leaderstats = player.leaderstats
if leaderstats then
local coinValue = leaderstats:FindFirstChild("coin") if coinValue then
coinValue.Value += 1 sound:Play()
end end
coin:Destroy() end
end
coin.Touched:Connect(onTouched)
while true do
coin.CFrame *= CFrame.Angles(0,math.rad(5),0) wait()
end
37
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
VendingMachineScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
local vendingMachine = script.Parent local click = vendingMachine.ClickDetector local players = game:GetService("Players") local player
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "VendingMachineEvent"
function clicked() event:FireClient(player) end
click.MouseClick:Connect(clicked)
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
38
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
NPCScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
local npc = script.Parent local click = npc.ClickDetector
local chat = game:GetService("Chat") local words = {}
words["help1"] = "誰かビルの上の宝を取ってきて!"
words["help2"] = "自動販売機でいいものが買えるかも!"
local count = 0 local head = npc.Head
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "QuestEvent"
local players = game:GetService("Players") local player
function playerSetUp(p) player = p
end
players.PlayerAdded:Connect(playerSetUp)
function clicked() count += 1
if count % 2 == 1 then
chat:Chat(head, words["help1"]) else
chat:Chat(head, words["help2"]) end
if count == 2 then event:FireClient(player) end
end
click.MouseClick:Connect(clicked)
39
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
CreateCoinScript
1 2 3 4 5 6 7 8 9 10 11 12
local storage = game:GetService("ServerStorage") local coin = storage.Coin
while true do
local clone = coin:Clone() clone.Parent = workspace local random = Random.new()
local x = random:NextInteger(-180,100) local z = random:NextInteger(-180,200) clone.CFrame = CFrame.new(x,2,z) wait(2)
end
QuestLocalScript
1 2 3 4 5 6 7 8 9
local quest = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("QuestEvent")
function onFired() quest.Enabled = true end
event.OnClientEvent:Connect(onFired)
StartLocalScript
1 2 3 4 5 6 7 8 9
local start = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("QuestEvent")
function onFired() start.Enabled = false end
event.OnClientEvent:Connect(onFired)
40
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
ClearLocalScript
1 2 3 4 5 6 7 8 9
local clear = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("ClearEvent")
function onFired() clear.Enabled = true end
event.OnClientEvent:Connect(onFired)
VendingMachineLocalScript
1 2 3 4 5 6 7 8 9
local vending = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("VendingMachineEvent")
function onFired() vending.Enabled = true end
event.OnClientEvent:Connect(onFired)
41
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
ShopScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
local event = Instance.new("RemoteEvent") event.Parent = game.ReplicatedStorage event.Name = "ShopEvent"
local sound = workspace.VendingMachine["\"Goldrush \"\"Win\"\"\""]
function onFired(player, cost)
local leaderstats = player.leaderstats if leaderstats then
local coinValue = leaderstats:FindFirstChild("coin") if coinValue then
if cost == 5 and coinValue.Value >= 5 then local effect = Instance.new("Fire")
local character = player.Character effect.Parent = character.Head coinValue.Value -= 5
sound:Play() end
if cost == 10 and coinValue.Value >= 10 then local character = player.Character
character.Humanoid.WalkSpeed *= 2 coinValue.Value -= 10
sound:Play() end
if cost == 30 and coinValue.Value >= 30 then local character = player.Character
character.Humanoid.JumpPower *= 2 coinValue.Value -= 30
sound:Play() end
end end end
event.OnServerEvent:Connect(onFired)
42
©D-SCHOOL All Rights Reserved. レッツ・ショッピング!(後編)
EffectLocalScript
1 2 3 4 5 6 7 8 9 10
local effect = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("ShopEvent")
function clicked() event:FireServer(5)
effect.Parent.Parent.Enabled = false end
effect.MouseButton1Click:Connect(clicked)
SpeedLocalScript
1 2 3 4 5 6 7 8 9 10
local speed = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("ShopEvent")
function clicked() event:FireServer(10)
speed.Parent.Parent.Enabled = false end
speed.MouseButton1Click:Connect(clicked)
JumpLocalScript
1 2 3 4 5 6 7 8 9 10
local jump = script.Parent
local replicatedStorage = game:GetService("ReplicatedStorage") local event = replicatedStorage:WaitForChild("ShopEvent")
function clicked() event:FireServer(30)
jump.Parent.Parent.Enabled = false end
jump.MouseButton1Click:Connect(clicked)