3-4 else/if を使用した複数の条件

ここでは、if ステートメントを使用して複数の条件を処理する方法について学びます。例として、簡単なレースコースを作成し、順位を決定するゴールを設置します。

なぜ複数の条件が必要か

例えば、1位に金、2位に銀、3位に銅と、3種類のメダルを配布したい場合に、複数の条件が必要になります。

メダルごとに if 文を使ってプレイヤーにメダルを与えることもできますが、金メダルを貰ったプレーヤーは、他のメダルは貰えないので、さらに if 文を実行する必要がなくなります。例えば、以下の架空のコードを考えてみましょう。

if プレイヤー == 1位 then
    金メダルを与える
end

if プレイヤー == 2位 then
    銀メダルを与える
end

if プレイヤー == 3位 then
    銅メダルを与える
end

この場合、1位になったプレーヤーも、その次の2位の判断、そして3位の判断も実行することになります。不要なコードが実行されるのは処理も遅くなり非常にもったいないことです。
このような場合に、最適なキーワード「elseif」があります。日本語にすると「でなければ、もし…」という意味です。

if プレイヤー == 1位 then
    金メダルを与える
elseif プレイヤー == 2位 then
    銀メダルを与える
elseif プレイヤー == 3位 then
    銅メダルを与える
else
    メダルは貰えない
end

こうすることで、1位になったプレイヤーは金メダルのみが貰え、それ以降のコードは実行されず、end から抜け出ますので、高速に動作するわけです。また、if ステートメントが読みやすくなり、バグの発生が軽減されることでしょう。

レースコースの設定

このプロジェクトでは、1 人用のレースコースを作成します。ゴールしたタイムによって、異なるメダルを授与するというものです。今回はゲームプレイの開始がスタートになります。ですからゴールラインにのみ、長方形のパーツを設置してください。スタート地点は、SpawnLocation になります。

パーツとスクリプト

レースはあらゆるプロジェクトで使用できます。

  1. FinishLine という名前のパーツを設置し、アンカー設定します。長距離のコースを作るとテストに時間がかかりますので、最初は短い距離で作成することをお勧めします。
ゴールライン
コース全体
  1. FinishLine で、RaceScript という名前のスクリプトを作成します。そのスクリプトで、レースが開始してから経過した秒数を格納する変数(timePassed)と、ゴールラインのパーツを格納する変数(finishLine )の 2 つを作成します。
local timePassed = 0
local finishLine = script.Parent
  1. ゴールしたら呼ぶ関数(finish)を作成します。まずは、print 文を使用してメッセージを表示してみましょう。
local finishLine = script.Parent

local function finish()
    print("touched the finish line")
end
  1. ご自身の力でコーディングしてみましょう。
  • プレイヤーがゴールラインに触れたときに、finish( )を実行する partTouched() という名前の関数を作ります。
  • FinishLineのタッチイベントに 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)
  1. テスト実行を行い、ゴールラインに触れたときに出力ウィンドウでメッセ―ジが表示されるのを確認します。

繰り返しからのfinish()の停止

メッセージの右側に「x3」とあるのは、3回同じメッセージが表示されたということを示します。つまり、プレイヤーは何回もゴールラインに触れ、その度に、 finish() が呼ばれているわけです。これを何とかしなくてはなりません。

そこで、新たに raceActive という変数を用意します。この変数に設定するものは、true(真) か false(偽) です。初期値は true とし、ゴールしたらfalseを設定するようにします。

  1. raceActiveという名前の新しい変数を作成し、trueに設定します。
local timePassed = 0
local finishLine = script.Parent

local raceActive = true

-- プレイヤーがゴールラインに触れるたびに実行される
local function finish()
  1. if 文に 2つ目の条件を追加して、 finish()を呼び出す前に raceActive が true かどうかを確認します。
local function partTouched(otherPart)
    local character = otherPart.Parent
    local humanoid = character:FindFirstChildWhichIsA("Humanoid")
    if humanoid and raceActive == true then
        finish()
    end

end
  1. finish() が再度呼び出されないようにするには、raceActive を false に設定すれば良いわけです。
local function finish()
    print("touched the finish line")
    raceActive = false
end
  1. ゲームをテストして、メッセージが 1 回しか表示されないことを確認します。

タイムを追跡する

if ステートメントと同様に、while ループでも条件を使用して実行する必要があるかどうかを確認できます。while というのは、ループ処理を行うときに使用するものです。if 文と似ており、while は条件式が真になっている間中、do から end の間を繰り返し実行するというものです。詳しくは、次の第4章の1をご覧ください。
プレーヤーのタイムを計測するには、 raceActive が true の場合にのみ、繰り返し実行されるようにすれば良いわけです。

  1. スクリプトの最後に、「while raceActive == true do」と入力します。Enter を押すと自動的に end が追加されるでしょう。raceActive が true になっている間中、do から end 内のプログラムが繰り返し実行されます。
finishLine.Touched:Connect(partTouched)

while raceActive == true do
    -- この部分が繰り返し実行される
end
whileループがスクリプトの一番下にあることを確認してください。タッチイベントを接続するまでに、while を実行してしまうと、raceActive が falseになることはなく、永遠にタッチイベントが接続できないという事態になります。プログラムの処理順番は非常に重要ですのでその辺りも考えなくてはなりません。
  1. プレーヤーのタイムを計るには、ループ内で 1秒ごとにtimePassed変数に 1 を加算します。テスト用の print 文を入れておきます。
finishLine.Touched:Connect(partTouched)

while raceActive == true do
    wait(1)
    timePassed = timePassed + 1
    print(timePassed)
end
  1. ゲームをプレイし、出力ウィンドウに 1 秒ごとに表示されることを確認します。

レースの勝者に報酬を与える

完成に近づきました。最後に、プレイヤーのタイムに基づいて異なるメダルを授与するプログラムを追加して完成です。ここの本題である「elseif」を使うことになります。

if ステートメントの作成

if/then ステートメントと 2 つの elseif を使用して、プレーヤーの終了時間を確認し、必要なメダルを授与します。

  1. finish()が呼ばれることが確認できましたので、print 文をコメントにするか削除しましょう。
local function finish()
    -- print("touched the finish line")
    raceActive = false
end
  1. どのタイムでどのメダルを授与すれば良いかをチェックするために、timePassedを表示する print文を入れておきます。文字列を変数または他の文字列と結合するには、「連結演算子」と呼ばれる「..」(ドット2つ)を使用して、文字列と変数名の間に「..」と入力します。
local function finish()
    raceActive = false
    print("You finished in " .. timePassed)
end
  1. 金メダルを獲得する条件はゴールタイム10秒以下としましょう。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
  1. テストプレイし、金メダルを獲得できることを確認してください。

追加条件の追加

金メダルのテストが完了したので、elseif キーワードを使用して他のメダルの条件をコーディングします。

  1. 銀メダルの獲得条件は、10秒より大きく、20秒以下としましょう。and キーワードを使用します。
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
  1. 銅メダルは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
  1. 銀メダル、および銅メダルのテストを行います。
銀メダル
銅メダル

トラブルシューティング

この時点で銀メダルと銅メダルが正しく表示されない場合は、次のいずれかを確認してください。

  • elseif 文は then で終了していますか?
  • partTouched()では、 if 文の 2 番目の条件で「==」が使用されていますか? ( raceActive == true の場合と同じ)
  • elseif がスコープ内にあることを確認します。各elseif 条件は、if/then 文の最初の行と最後のendの間にある必要があります。

else 条件の追加

ここまでのプログラムでは、30秒より大きいタイムになった場合、メッセージは何も表示されません。もう一度、挑戦する勧めるようなメッセージを表示したいと思います。この場合、すべての条件に一致しなかった場合に実行される else ステートメントを使用します。

if ~ elseif ですべての条件が一致しない場合に備えて、すべての if ステートメントに else を含めることをお勧めします。
  1. 最後の elseif の下と end の上で、新しい空白行を入れ、else と入力します。Enter を押すと、不要な end が追加される場合があります。その場合は削除しましょう。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
  1. else メッセージを確認するために再びテストします。

トラブルシューティング

  • else 文にtimePassed <= 20 や then などの不要なものは記述していませんか?
  • else 文は常に if 文の最後に記述しなくてはなりません。else を単独で使用することはできません。先頭は if、 次に elseif (使用しないもある)、そして最後に else が続き、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

コメントを残す