이전 튜토리얼에서는 사라지는 플랫폼과 치명적인 용암 등 다양한 게임 기능을 만들었습니다. 이번 튜토리얼에서는 이를 결합하여 사용자가 가장 오랫동안 살아남는지를 확인할 수 있는 플레이 가능한 게임을 만듭니다. 사용자가 살아 있는 매 초마다 점수가 추가됩니다.
설정하기
먼저 게임의 장면을 설정해야 합니다. 이전 튜토리얼에서 만든 사라지는 플랫폼을 복제하고 사용자가 가능한 한 오랫동안 플랫폼 보드 위에 머물도록 경쟁하게 하세요.
또한 치명적인 용암을 사용하여 사용자가 플랫폼에서 떨어질 때 죽게 하거나, 그냥 떨어지게 할 수 있습니다. 사용자가 플랫폼에 점프하여 게임을 시작할 수 있도록 SpawnLocation을 적절한 위치에 배치하세요.

플레이어 점수
Roblox에는 사용자 통계를 표시하기 위한 내장 리더보드가 있습니다. 리더보드를 통해 플레이어 점수를 설정하면 게임 화면의 오른쪽에 표시됩니다.

더 많은 사용자 정의 방법으로 정보를 표시하는 방법은 이후 튜토리얼에서 배우게 되지만, 리더보드는 Roblox에서 가시적인 점수 시스템을 만드는 가장 간단한 방법입니다.
게임 상태를 설정하는 스크립트는 ServerScriptService에 두는 것이 가장 좋습니다. 게임이 시작될 때 자동으로 실행됩니다. ServerScriptService에서 SetupPoints라는 스크립트를 만드세요.

플레이어 추가 감지
Roblox에서 서비스는 유용한 기능을 수행하는 객체입니다. Players 서비스에는 게임에 참여하는 각 사용자에 대한 점수를 설정하는 데 사용할 수 있는 PlayerAdded라는 이벤트가 있습니다.
서비스에 접근하려면 GetService 함수를 game 객체에서 사용할 수 있습니다. 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 do
task.wait(1)
end플레이어 목록
게임의 모든 사용자에 대해 코드를 실행하려면 GetPlayers 함수가 반환하는 배열을 반복해야 합니다.
배열은 순서대로 저장된 항목 목록입니다. 각 항목은 인덱스 위치로 접근할 수 있으며, 인덱스는 1부터 시작합니다. 배열의 길이는 #로 접두사를 붙여서 얻을 수 있습니다.
- Players:GetPlayers()의 결과를 playerList 변수에 저장합니다.
- 시작 값이 1이고 끝 값이 #playerList인 for 루프를 생성하여 각 플레이어에 대해 한 번의 반복을 수행합니다.
while true do
task.wait(1)
local playerList = Players:GetPlayers()
for currentPlayer = 1, #playerList do
-- playerList의 각 플레이어에 대한 로직을 여기에 추가하세요
end
end점수 부여하기
for 루프에서 각 사용자에게 점수를 부여하려면, 배열에서 사용자를 가져와서 그들의 leaderstats 폴더에 저장된 Points 객체에 1을 추가해야 합니다.
배열에 저장된 객체는 대괄호를 사용하여 접근합니다. 예를 들어, playerList 배열의 첫 번째 항목은 playerList[1]로 접근할 수 있습니다. for 루프에서 playerList[currentPlayer]를 작성하면 루프의 각 반복에서 목록의 각 사용자로 이동할 수 있습니다.
- playerList[currentPlayer]의 사용자를 player라는 변수에 저장합니다.
- 사용자의 Points 객체를 points라는 변수에 저장합니다.
- Value 속성을 points.Value + 1로 설정합니다.
while true do
task.wait(1)
local playerList = Players:GetPlayers()
for currentPlayer = 1, #playerList do
local player = playerList[currentPlayer]
local points = player.leaderstats.Points
points.Value += 1
end
end게임을 테스트하면 리더보드에서 플레이어의 점수가 매 초마다 1씩 증가하는 것을 확인할 수 있습니다.
캐릭터 감지하기
게임의 목표는 누가 가장 오랫동안 살아남는지를 확인하는 것이므로, 죽은 사용자는 점수를 0으로 리셋해야 합니다.
사용자의 Character 모델을 가져와야 사용자가 죽었는지를 감지할 수 있습니다. 이 모델은 Player 객체가 로드된 후에만 게임에 추가되며, CharacterAdded 이벤트를 사용하여 캐릭터가 준비되었을 때를 감지할 수 있습니다. onCharacterAdded라는 함수를 만들고, 캐릭터와 플레이어에 대한 두 개의 매개변수를 추가합니다.
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")
endDied 이벤트에 연결해야 하는 함수는 매우 짧고 여기서만 필요하므로, 다시 익명 함수를 사용할 수 있습니다.
- Humanoid의 Died 이벤트에 새로운 익명 함수를 연결합니다.
- 익명 함수 내에서 플레이어의 Points 객체에 대한 변수를 points로 만듭니다.
- Value 속성을 0으로 설정합니다.
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마지막으로, while 루프의 끝에서 점수를 부여하기 전에 IsAlive를 확인해야 합니다. GetAttribute 함수는 속성의 이름을 받아 값을 반환합니다. while 루프에서 점수를 부여하는 코드를 if 문으로 감싸고 조건을 player:GetAttribute("IsAlive")로 설정합니다.
while true do
task.wait(1)
local playerList = Players:GetPlayers()
for currentPlayer = 1, #playerList do
local player = playerList[currentPlayer]
if player:GetAttribute("IsAlive") then
local points = player.leaderstats.Points
points.Value += 1
end
end
end이제 게임을 테스트하면 사용자가 살아 있는 매 초마다 점수를 얻고, 죽어 있을 때는 0으로 유지되는 것을 확인할 수 있습니다. 친구들과 함께 플레이하여 누가 가장 높은 점수를 얻는지 확인해 보세요.
이것은 시작에 불과합니다. 사용자를 위해 게임을 계속 개선할 수 있습니다. 다음은 몇 가지 팁입니다:
- 모든 플랫폼에 대한 코드를 하나의 스크립트로 통합하여 업데이트를 훨씬 쉽게 만드세요.
- 사용자가 게임 영역으로 텔레포트되기 위해 대기하는 로비 영역을 만드세요. 이를 통해 사용자가 동시에 시작할 수 있습니다.
- 각 라운드의 승자를 발표하세요.
최종 코드
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