for ループを使用した、かなり実用的なものを作成してみましょう。プレーヤーがボタンにタッチすると、前方の橋が渡れるようになります。ただしタイマーがあり、時間が0になると奈落の底に落下してしまいます。タイマーは前方に見えるパーツ上に表示したいと思います。そのタイマーに for ループを使用します。
プロジェクトの設定
この橋は、アスレチックゲーム(Robloxではオービーと呼ばれる)などのアクションゲームに使用できます。
パーツの作成
- 図のように最低3つのパーツを設置し、名称を下記と同じようにしてください。すべてのパーツは動かないようにアンカー設定してください。
- TimerDisplay(タイマー表示)
- Bridge(橋)
- ButtonBridge(橋ボタン)
- 通れない橋は半透明にし、通り抜けてしまう設定にします。これを行うには、Bridgeを選択し、そのプロパティを下記の通りに変更します。
- Transparency ← 0.8 (半透明)
- CanCollide ← False (通り抜ける)
タイマー表示の作成
橋を渡るとき、プレイヤーは橋が消えるまであと何秒か知りたいものです。画像や文字を表示する方法の1つにSurfaceGUI というものがあります。これをパーツに追加することでテキスト文字が表示できます。
- TimerDisplay を選択し、 SurfaceGuiを追加します。その SurfaceGUI を選択して TextLabelを追加します。
現在、矢印で示しているように TextLabel が見えないかもしれません。非常に小さかったり、パーツの表示面が側面にある可能性があります。プレイヤーがタイマーを見やすくするために、SurfaceGUI の表示面を変更し、さらに文字サイズを大きくしなくてはなりません。
- SurfaceGUI を選択します。Faceプロパティを見つけます。この値を変更することで表示面が変えられます。プレイヤーが見やすいように表示面を変更してください。
この例では、Face は Left になっていますが、パーツの向きなどにより変わります。
- SurfaceGUI を広げるには、CanvasSize の左側の矢印をクリックして展開し、X と Y の両方を 100 に変更します。
CanvasSize が見当たらない? SizingMode を FixedSize に設定すると CanvasSize が表示されます。
- TextLabel を選択します。Sizeプロパティを展開し、さらに X と Y を展開します。X と Y の両方で、Scaleを 1 に、Offset を 0 に変更します。これにより、TextLabel がパーツの面と同じサイズになります。
- 下にスクロールして、TextScaled をオンに設定します。これにより、テキスト文字が Surface GUI に合わせて自動的に拡大表示されます。
- Textプロパティの横に「Label」と入っていると思いますが、これが現在表示している文字です。プログラムを使ってこの値を変更することでタイマー表示ができます。初期値は空白にしたいので消去しておきます。
プログラムの作成
タイマーの準備ができたところで、橋の制御とカウントダウンを表示するプログラムを作ります。
- Bridge に、TimedBridge という名前の新しいスクリプトを追加します。bridge、button、timerText の変数に各パーツを代入しておきます。橋が通れる時間は、timerDuration 変数に設定します。この値は、橋の長さによって調整してください。
local bridge = script.Parent
local button = game.Workspace.ButtonBridge
local timerText = game.Workspace.TimerDisplay.SurfaceGui.TextLabel
-- 橋が通れる時間
local timerDuration = 5
タッチ操作のコーディング
作成する関数は2つです。1つはタイマー開始で呼ばれるもの、もう1つはボタンに触れたら呼ばれる関数です。
- まずは、タイマー開始で呼ばれる関数を作成します。関数名は startTimer() とし、動作確認用に print 文を入れておきます。
local timerDuration = 5
local function startTimer()
print("Countdown started")
end
- 次に、橋ボタンに触れたら呼ばれる関数を buttonPressed() という名前で作成します。下記のプログラムは「3-2 if/then の練習ートラップ」で解説しましたので、忘れてしまった方はそちらをご覧ください。
触れたパーツがプレイヤーのパーツ(手足等)かどうかを確認します。humanoid 変数にオブジェクトが入っていれば、それはプレイヤーが触れたということです。
local function startTimer()
print("Countdown started")
end
local function buttonPressed(partTouched)
local character = partTouched.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
end
end
- タイマーを開始するには、if ステートメントで startTimer() 関数を呼び出します。
local function buttonPressed(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
startTimer()
end
end
- buttonPressed() 関数の下で、 ButtonBridge パーツの Touched イベントにこの関数を接続します。
local function buttonPressed(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
startTimer()
end
end
button.Touched:Connect(buttonPressed)
- テストプレイします。ButtonBridge に触れるたびに、出力ウィンドウにメッセージが表示されます。
トラブルシューティング
出力ウィンドウにメッセージが表示されない場合、次のいずれかを試してください。
問題:「… is not a valid member of workspace」というエラー メッセージ
- 変数名、パーツ名は間違っていませんが? 大文字小文字の区別があります。
問題:パーツが見えません
- 3 つのパーツはアンカー設定されていますか?
- Bridge の Transparency は1になっていませんか? (1は完全な透明)
タイマーの作成
プレイヤーが橋ボタンに触れると、橋が不透明になり渡れるようにします。さらにタイマーが開始され、0になると再び半透明に戻り、渡り損ねたプレイヤーは下に落下してしまうようにします。
橋を渡れるようにする
まずは、橋を渡れるようにしなくてはなりません。
- 橋を通行可能な状態にしましょう。Transparency を 0 にすれば不透明になります。不透明にはなりますが、すり抜けて落下してしまいます。CanCollide プロパティを true にすることにより、通り抜けできなくなりますので、これで無事に渡れるようになります。
local function startTimer()
-- 橋を見やすく、歩きやすくする
bridge.Transparency = 0
bridge.CanCollide = true
end
- 次に、タイマーをカウントダウンさせなくてはなりません。このときに for ループを使用します。
- 制御変数:count
- 開始値:timerDuration
- 終了値: 0
- 増減値:-1
local function startTimer()
-- 橋を見やすく、歩きやすくする
bridge.Transparency = 0
bridge.CanCollide = true
for count = timerDuration, 0, -1 do
end
end
- タイマーを表示するには、「timerText.Text = count」とし、 timerText のプロパティ Text に値を代入すれば良いわけです。このままでは、一瞬で count は 0 になってしまいます。
for count = timerDuration, 0, -1 do
timerText.Text = count
end
- 1 秒に1 回だけカウントダウンするには、task.wait(1) を使用します。
for count = timerDuration, 0, -1 do
timerText.Text = count
task.wait(1)
end
- ゲームを実行します。橋ボタンをタッチすると橋が現れ、タイマーがスタートします。
橋ボタンの上を移動すると、タイマーが再起動し続けることに注意してください。これは、ボタンがタッチされるたびに for ループが呼び出され、最初から for ループが開始されるためです。これは次のセクションで修正します。
橋が再起動しないようにする
タイマーが何度も開始されないようにするには、 startTimer() の再呼び出しを許可するかどうかを制御する別の変数を追加する必要があります。この変数に true または false を設定して、呼び出しをコントロールします。
- timerActiveという名前の変数をプログラムの上の方に作成し、まだ誰も橋ボタンに触れていないということで、false を代入しておきます。
local timerDuration = 5
local timerActive = false
local function startTimer()
- timerActive が false の場合にのみタイマーが開始されるようにするには、 buttonPressed() の if ステートメントに、もう1つの条件を追加します。
local function buttonPressed(otherPart)
local character = otherPart.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid and timerActive == false then
startTimer()
end
end
- タイマーが終了する前に startTimer() が再び実行されないようにするには、timerActive を true に設定します。
local function startTimer()
timerActive = true
bridge.Transparency = 0
bridge.CanCollide = true
- startTimer() 関数では、for ループの後、Bridge を半透明にし、CanCollide を false に変更して、通り抜けてしまうようにします。
local function startTimer()
timerActive = true
bridge.Transparency = 0
bridge.CanCollide = true
-- timerDurationからカウントダウンするForループ
for count = timerDuration, 0, -1 do
timerText.Text = count
task.wait(1)
end
-- 橋を渡れないようにする
bridge.Transparency = 0.8
bridge.CanCollide = false
end
- さらに、タイマー表示をクリアするには、timerText の Text プロパティに空の文字列に代入します。最後に timerActive を false に設定して、タイマーが再び使えるようにします。
bridge.Transparency = 0.8
bridge.CanCollide = false
timerText.Text = ""
timerActive = false
- テストプレイを行い、ブリッジが複数回使用できることを確認します。
完成したプログラム
local bridge = script.Parent
-- 橋ボタンのパーツを取得する
local button = game.Workspace.ButtonBridge
-- タイマー表示用パーツを取得する
local timerPart = game.Workspace.TimerDisplay
-- テキストを表示するオブジェクトを取得する
local timerText = timerPart.SurfaceGui.TextLabel
-- プレイヤーが橋を渡るまでの時間
local timerDuration = 5
local timerActive = false
local function startTimer()
print("Countdown started")
timerActive = true
bridge.Transparency = 0
bridge.CanCollide = true
-- timerDurationからカウントダウンするForループ
for count = timerDuration, 0, -1 do
timerText.Text = count
task.wait(1)
end
-- 橋を渡れないようにする
bridge.Transparency = 0.8
bridge.CanCollide = false
timerText.Text = ""
timerActive = false
end
local function buttonPressed (partTouched)
local character = partTouched.Parent
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
print("part touched")
if humanoid and timerActive == false then
print("starting timer")
startTimer()
end
end
button.Touched:Connect(buttonPressed)
[ 4-5 ネストされたループ ]