ループのネストとは、ループの中にさらにループがあるということです。例えば、6つのカップケーキを3回焼くという処理では、外側のループは3回になり、内側のループは6回実行されるという感じになります。
ネストされたループの実行方法
ループがネストされている場合、プログラムは次のループに到達するまで 1 行ずつ実行されます。内側のループは、外側のループに戻る前に条件が満たされるまで実行されます。
ネストされたループのロジック
次の図は、ループが実行されるイメージを示しています。外側のループが紫色のところで、内側のループが水色の部分になります。
ネストされたループの例
実際にネストしたプログラムの例をあげてみましょう。
下記の例では、外側のループが7回、内側のループが5回実行されています。
- ServerScriptService にPartMakerという名前の新しいスクリプトを作成します。以下のコードをコピーします。
local numberOfBatches = 7
local partsPerBatch = 5
local partsMade = 0
-- 1個のキューブを作成
local function createPart(color)
local part= Instance.new("Part")
part.Size = Vector3.new(2, 2, 2)
part.CFrame = CFrame.new(20, 0, 20)
part.Color = color
part.Parent = workspace
end
-- 外側のループ
for partBatch = 1, numberOfBatches do
print ("Top outer loop: part batch " .. partBatch)
local currentColor = Color3.fromRGB(math.random(0, 255),math.random(0, 255),math.random(0, 255))
-- 内側のループ
for partNumber = 1, partsPerBatch do
createPart(currentColor)
print("Inner loop: part " .. partNumber)
-- 作成したキューブの数
partsMade = partsMade + 1
task.wait(0.5)
end
print("Bottom outer loop: " .. partsMade .. " parts made so far.")
task.wait(2)
end
- テスト実行します。同じ色のパーツが5個ずつ出現し、2秒後、新たな色のパーツが再び5個出ました。それが全部で7回繰り返えし実行されます。
ネストされた for ループ タワー
各ループには独自のプログラムを記述できるため様々な処理が行えます。ループをネストさせることでキューブの出現位置を変更し、この映像のようなタワーを作ることもできます。プログラムには、3つのループがあり、それぞれタワーの幅、長さ、高さのどこにキューブを生成するのかを制御しています。
Cube Maker スクリプトのコーディング
ネストされたループを練習するには、立方体の塔を作成するスクリプトを作成します。まず初めに 1 つのキューブを生成する関数を作ります。この関数を繰り返し呼び出すことで塔が建てられます。
スクリプトの設定
最初に 1 つのキューブを生成する関数を作ります。この関数を繰り返し呼び出すことで塔が建てられます。
- 先ほど作成した PartMaker スクリプトを削除します。そうしないと、同じ場所で同時にパーツを作成する 2 つのスクリプトが存在することになります。
- TowerBuilder という名前の新しいスクリプトを作成します。上部にタワーの高さとキューブ1個のサイズを示す変数を追加します。
local TOWER_SIZE = 4
local CUBE_SIZE = 2
上記の変数がすべて大文字になっていることに注意してください。これらは定数、または変更されない変数と呼ばれます。スクリプト内で変更される変数と区別するには、大文字とアンダースコアを使用して入力します。
- CUBE_SIZEを使用して単一の正方形キューブを作成するmakecube()という名前の関数を作成します。
local TOWER_SIZE = 4
local CUBE_SIZE = 2
-- 1個のキューブを作成する
local function makeCube()
local cube = Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
end
- 関数のパラメータを使って色を受け取ることにします。キューブの色を設定します。
local function makeCube(color)
local cube = Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
cube.Color = color
end
- 最後に、キューブの親を Workspace に設定すれば表示されます。
local function makeCube(color)
local cube= Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
cube.Color = color
cube.Parent = workspace
end
作成したオブジェクトの Parent を Workspace 下に設定すると画面に表示しますが、この設定はオブジェクトの各プロパティを設定した後に行うことをお勧めします。画面に表示された後にプロパティを変更すると、少しばかりシステムに負担をかけることになります。
workspace はグルーバル変数です。グルーバル変数とはどのスクリプトからでも参照できる共通の変数を意味します。Roblox システムの方で「workspace = game.Workspace」が実行されていると考えれば良いでしょう。
さまざまな方向へのスポーン
タワーを作成するには、パーツの X、Y、Z プロパティを設定して、特定の場所でキューブを生成します。X と Z は横、奥行き方向で、Y は高さを示します。
- makeCube () には4つのパラメータがあります。キューブを出現させる位置が spawnX、spawnY、spawnZ で、その色は color になります。
-- 1個のキューブを作成する
local function makeCube(spawnX, spawnY, spawnZ, color)
local cube = Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
cube.Color = color
cube.Parent = workspace
end
- spawnX、spawnY、spawnZ パラメータを使用して、キューブの CFrame プロパティを新しい CFrameに設定します。
local function makeCube(spawnX, spawnY, spawnZ, color)
local cube = Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
cube.Color = color
cube.CFrame = CFrame.new(spawnX, spawnY, spawnZ)
cube.Parent = workspace
end
CFrame は 3D の位置と回転角度を格納するために使用されるデータ型です。世界にオブジェクトを配置するために使用されます。
入れ子になったループでスポーンする
スクリプトには、タワーの高さ、幅、奥行きのループが 1つずつ、合計3つのループがあります。上に移動する前にフロア全体を完成させるには、最も外側のループで Y 座標を設定するところから始めます。
- makeCube() 関数の下で、for ループを作成して、各キューブが出現する高さを設定します。
- 制御変数:heightIndex = 1
- 終了値: TOWER_SIZE
- 増減数:未指定(未指定の場合は自動的に1になる)
ループ内に「local spawnY = (heightIndex – 1) * CUBE_SIZE」を追加します。
-- タワーの作成
for heightIndex = 1, TOWER_SIZE do
local spawnY = (heightIndex - 1) * CUBE_SIZE
end
spawnYの計算では、最初のキューブが地面の高さで出現し、毎回 1サイズのキューブの空間を移動するようにします。地面の高さは 0 であるため、heightIndexから 1 を引く必要があります。
- 最初のループが終了したら、2番目のループを開始します。最初の for ループ内に、タワーの横方向に沿ってキューブを配置する場所を指定する新しい for ループを追加します。
- 制御変数:lengthIndex = 1
- 終了値:TOWER_SIZE
ループ内に「local spawnX = lengthIndex * CUBE_SIZE」を追加します。
for heightIndex = 1, TOWER_SIZE do
local spawnY = (heightIndex - 1) * CUBE_SIZE
for lengthIndex = 1, TOWER_SIZE do
local spawnX = lengthIndex * CUBE_SIZE
end
end
ネストされたループを使用する場合、コードが正しくインデントされていることが重要です。これにより、コードが読みやすく整理されたものになります。
- 2 番目のループ内に、タワーの奥行き方向の3番目の for ループを追加します。この最後のループで、makecube() を呼び出し、出現座標と色をパラメータに渡します。
- 制御変数:widthIndex = 1
- 終了値:TOWER_SIZE
ループ内に次のプログラムを追加します。
- local spawnZ = widthIndex * CUBE_SIZE
- makeCube(spawnX, spawnY, spawnZ, currentColor)
タワーが建てられるのを見ることができるように、0.25秒の待機時間を追加します。
-- タワーの作成
for heightIndex = 1, TOWER_SIZE do
local spawnY = (heightIndex - 1) * CUBE_SIZE
for lengthIndex = 1, TOWER_SIZE do
local spawnX = lengthIndex * CUBE_SIZE
for widthIndex = 1, TOWER_SIZE do
local spawnZ = widthIndex * CUBE_SIZE
makeCube(spawnX, spawnY, spawnZ, currentColor)
task.wait(0.25)
end
end
end
- 各フロアをランダムな色にするには、外側のループのところでランダムなRGB番号を使って色を作成します。
for heightIndex = 1, TOWER_SIZE do
local spawnY = (heightIndex - 1) * CUBE_SIZE
local currentColor = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255))
for lengthIndex = 1, TOWER_SIZE do
local spawnX = lengthIndex * CUBE_SIZE
for widthIndex = 1, TOWER_SIZE do
local spawnZ = widthIndex * CUBE_SIZE
makecube(spawnX, spawnY, spawnZ, currentColor)
task.wait(0.25)
end
end
end
- テストプレイして確認してみましょう。出力ウィンドウにエラー(赤い文字)が表示されず、完全なタワーが作成されたら成功です。
オプションのチャレンジ
練習問題です。下のように、キューブの透明度を変えるにはどうしたら良いでしょうか?
答えは下にありますが、まずは自力で改造してみてください。
フェードアウェイパーツ
タワーが構築されるにつれて、パーツの透明度が左から右にフェードアウトします。
プログラムは下記の通りになると思います。
local TOWER_SIZE = 6
local CUBE_SIZE = 2
-- 1個のキューブを作成する
local function makeCube(spawnX, spawnY, spawnZ, color, transparency)
local cube = Instance.new("Part")
cube.Size = Vector3.new(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)
cube.Color = color
cube.Transparency = transparency -- 透明度を設定
cube.CFrame = CFrame.new(spawnX, spawnY, spawnZ)
cube.Parent = workspace
end
-- タワーの作成
for heightIndex = 1, TOWER_SIZE do
local spawnY = (heightIndex - 1) * CUBE_SIZE
local currentColor = Color3.fromRGB(math.random(0, 255), math.random(0, 255), math.random(0, 255))
for lengthIndex = 1, TOWER_SIZE do
local spawnX = lengthIndex * CUBE_SIZE
local cubeTransparency = (lengthIndex - 1) * 0.10 --Updates every loop starting at 0
for widthIndex = 1, TOWER_SIZE do
local spawnZ = widthIndex * CUBE_SIZE
makeCube(spawnX, spawnY, spawnZ, currentColor, cubeTransparency)
task.wait(0.05)
end
end
end
モデルが雨のように降る
動画のようなケーキを降らせてみましょう。これはケーキはパーツを組み合わせて作成したモデルです。プログラムに対応したモデルを作らなければ、プログラムエラーになりますので注意してください。
- 2個以上のパーツでケーキを作ります。(もちろん、ケーキっぽくなくてもOK)
- 1つのパーツに「Cup」という名前を、もう1つのパーツに「Frosting」という名称を付けます。
- それらのパーツを Weld で接着します。(アンカーにしてはいけません)
- パーツを選択し、モデルにします。モデルの名称を「Cupcake」にします。
- モデルのプロパティ PrimaryPart に「Cup」を設定します。
- 作成したモデル「Cupcake」を ServerStorage に移動します。
- PartMaker 内のプログラムをすべて消去します。
- 下記のプログラムをコピーし、そこにペーストして完了です。
6個ずつのケーキが30回振ってきます。
local ServerStorage = game:GetService("ServerStorage")
local numberOfBatches = 30
local cupcakesPerBatch = 6
local cupcakesBaked = 0
-- 1個のケーキを作成
local function makeCupcake(frostingColor, cupColor)
local cupcake = ServerStorage.Cupcake:Clone()
local cup = cupcake.Cup
local frosting = cupcake.Frosting
cupcake:SetPrimaryPartCFrame(CFrame.new(0,20, 0) * CFrame.Angles(0, 0, -90))
frosting.Color = frostingColor
cup.Color = cupColor
cupcake.Parent = workspace
end
-- 外側のループ
for cupcakeBatch = 1, numberOfBatches do
print ("Top outer loop: cupcake batch " .. cupcakeBatch)
local frostingColor = Color3.fromRGB(math.random(0,255),math.random(0,255),math.random(0,255))
local cupColor = Color3.fromRGB(math.random(0,255),math.random(0,255),math.random(0,255))
-- 内側のループ
for cupcakeNumber = 1, cupcakesPerBatch do
makeCupcake(frostingColor, cupColor)
print("Inner loop: cupcake " .. cupcakeNumber)
-- Track muffins baked
cupcakesBaked = cupcakesBaked + 1
task.wait(0.5)
end
print("Bottom outer loop: " .. cupcakesBaked .. " cupcakes baked so far.")
end
まとめ
より複雑なタスクを実行するには、複数のループ、さらには異なる種類のループを組み合わせると便利です。すべてのループは入れ子にすることができます。つまり、あるループが別のループの中にあることになります。ネストされたループは、他のループと同じロジックに従います。最初の最も外側のループで開始され、内側のループを通じてタスクが実行され、その後、該当する場合は最初のループに戻ります。
[ 5-1 配列の概要 ]