이전 튜토리얼에서는 사라지는 플랫폼과 치명적인 용암 등 다양한 경험 기능을 만들었습니다. 이번 튜토리얼에서는 사용자가 생존하는 동안 누가 가장 오래 버티는지를 확인할 수 있는 플레이 가능한 경험으로 이 모든 것을 연결합니다. 사용자가 생존하는 매 초마다 점수가 추가됩니다.
설정하기
먼저 경험을 위한 장면을 설정해야 합니다. 이전 튜토리얼에서 만든 사라지는 플랫폼을 복제하여 사용자가 가능한 한 오랜 시간 동안 플랫폼 보드에 머물도록 경합하게 하세요.
또한 치명적인 용암을 사용하여 사용자가 플랫폼에서 떨어질 때 죽게 하거나, 그냥 그들이 멸망하는 대로 두어도 됩니다. 사용자가 플랫폼에 점프하여 플레이를 시작할 수 있도록 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 폴더의 값들을 읽고 찾은 내용을 표시합니다.
플레이어의 점수를 추적할 통계를 추가하기 위해, leaderstats 폴더에 새 IntValue 개체를 부모로 할 수 있습니다. 값 개체의 이름은 현재 값과 함께 표시됩니다.
- 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 루프를 생성하여 각 사용자에 대해 한 번의 반복을 수행합니다.
while true dotask.wait(1)local playerList = Players:GetPlayers()for currentPlayer = 1, #playerList do-- Add your logic here for each player in the playerListendend
점수 부여하기
for 루프에서 각 사용자에게 점수를 부여하려면 배열에서 사용자를 꺼내고 Points 개체에 1을 추가해야 합니다.
배열에 저장된 개체는 대괄호를 사용하여 접근합니다. 예를 들어 playerList 배열의 첫 번째 항목은 playerList[1]로 접근할 수 있습니다. for 루프에서 playerList[currentPlayer]를 쓰면 루프의 매 반복에서 각 사용자에 접근할 수 있습니다.
- playerList[currentPlayer]의 사용자를 player라는 변수에 저장합니다.
- 사용자의 Points 개체를 points라는 변수에 저장합니다.
- Value 속성을 points.Value + 1로 설정합니다.
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 이벤트를 사용하여 캐릭터가 준비되었을 때를 감지할 수 있습니다. character와 player라는 두 개의 매개변수를 가진 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")
end
Died 이벤트에 연결해야 하는 함수는 매우 짧고 여기서만 필요하므로 익명 함수를 사용할 수 있습니다.
- 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 함수를 사용하여 임의의 객체에 속성을 생성할 수 있습니다. SetAttribute를 player에 호출하여 새 속성인 "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으로 유지되는 것을 확인할 수 있습니다. 친구들과 함께 플레이하여 누가 가장 높은 점수를 얻는지 확인해보세요.
이것은 단지 시작일 뿐입니다. 사용자의 경험을 계속 개선할 수 있습니다. 몇 가지 팁은 다음과 같습니다:
- 모든 플랫폼에 대한 코드를 하나의 스크립트에 배치하여 업데이트를 훨씬 더 쉽게 만드세요.
- 사용자가 경험 영역으로 전송되기를 기다리는 로비 공간을 만드세요. 이를 통해 사용자가 동시에 시작할 수 있습니다.
- 각 라운드의 승자를 발표하세요.
최종 코드
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