プレイヤーの着順で、金、銀、銅などの異なるメダルを授与したい場合があります。
プレイヤーにメダルを授与するために、各メダルに対して個別に if 文を書くこともできますが、elseif を使用することにより、コンパクトで高速なコードが実現できます。
if/then 文が実行されると、最初に見つかった真の条件だけが実行されます。以下は elseif を使用した場合と使用しない場合のコード比較です。elseif の場合、end は一度だけ入力する必要があり、コードが非常に短くなっている点に注目してください。
elseif なし | elseif あり |
---|---|
if プレイヤーが1位 then 金メダルを獲得する end if プレイヤーが2位 then 銀メダルを獲得する end if プレイヤーが3位 then 銅メダルを獲得する end | if プレイヤーが1位 then 金メダルを獲得する elseif プレイヤーが2位 then 銀メダルを獲得する elseif プレイヤーが3位 then 銅メダルを獲得する end |
レース用コースを作成する
このプロジェクトでは、プレイヤー1人用のパルクールコースを作成します。プレイヤーは完走までにかかったタイムにより、異なるメダルが与えられます。まず、コースにスタートとゴール地点を配置します。次にプレイヤーのタイムを計り、異なる種類のメダルを与えるスクリプトを作成します。
パーツとスクリプトを作成する
- FinishLine という名前のアンカーにしたパーツを作成し、ParkourScript という名前のスクリプトを追加します。テストを早くするために、スタートとゴール地点を近くに設置します。ゴール地点はスクリプトを作成した後でも移動させることができます。
- ParkourScript に下記の2つの変数を作成します。
- レースを開始してから経過した時間(秒数)を格納するもの
- ゴール地点のパーツを格納するもの
local timePassed = 0
local finishLine = script.Parent
- 後でコードをテストするための print文を持つ finish() という名前の新しい関数を作成します。
local timePassed = 0
local finishLine = script.Parent
local function finish()
print("touched the finish line")
end
- プレイヤーがタッチしたときに finish() を実行する partTouched() という名前の関数を作成します。finishLine の Touched イベントを partTouched に紐づけることを忘れないでください。
local function finish()
print("touched the finish line")
end
local function partTouched(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
finish()
end
end
finishLine.Touched:Connect(partTouched)
- テストプレイし、ゴールに到達すると finish() が呼び出されることを確認します。
finish()が繰り返されるのを防ぐ
現在、プレイヤーがゴール地点にタッチしている間、finish() が何回も呼ばれているのが確認できると思います。それでは都合が悪いので、true または false を格納するブーリアン変数を使用して、finish() が一度だけ呼び出されるようにします。
- raceActive という名前の新しい関数を作成し、true に設定します。
local timePassed = 0
local finishLine = script.Parent
local raceActive = true
-- プレイヤーがフィニッシュラインに触れるたびに実行される
local function finish()
- if文に2つ目の条件を追加し、raceActive を呼び出す前に finish() が true になっているか確認します。
local function partTouched(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid and raceActive == true then
finish()
end
end
- finish() が再び呼び出されるのを防ぐため、raceActive を false に設定します。
local function finish()
print("touched the finish line")
raceActive = false
end
- ゲームをテストし、finish() が1度だけ実行されることを確認します。
タイムを計る
if文と同じように、while ループも実行するかどうかを判断することができます。プレイヤーの時間を計測するには、while true do ループを使用してタイマーを作成し、raceActive 変数が true の場合にのみ実行するようにします。以前使用したwhile true do ループには条件がなかったので、永遠に実行され続けました。
- スクリプトの一番下に while raceActive == true do と入力します。
finishLine.Touched:Connect(partTouched)
while raceActive == true do
end
whileループが一番下になっていることを確認する
この while true do ループは最終的には停止しますが、必ずスクリプトの一番下に記述する必要があります。こうすることにより、ループに到達する前に、それ以前のコードが確実に実行されるようになります。
- プレイヤーのタイムを計測するには、ループで1秒にごとにtimePassed 変数に1を加算します。作業をテストするために print文も入れておきます。
finishLine.Touched:Connect(partTouched)
while raceActive == true do
wait(1)
timePassed = timePassed + 1
print(timePassed)
end
- ゲームをプレイし、Outputウィンドウに秒数が表示されることを確認します。
プレイヤーにメダルを与える
if文を作成する
2つの elseif を持つ if/then 文を使用してプレイヤーのゴールタイムを確認し、適切なメダルを与えます。
- finishRace() の作業をテストしたので、テスト用の print 文を削除します。コードは1行1行実行するのに時間がかかるので、余分なコードを削除するとゲームの実行が速くなります。
local function finish()
-- printを削除
raceActive = false
end
- どのタイムにどのメダルを与えるのかを分かりやすくするため、timePassed を含む print 文をコーディングします。文字列と変数名の間に「..」と入力します。これは、文字列と変数、または文字列同士をを繋げる、結合と呼ばれるものです。
local function finish()
raceActive = false
print("You finished in " .. timePassed)
end
- プレイヤーが金メダルを獲得したかどうかをチェックするには、if 文で、プレイヤーがゴールすると予想される最速タイムと timePassed を比較すれば良いわけです。この例では、プレイヤーのタイムが10秒以下かどうかをチェックしています。
local function finish()
raceActive = false
print("You finished in " .. timePassed)
if timePassed <= 10 then
print("You get a gold medal!")
end
end
- テストプレイし、金メダルが与えられることを確認します。
elseIf条件を追加する
金メダルをのテストが済んだところで、次に elseif キーワードを使用して、他のメダルの条件をコーディングします。
- 銀メダルについては、elseif と入力した後に、与えられるタイムの範囲を指定します。この例では、10秒より大きく、20秒以下を範囲としています。
elseif を then で締めくくり、次の行に print 文を追加します。
local function finish()
raceActive = false
print("You finished in " .. timePassed)
if timePassed <= 10 then
print("You get a gold medal!")
elseif timePassed > 10 and timePassed <= 20 then
print("You get a silver medal!")
end
end
- 次に銅メダルです。見なくてもコーディングできると思います。下記の例では、20秒より大きく、30秒以下を範囲としています。
local function finish()
raceActive = false
print("You finished in " .. timePassed)
if timePassed <= 10 then
print("You get a gold medal!")
elseif timePassed > 10 and timePassed <= 20 then
print("You get a silver medal!")
elseif timePassed > 20 and timePassed <= 30 then
print("You get a bronze medal!")
end
end
elseif をスコープ内に収める
if 文は多くの elseif 条件を持つこともありますが、すべて if/then 文の最初の行と if/then 文の end の間にコーディングされる必要があります。
- 銀メダルと銅メダルのテストを行ってください。
問題解決のヒント
・各 elseif では、条件の後に then を入れる必要があります。
例:elseif timePassed > 10 then
・partTouched() では、if 文の2つ目の条件で == が使われていることを確認します。
例:raceActive == true
・各 elseif がスコープ内にあることを確認します。各 elseif 条件は if/then 文の最初の行と end の間に入れる必要があります。
elseを使って確認する
プレイヤーがメダルを獲得できなかった場合、もう一度トライしてみるように促します。この場合、else 文が使用できます。これは、他の条件が true でなかった場合に実行され、メッセージを表示するものです。
- 最後の elseif の下、end の上に新しい行を追加し、else と入力します。then は入れないでください。else の下で print 文を使用してもう一度トライするように促します。
local function finish()
raceActive = false
print("You finished in " .. timePassed)
if timePassed <= 10 then
print("You get a gold medal!")
elseif timePassed > 10 and timePassed <= 20 then
print("You get a silver medal!")
elseif timePassed > 20 and timePassed <= 30 then
print("You get a bronze medal!")
else
print("Try again!")
end
end
- テストプレイし、“Try again!” のメッセージを確認します。30秒を超えるとメッセージが表示されるはずです。
else文は、常にif文の最終チェックを行うものとして扱います。else文の下に
if
、elseif
、else
のような条件や、元のif文のend
がないことを確認します。問題解決のヒント
・else 文の後に、timePassed <= 20 や then のような条件がないことを確認します。
・else 文は、常に if 文の最終チェックを行うものとして扱います。else 文の下に if、elseif、else のようなキーワードは決してあってはいけません。if で始まり、最後は end で終了していることを確認します。
完成したスクリプト
local timePassed = 0
local finishLine = script.Parent
-- レースが終わったときに、finishとタイマーが繰り返されないようにするために使用する
local raceActive = true
-- プレーヤーがフィニッシュラインに触れると実行さる
local function finish()
raceActive = false
print("You finished in " .. timePassed)
if timePassed <= 10 then
print("You get a gold medal!")
elseif timePassed > 10 and timePassed <= 20 then
print("You get a silver medal!")
elseif timePassed > 20 and timePassed <= 30 then
print("You get a bronze medal!")
else
print("Try again!")
end
end
-- フィニッシュラインに触れたら呼ばれる
local function partTouched(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid and raceActive == true then
finish()
end
end
finishLine.Touched:Connect(partTouched)
-- レースが実行されている間、時間をカウントアップする
-- これはスクリプトの一番下に記述する必要がある
while raceActive == true do
wait(1)
timePassed = timePassed + 1
print(timePassed)
end
参考
実は、elseif をもう少しコンパクトにし、実行速度を上げることができます。
最初の timePassed <= 10 が true になった場合、金メダルを受け取った後、if 文から抜け出ます。つまり、その下の行「elseif timePassed > 10 and timePassed <= 20 then」には行かないため、timePassed は10よりも大きいことは確実です。よって、timePassed > 10 は不要ということになり、elseif timePassed <= 20 then だけでよいことになります。銅メダルも同じことが言えますので、最終的には下記のコードで問題ないでしょう。
if timePassed <= 10 then
print("You get a gold medal!")
elseif timePassed <= 20 then
print("You get a silver medal!")
elseif timePassed <= 30 then
print("You get a bronze medal!")
else
print("Try again!")
end