これまでのチュートリアルでは、フェードするプラットフォームや致命的な溶岩など、さまざまな体験機能を作成しました。このチュートリアルでは、これらを統合してユーザーが最も長く生き残ることができるかを競うプレイ可能な体験を作ります。生存している間、毎秒ポイントがスコアに追加されます。
準備
まずは、体験のシーンを設定する必要があります。前のチュートリアルで作成したfading platformsを複製し、ユーザーが可能な限りプラットフォームのボードに留まって競えるようにします。
また、致命的な溶岩を使用して、ユーザーがプラットフォームから落ちた際に死亡させることもできます。さもなければ、ユーザーが自らの運命に落ちるのを許可します。ユーザーがプラットフォームにジャンプしてプレイを開始できるよう、SpawnLocationをどこかに配置してください。

プレイヤーポイント
Robloxには、ユーザーの統計を表示するための組み込みのLeaderboardがあります。リーダーボードを通じてプレイヤーポイントを設定すると、ユーザーが体験中に画面の右側に表示されます。

よりカスタマイズ可能な情報の表示方法については後のチュートリアルで学びますが、リーダーボードはRobloxで視覚的なスコアリングシステムを作成する最もシンプルな方法です。
体験の状態を設定するスクリプトは、体験が始まったときに自動的に実行されるため、ServerScriptServiceに配置するのが最適です。ServerScriptService内にSetupPointsという名前のスクリプトを作成します。

プレイヤーのリスナー
Robloxでは、サービスはさまざまな便利な機能を実行するオブジェクトです。Playersサービスには、体験に参加する各ユーザーのポイントを設定するために使用できるPlayerAddedというイベントがあります。
サービスには、GetService関数を使用してアクセスできます。gameオブジェクトは、体験のすべてを含む変数で、どこからでもアクセス可能です。
game:GetService("Players")を使用してPlayersサービスの変数を作成します。
新しいプレイヤー用のパラメータを持つ onPlayerAdded という名前の関数を作成します。
onPlayerAdded関数をPlayerAddedイベントに接続します。
local Players = game:GetService("Players")local function onPlayerAdded(player)endPlayers.PlayerAdded:Connect(onPlayerAdded)
スタッツフォルダーを作成
ユーザーのポイントをリーダーボードに表示するには、Playerオブジェクト内に"leaderstats"と呼ばれる新しいFolderを作成し、そこにポイントを格納するだけで済みます。新しいオブジェクトはスクリプト内でInstance.new()関数を通じて作成できます。
Instance.new("Folder")を使用して新しいFolderオブジェクトを作成し、結果をleaderstatsという新しい変数に格納します。
local function onPlayerAdded(player)local leaderstats = Instance.new("Folder")endleaderstatsのNameプロパティを"leaderstats"に設定します。
leaderstatsをplayerの親にします。
local Players = game:GetService("Players")local function onPlayerAdded(player)local leaderstats = Instance.new("Folder")leaderstats.Name = "leaderstats"leaderstats.Parent = playerendPlayers.PlayerAdded:Connect(onPlayerAdded)
ポイントを作成
リーダーボードシステムは、leaderstatsフォルダー内のあらゆる値を読み取り、見つけたものを表示します。
プレイヤーのポイントを追跡するためのスタッツを追加するには、新しいIntValueオブジェクトをleaderstatsフォルダーに親として追加できます。値オブジェクトの名前は、その現在の値とともに表示されます。
- Nameを"Points"に設定します。
- Valueを0に設定します。これはリーダーボードが最初にプレイヤーに表示する値です。
- pointsオブジェクトをleaderstatsフォルダーに親として追加します。
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
end
Players.PlayerAdded:Connect(onPlayerAdded)
体験をテストすると、リーダーボードが右上にユーザーの名前とその横にポイントスコアが表示されるのを確認できるはずです。
時間を数える
各ユーザーは、生存している各秒ごとにポイントを獲得する必要があります。whileループとtask.wait()関数を使用して、毎秒ポイントの値を更新できます。
- スクリプトの最後にtrueを条件として使用したwhileループを作成します。
- ループ内でtask.wait()を使用して1秒待ちます。
Players.PlayerAdded:Connect(onPlayerAdded)while true dotask.wait(1)end
プレイヤーリスト
全てのユーザーに対してコードを実行するには、GetPlayers関数から返されたユーザーの配列を反復処理する必要があります。
配列は、順番に保存されたアイテムのリストです。各アイテムには、インデックス位置を通じてアクセスでき、これは1から始まります。配列の長さは、#を前に付けることで取得できます。
- Players:GetPlayers()の結果をplayerListという変数に格納します。
- 開始値を1、終了値を#playerListとするforループを作成し、ループの各反復で1人のプレイヤーを取得します。
while true dotask.wait(1)local playerList = Players:GetPlayers()for currentPlayer = 1, #playerList do-- プレイヤーリスト内の各プレイヤーに対するロジックをここに追加endend
ポイントを授与
forループ内の各ユーザーにポイントを授与するには、配列からそのユーザーを取得し、そのleaderstatsフォルダー内に保存されているPointsオブジェクトに1を追加します。
配列に保存されたオブジェクトには、角括弧を使用してアクセスします - 例えば、playerList配列の最初のアイテムにはplayerList[1]でアクセスできます。forループ内でplayerList[currentPlayer]を書くことで、各反復のたびにリスト内の各ユーザーを移動できます。
- playerList[currentPlayer]に格納されているユーザーをplayerという変数に格納します。
- ユーザーのPointsオブジェクトをpointsという変数に格納します。
while true dotask.wait(1)local playerList = Players:GetPlayers()for currentPlayer = 1, #playerList dolocal player = playerList[currentPlayer]local points = player.leaderstats.Pointspoints.Value += 1endend
体験をテストすると、ユーザーのスコアが毎秒1ずつカウントアップして表示されるのを確認できます。
キャラクターをリスン
体験の目的は、誰が最も長く生き残るかを確認することなので、死亡したユーザーはポイントを0にリセットする必要があります。
ユーザーが死亡したかどうかを検出するには、ユーザーのCharacterモデルを取得する必要があります。このモデルはユーザーのPlayerオブジェクトが読み込まれた後に体験に追加されます。これには、CharacterAddedイベントを使用してキャラクターが利用可能になったときにリスンします。onCharacterAddedという名前の関数を作成し、キャラクター用の1つ、プレイヤー用の1つのパラメータを追加します。
local Players = game:GetService("Players")
local function onCharacterAdded(character, player)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
onCharacterAdded関数のパラメータにユーザーを含めたにも関わらず、実際のCharacterAddedイベントはキャラクターのみを返し、関連するユーザーは返しません。そのため、イベント接続のためには無名関数を使用してplayerオブジェクトも渡します。
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
ポイントをリセット
ユーザーが死亡すると、Humanoidは自動的にDiedイベントを発火させます。このイベントを使用して、ポイントをリセットするタイミングを把握できます。
HumanoidはCharacterモデルの中にあり、モデルの内容はユーザーがスポーンしたときにのみ構成されます。Humanoidオブジェクトの読み込みを安全に待つには、WaitForChild()関数を使用します。待機する子の名前を文字列として渡し、任意の親オブジェクトで呼び出すことができます。character:WaitForChild("Humanoid")を使用してHumanoidを待つための変数を作成します。
local Players = game:GetService("Players")
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
end
Diedイベントに接続する必要がある関数は非常に短く、ここでのみ必要なため、再度無名関数を使用できます。
- HumanoidのDiedイベントに新しい無名関数を接続します。
- 無名関数内で、プレイヤーのPointsオブジェクト用の変数をpointsとして作成します。
local Players = game:GetService("Players")
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
local points = player.leaderstats.Points
points.Value = 0
end)
end
これをテストすると、ユーザーのスコアが死亡時にリセットされるのが確認できます。
プレイヤーを確認
ユーザーが死んでいるのにもかかわらずポイントを獲得し続けるのは、体験の精神に反しているため、コードはポイントを授与する前にユーザーが生存しているかどうかを確認する必要があります。
最初に、プレイヤーが生存しているかどうかを確認するために、onPlayerAdded関数内で属性を定義します。この時点では、ユーザーはまだ生存しておらず、スポーンしていません。ユーザーのキャラクターモデルがまだ追加される必要があります。
属性は、Roblox内のオブジェクトを自身のデータでカスタマイズすることを可能にします。属性は名前と値で構成されます。属性は、SetAttribute関数を使用して任意のオブジェクトに作成できます。playerに対してSetAttributeを呼び出し、"IsAlive"という属性を値falseで作成します。
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player:SetAttribute("IsAlive", false)
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
ユーザーのキャラクターモデルが再スポーンすると、IsAliveの値をtrueに変更し、ユーザーが再びポイントを獲得できるようにします。
- onCharacterAdded内で、playerのIsAlive属性をtrueに設定します。
- onCharacterDied内で、playerのIsAlive属性をfalseに設定します。
local Players = game:GetService("Players")
local function onCharacterAdded(character, player)
player:SetAttribute("IsAlive", true)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
local points = player.leaderstats.Points
points.Value = 0
player:SetAttribute("IsAlive", false)
end)
end
最後に、IsAliveをwhileループ内のポイントを授与する前に確認する必要があります。GetAttribute関数は、属性の名前を受け取り、その値を返します。whileループ内で、ポイントを授与するコードをif文にラップし、条件をplayer:GetAttribute("IsAlive")にします。
while true dotask.wait(1)local playerList = Players:GetPlayers()for currentPlayer = 1, #playerList dolocal player = playerList[currentPlayer]if player:GetAttribute("IsAlive") thenlocal points = player.leaderstats.Pointspoints.Value += 1endendend
現在、体験をテストすると、ユーザーが生存している限り毎秒ポイントを獲得し、生存していないときは0のままであることが分かります。友達を誘って一緒にプレイし、誰が最高のスコアを得られるか確認してください。
これは始まりに過ぎません:体験をユーザーのためにさらに向上させることができます。以下は幾つかのヒントです:
- すべてのプラットフォームのコードを1つのスクリプトにまとめ、更新を簡単にします。
- ユーザーが体験エリアにテレポートされるのを待つロビーエリアを作成し、ユーザーが同時に開始できるようにします。
- 各ラウンドの勝者を発表します。
最終コード
local Players = game:GetService("Players")
local function onCharacterAdded(character, player)
player:SetAttribute("IsAlive", true)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
local points = player.leaderstats.Points
points.Value = 0
player:SetAttribute("IsAlive", false)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player:SetAttribute("IsAlive", false)
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
Players.PlayerAdded:Connect(onPlayerAdded)
while true do
task.wait(1)
local playerList = Players:GetPlayers()
for i = 1, #playerList do
local player = playerList[i]
if player:GetAttribute("IsAlive") then
local points = player.leaderstats.Points
points.Value += 1
end
end
end