DataModel
*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.
Data Model (còn được gọi là game sau khi biến đổi toàn cầu được sử dụng để truy cập nó) là nền tảng của hệ thống cha-con Roblox. Các con của nó trực tiếp là các dịch vụ, chẳng hạn như
Mẫu mã
local Workspace = game:GetService("Workspace")
local Lighting = game:GetService("Lighting")
-- Examples of modifying properties of these services
Workspace.Gravity = 20
Lighting.ClockTime = 4
Tóm Tắt
Thuộc Tính
Mô tả ID của người dùng hoặc nhóm sở hữu địa điểmnày.
Mô tả Enum.CreatorType của địa điểmđó, whether nó thuộc sở hữu của người dùng hay một nhóm.
Mô tả ID của trải nghiệm mà nơi đang chạy trên máy chủ thuộc về.
Không hoạt động. Mô tả trong quá khứ Enum.Genre của nơi này như đã đặt trên trang Roblox.
Một thẻ hiệu suất độc đáo cho máy chủ trò chơi đang chạy.
Mô tả ID của nơi chạy trên máy chủ.
Mô tả phiên bản của nơi mà máy chủ đang chạy.
Mô tả ID máy chủ riêng của máy chủ, nếu máy chủ là máy chủ riêng hoặc một reserved server .
Mô tả UserId của Class.Player mà sở hữu máy chủ riêng nếu máy chủ là riêng tư.
Một tham khảo đến dịch vụ Workspace .
Phương Pháp
Làm cho một chức năng để gọi trước khi máy chủ khởi động lại.
Trả lại một bảng chứa các thông tin cơ bản về các công việc đã thực hiện bởi lịch trình lựa chọn nhiệm vụ.
Đảm bảo một loạt các Instances được liên kết với URL nội dung đã được cung cấp.
Trả lại true nếu khách hàng đã hoàn thành việc tải trò chơi lần đầu tiên.
Đặt DataModel.PlaceId của game hiện tại vào nơi được cho placeId .
Đặt DataModel.GameId của game hiện tại vào universeId đã được cho.
Trả lại dịch vụ được xác định bởi tên người dùng đã được tạo, lỗi cho một tên không hợp lệ.
Trả lại dịch vụ với tên lớp yêu cầu, tạo nó nếu nó không tồn tại.
Sự Kiện
Kích hoạt khi người dùng nhập lệnh và tăng hoặc giảm chất lượng đồ họa bằng cách sử dụng các phím nóng.
Lửa trên khách khi game kết thúc tải lần đầu tiên.
Lửa khi bạn rời khỏi nơi hiện tại.
Được kích hoạt khi một dịch vụ được tạo.
Đã kích hoạt khi một dịch vụ sắp bị xóa.
Thuộc Tính
CreatorId
Thuộc tính này mô tả ID của người dùng hoặc nhóm mà sở hữu địa điểmđó. Nếu thuộc tính DataModel.CreatorType là 'User' thì CreatorId sẽ là ID của nhóm Class
Mẫu mã
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
if game.CreatorType == Enum.CreatorType.User then
if player.UserId == game.CreatorId then
print("The place owner has joined the game!")
end
elseif game.CreatorType == Enum.CreatorType.Group then
if player:IsInGroup(game.CreatorId) then
print("A member of the group that owns the place has joined the game!")
end
end
end)
CreatorType
Thuộc tính này mô tả Enum.CreatorType của địa điểmđó, dù nó thuộc sở hữu của người dùng hay một nhóm.
Nếu Enum.CreatorType là 'Người dùng' , thì DataModel.CreatorId tính năng sẽ mô tả Class.Player.UserId|UserId của tài khoản mà sở hữu trò chơi. Nếu 1> Amount.CreatorType là1> Group, th
Mẫu mã
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
if game.CreatorType == Enum.CreatorType.User then
if player.UserId == game.CreatorId then
print("The place owner has joined the game!")
end
elseif game.CreatorType == Enum.CreatorType.Group then
if player:IsInGroup(game.CreatorId) then
print("A member of the group that owns the place has joined the game!")
end
end
end)
GameId
Thuộc tính này mô tả ID của trải nghiệm mà nơi đang chạy trên máy chủ thuộc về.
ID này có thể được tìm thấy ở góc trên bên phải của Asset Manager trong Roblox Studio. Khi sử dụng Roblox Studio, nếu nơi đó chưa được xuất bản lên Roblox thì GameId sẽ được tương ứng với mẫu đang được sử dụng.
Xem thêm:
- DataModel.PlaceId , mô tả ID của nơi đang chạy trên máy chủ
- DataModel.JobId , which is a unique identifier for the server game instance running
- TeleportService , which is a service that can be used to transport Players between games
Genre
Thuộc tính này đã bị hỏng và không nên sử dụng.
Đặ性 này trước đây mô tả Enum.Genre của nơi này như được thiết lập trên trang Roblox.
Điều này, cùng với DataModel.GearGenreSetting , không còn hoạt động một cách chính xác do sự tồn tại của các thể loại trên trang Roblox hiện tại không được phản ánh trong hồ sơ Enum.Genre . Do kết quả, khi cố gắng đọc thuộc tính này có thể thả
JobId
Đây là một nhận dạng độc đáo cho máy chủ trò chơi ví dụ / trường hợpchạy. Nó là một nhận dạng độc nhất (UUID), có nghĩa là không có hai máy chủ, trong quá khứ hoặc hiện tại, sẽ bao giờ không có cùng một ID.
Mặc định cho một dòng trống trong Studio.
Xem thêm
- TeleportService:GetPlayerPlaceInstanceAsync() which can be used to retrieve the DataModel.JobId of a user's current máy chủ.
- TeleportService:TeleportToPlaceInstance() which can be used to teleport a Player to a specific máy chủ.
- DataModel.PrivateServerId mô tả ID của máy chủ game thuộc về game server instance.
- HttpService:GenerateGUID() , một hàm có thể được sử dụng để tạo UUID của riêng bạn.
PlaceId
Thuộc tính này mô tả ID của nơi chạy trên máy chủ.
Nếu nơi đã được đăng trên Roblox, ID này có thể được tìm thấy trong Studio's Asset Manager bằng cách nhấp chuột phải vào nơi trong thư mục Places và chọn Copy ID to Clipboard .
Nếu nơi đó chưa được xuất bản lên Roblox, thì ID này sẽ tương ứng với mẫu đang được sử dụng.
Xem thêm
- DataModel.GameId , mô tả ID của trải nghiệm mà hiện tại địa điểm thuộc về
- DataModel.JobId , which is a unique identifier for the server game instance running
- TeleportService , which is a service that can be used to transport Players between places
PlaceVersion
Thuộc tính này mô tả phiên bản mà máy chủ đang chạy trên.
Phiên bản này được tương ứng với số phiên bản được hiển thị dưới mục Lịch sử phiên bản của cài đặt nơi. Đây không phải là phiên bản hiện tại của client Roblox. Đặt này là 0 cho tất cả các trải nghiệm không đăng nhập.
Khi một máy chủ bị tạo cho một địa điểm, nó sử dụng phiên bản hiện tại của địa điểmđó. Nếu nơi đó được cập nhật sau khi máy chủ này chạy, máy chủ sẽ ở trong phiên bản hiện tại của nó.
Thuộc tính này có thể được sử dụng để hiển thị một ScreenGui đang hiển thị phiên bản hiện tại của trò chơi cho Players để giúp với việc đăng nhập.
Mẫu mã
local StarterGui = game:GetService("StarterGui")
local versionGui = Instance.new("ScreenGui")
local textLabel = Instance.new("TextLabel")
textLabel.Position = UDim2.new(1, -10, 1, 0)
textLabel.AnchorPoint = Vector2.new(1, 1)
textLabel.Size = UDim2.new(0, 150, 0, 40)
textLabel.BackgroundTransparency = 1
textLabel.TextColor3 = Color3.new(1, 1, 1)
textLabel.TextStrokeTransparency = 0
textLabel.TextXAlignment = Enum.TextXAlignment.Right
textLabel.TextScaled = true
local placeVersion = game.PlaceVersion
textLabel.Text = string.format("Server version: %s", placeVersion)
textLabel.Parent = versionGui
versionGui.Parent = StarterGui
PrivateServerId
Thuộc tính này mô tả ID máy chủ riêng của máy chủ, nếu máy chủ là một máy chủ riêng.
Nếu máy chủ không phải là máy chủ riêng, thì đây sẽ là một dòng chuỗi trống.
Server riêng
Các máy chủ riêng tham khảo đến các điều sau theo dõi:
- Máy chủ riêng mà người dùng có thể mua từ trang trò chơi
- Các máy chủ dự phòng, máy chủ riêng tạo bởi nhà phát triển bằng cách sử dụng TeleportService:ReserveServer()
PrivateServerId vs JobId
PrivateServerId của một máy chủ khác với DataModel.JobId . The JobId is the unique identifier of the máy ví dụ / trường hợphiện tại.
Các máy chủ riêng (hoặc các máy chủ dự phòng) có thể có nhiều máy chủ instanh mà họ có thể thời gian thông qua. Điều này là bởi vì, mặc dù chỉ có một máy chủ instanh có thể chạy cùng một lúc cho một máy chủ riêng,
Xem thêm:
- DataModel.PrivateServerOwnerId , một tính năng mô tả chủ sở hữu của một máy chủ riêng
- TeleportService:ReserveServer() , một hàm tạo ra một máy chủ dự phòng
Mẫu mã
local function getServerType()
if game.PrivateServerId ~= "" then
if game.PrivateServerOwnerId ~= 0 then
return "VIPServer"
else
return "ReservedServer"
end
else
return "StandardServer"
end
end
print(getServerType())
PrivateServerOwnerId
Thuộc tính này mô tả UserId của Class.Player mà sở hữu Player nếu máy chủ là riêng tư.
Nếu máy chủ là một máy chủ tiêu chuẩn hoặc dự phòng thì giá trị này sẽ được thiết lập thành 0 .
Đặc tính này có thể được sử dụng để xác định nếu một Player là chủ sở hữu của máy chủ riêng, ví dụ:
local Players = game:GetService("Players")
-- đây có phải là một máy chủ riêng?
if game.PrivateServerId ~= "" and game.PrivateServerOwnerId ~= 0 then
-- lắng nghe những người chơi mới được thêm
Players.PlayerAdded:Connect(function(player)
-- kiểm tra nếu người chơi là chủ sở hữu của máy chủ
if player.UserId == game.PrivateServerOwnerId then
print("The private server owner has joined the game")
end
end)
end
Xem thêm:
- DataModel.PrivateServerId , một tính năng mô tả ID độc đáo của riêng tư và reserved servers
Mẫu mã
local function getServerType()
if game.PrivateServerId ~= "" then
if game.PrivateServerOwnerId ~= 0 then
return "VIPServer"
else
return "ReservedServer"
end
else
return "StandardServer"
end
end
print(getServerType())
Workspace
Thuộc tính Workspace là một tham chiếu đến dịch vụ Workspace.
Điều này luôn luôn chỉ đến Workspace và sẽ không bao giờ nil .
Class.Workspace cũng có thể được truy cập bằng cách sử dụng biến toàn cầu workspace và hàm ServiceProvider:GetService() . Ví dụ:
workspace -- một biến toàn cầugame.Workspace -- một tính năng của DataModel (trò chơi)game:GetService("Workspace") -- workspace is a service
Phương Pháp
BindToClose
Kết nối một chức năng để được gọi trước khi máy chủ kết thúc. Nếu chức năng được kết nối một tham số, nó truyền Enum.CloseReason để xác định lý do tại sao máy chủ kết thúc.
Bạn có thể liên kết nhiều chức năng bằng cách gọi BindToClose() nhiều lần. Các chức năng liên kết được gọi trong paralel và chạy cùng một lúc.
Máy chủ trải nghiệm chờ 30 giây cho tất cả các chức năng liên quan đến ngừng chạy trước khi nó kết thúc. Sau 30 giây, máy chủ vẫn kết thúc ngay cả khi các chức năng vẫn đang chạy.
Để xác nhận rằng phiên hội thảo hiện tại không ở Roblox Studio, hãy sử dụng RunService:IsStudio() . Điều này ngăn chặn các hàm liên kết khỏi hoàn thành chạy trong các phiên hội thảo ngoài hành lang.
Khi bạn sử dụng DataStoreService, bạn cũng nên sử dụng BindToClose để kết nối một chức năng lưu tất cả các dữ liệu không lưu vào DataStores . Điều này ngăn chặn sự mất mát dữ liệu nếu máy chủ bị khởi động
Xem thêm:
- Enum.CloseReason vì lý do cho máy chủ ngừng hoạt động.
- PluginGui:BindToClose() , which binds a function to a PluginGui close button.
Tham Số
Một hàm được gọi trước khi máy chủ kinh nghiệm bị tắt. Nếu hàm được liên kết, nó sẽ truyền Enum.CloseReason để đặt lý do cho sự tắt máy chủ.
Lợi Nhuận
Mẫu mã
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")
local allPlayerSessionDataCache = {}
local function savePlayerDataAsync(userId, data)
return playerDataStore:UpdateAsync(userId, function(oldData)
return data
end)
end
local function onServerShutdown(closeReason)
if RunService:IsStudio() then
-- Avoid writing studio data to production and stalling test session closing
return
end
-- Reference for yielding and resuming later
local mainThread = coroutine.running()
-- Counts up for each new thread, down when the thread finishes. When 0 is reached,
-- the individual thread knows it's the last thread to finish and should resume the main thread
local numThreadsRunning = 0
-- Calling this function later starts on a new thread because of coroutine.wrap
local startSaveThread = coroutine.wrap(function(userId, sessionData)
-- Perform the save operation
local success, result = pcall(savePlayerDataAsync, userId, sessionData)
if not success then
-- Could implement a retry
warn(string.format("Failed to save %d's data: %s", userId, result))
end
-- Thread finished, decrement counter
numThreadsRunning -= 1
if numThreadsRunning == 0 then
-- This was the last thread to finish, resume main thread
coroutine.resume(mainThread)
end
end)
-- This assumes playerData gets cleared from the data table during a final save on PlayerRemoving,
-- so this is iterating over all the data of players still in the game that hasn't been saved
for userId, sessionData in pairs(allPlayerSessionDataCache) do
numThreadsRunning += 1
-- This loop finishes running and counting numThreadsRunning before any of
-- the save threads start because coroutine.wrap has built-in deferral on start
startSaveThread(userId, sessionData)
end
if numThreadsRunning > 0 then
-- Stall shutdown until save threads finish. Resumed by the last save thread when it finishes
coroutine.yield()
end
end
game:BindToClose(onServerShutdown)
game:BindToClose(function(closeReason)
print(`Closing with reason {closeReason}`)
task.wait(3)
print("Done")
end)
GetJobsInfo
Trả lại một bảng chứa các thông tin cơ bản về các công việc đã thực hiện bởi lịch trình lựa chọn nhiệm vụ.
Trong công nghệ, một lịch trình nhiệm vụ là một hệ thống chịu trách nhiệm thực hiện các nhiệm vụ chính ở các thời điểm thích hợp.
Bạn cũng có thể tìm thấy các chỉ số lịch trình nhiệm vụ trực tiếp trong cửa sổ Lịch trình nhiệm vụ trong Roblox Studio.
Ghi nhận đầu tiên trong bảng trả về là một từ điển tham khảo chứa các chỉ số (hoặc đầu mục) có sẵn. Nó được trình bày như sau:
{["name"] = "name",["averageDutyCycle"] = "averageDutyCycle",["averageStepsPerSecond"] = "averageStepsPerSecond",["averageStepTime"] = "averageStepTime",["averageError"] = "averageError",["isRunning"] = "isRunning",}
Các mục tiếp theo trong bảng được trả lại là các từ điển chứa các thống kê trên đó bao gồm các công việc được thực hiện bởi lịch trình lựa chọn nhiệm vụ. Ví dụ:
{["name"] = "Heartbeat",["averageDutyCycle"] = 0,["averageStepsPerSecond"] = 0,["averageStepTime"] = 0,["averageError"] = 0,["isRunning"] = false,}
Xem thêm:
Lợi Nhuận
Một bảng chứa thông tin về các công việc được thực hiện bởi lịch trình lựa chọn công việc, xem trên để biết hình dạng.
Mẫu mã
local jobInfo = game:GetJobsInfo()
local jobTitles = jobInfo[1]
table.remove(jobInfo, 1)
local divider = string.rep("-", 120)
print(divider)
warn("JOB INFO:")
print(divider)
for _, job in pairs(jobInfo) do
for jobIndex, jobValue in pairs(job) do
local jobTitle = jobTitles[jobIndex]
warn(jobTitle, "=", jobValue)
end
print(divider)
end
GetObjects
Phương thức này trả về một loạt các Instances được liên kết với URL nội dung đã được cung cấp. Nó có thể được sử dụng để tạo nội dung từ thư viện Roblox. Nó không thể tạo ra nội dung Class.Sound
Class.InsertService:LoadAsset() , DataModel:GetObjects() không yêu cầu một tài sản để được "tin cậy", có nghĩa là một tài sản không cần phải thuộc sở hữu bởi người dùng đăng nhập hoặc tạo bởi Roblox để được tích
Do hệ thống bảo mật của chức năng này, nó chỉ có thể được sử dụng bởi plugin hoặc dòng lệnh. Đối với một alternatif có thể được sử dụng trong Scripts và LocalScripts, xem InsertService:LoadAsset() .
Tham Số
Địa chỉ URL nội dung đã được cung cấp.
Lợi Nhuận
Một mat阵 của Instances được liên kết với URL nội dung.
Mẫu mã
local Selection = game:GetService("Selection")
local WEB_URL = "plugin URL here"
local function downloadPlugin(webURL)
-- get the content URL
local contentID = string.match(webURL, "%d+")
local contentURL = "rbxassetid://" .. contentID
-- download the objects
local objects = game:GetObjects(contentURL)
-- decide where to parent them
local selection = Selection:Get()
local parent = #selection == 1 and selection[1] or workspace
-- parent the objects
for _, object in pairs(objects) do
object.Parent = parent
end
end
downloadPlugin(WEB_URL)
local IMAGES = {
-- Insert Decal web URLs in an array here (as strings)
}
-- open the dictionary
local outputString = "textures = {"
-- utility function to add a new entry to the dictionary (as a string)
local function addEntryToDictionary(original, new)
outputString = outputString
.. "\n" -- new line
.. " " -- indent
.. '["'
.. original
.. '"]' -- key
.. ' = "'
.. new
.. '",' -- value
end
print("Starting conversion")
for _, webURL in pairs(IMAGES) do
-- get the content URL
local contentID = string.match(webURL, "%d+")
local contentURL = "rbxassetid://" .. contentID
local success, result = pcall(function()
local objects = game:GetObjects(contentURL)
return objects[1].Texture
end)
if success then
addEntryToDictionary(webURL, result)
else
addEntryToDictionary(webURL, "Error downloading decal")
end
task.wait()
end
print("Conversion complete")
-- close the dictionary
outputString = outputString .. "\n}"
-- print the dictionary
print(outputString)
IsLoaded
Hàm này trả về true nếu khách hàng đã hoàn thành việc tải trò chơi lần đầu tiên.
Khi tất cả các Instances đầu tiên trong trò chơi đã hoàn thành sao chép đến client, hàm này sẽ trả về true.
Nếu chúng không được gắn với ReplicatedFirst , LocalScripts sẽ không chạy khi trò chơi chưa được tải. Các câu lệnh sau đây, chạy từ một LocalScript ở 1> Class.ReplicatedFirst1> sẽ
if not game:IsLoaded() thengame.Loaded:Wait()end
Xem thêm:
- DataModel.Loaded , một sự kiện xảy ra khi game đã tải
- Instance:WaitForChild() , một hàm có thể được sử dụng để chờ đợi một cá nhân Instance để sao chép mà không cần phải đợi toàn bộ trò chơi để
Lợi Nhuận
Whether the client has finished loading the game for the first time.
Mẫu mã
local Players = game:GetService("Players")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- Create a basic loading screen
local screenGui = Instance.new("ScreenGui")
screenGui.IgnoreGuiInset = true
local textLabel = Instance.new("TextLabel")
textLabel.Size = UDim2.new(1, 0, 1, 0)
textLabel.BackgroundColor3 = Color3.fromRGB(0, 20, 40)
textLabel.Font = Enum.Font.GothamMedium
textLabel.TextColor3 = Color3.new(0.8, 0.8, 0.8)
textLabel.Text = "Loading"
textLabel.TextSize = 28
textLabel.Parent = screenGui
-- Parent entire screen GUI to player GUI
screenGui.Parent = playerGui
-- Remove the default loading screen
ReplicatedFirst:RemoveDefaultLoadingScreen()
--wait(3) -- Optionally force screen to appear for a minimum number of seconds
if not game:IsLoaded() then
game.Loaded:Wait()
end
screenGui:Destroy()
SetPlaceId
Hàm này đặt DataModel.PlaceId của instância trò chơi lên placeId đã được cho.
Cài đặt cả hai DataModel.PlaceId và DataModel.GameId đều được yêu cầu để acces Class.
local DataStoreService = game:GetService("DataStoreService")-- truy cập DataStore 'Data' bằng cách đặt PlaceId để định vị nơi và GameId để định vị vũ trụ.game:SetPlaceId(placeId)game:SetUniverseId(universeId)local dataStore = DataStoreService:GetDataStore("Data")
Tham Số
ID để đặt DataModel.PlaceId vào.
Lợi Nhuận
SetUniverseId
Hàm này đặt DataModel.GameId của các thành phần trò chơi hiện tại lên universeId đã được đưa. Điều này hữu ích khi kiểm tra các tập tin rbxl địa phương không được xuất bản lên Roblox.
Để truy cập vào DataStoreService ở một địa điểmchưa được xuất bản, cả DataModel:SetUniverseId() và DataModel:SetPlaceId() đều phải được cài đặt.
Tham Số
ID để đặt Class.DataModel.GameId lên.
Lợi Nhuận
Sự Kiện
GraphicsQualityChangeRequest
Kích hoạt khi người dùng yêu cầu tăng hoặc giảm chất lượng đồ họa bằng cách sử dụng các phím nóng.
Sự kiện này bắt lửa dưới các điều kiện sau đây:
- Nếu người dùng nhấn F10, sự kiện này sẽ kích hoạt với một betterQuality参数 của true .
- Nếu người dùng nhấn ShiftF10 , sự kiện này bắt đầu với một betterQuality参数 của 0> false0> .
Sự kiện này không cung cấp mức chất lượng đồ họa hiện tại hoặc bao gồm tất cả các cập nhật đến chất lượng đồ họa. Ví dụ, những thay đổi được thực hiện trong menu thoát GUI chính không được đăng ký.
Bạn có thể lấy lại một người dùng's Enum.SavedQualitySetting bằng cách sử dụng UserGameSettings với các thẻ sau:
UserSettings():GetService("UserGameSettings").SavedQualityLevel
Nếu cài đặt đồ họa của người dùng được đặt thành tự động thì Enum.SavedQualitySetting sẽ là Automatic . Hiện tại không có cách nào để nhận được mức độ chất lượng đồ họa hiện tại của máy tính của ng
Tham Số
Dù người dùng đã yêu cầu tăng ( true ) hay giảm ( false ) trong chất lượng đồ họa.
Mẫu mã
game.GraphicsQualityChangeRequest:Connect(function(betterQuality)
if betterQuality then
print("The user has requested an increase in graphics quality!")
else
print("The user has requested a decrease in graphics quality!")
end
end)
Loaded
Sự kiện này sẽ bắt đầu trên client khi trò chơi kết thúc tải lần đầu tiên.
Sự kiện Loaded xảy ra khi tất cả các Instances đầu tiên trong game đã hoàn thành việc sao chép đến client.
Nếu chúng không được gắn với ReplicatedFirst , LocalScripts sẽ không chạy trước khi sự kiện này kết thúc. Các câu lệnh sau đây, chạy từ một LocalScript trong 1> Class.ReplicatedFirst1> , sẽ
if not game:IsLoaded() thengame.Loaded:Wait()end
Xem thêm:
- DataModel:IsLoaded() , một hàm trả về nếu trò chơi được tải hoặc không
- Instance:WaitForChild() , một hàm có thể được sử dụng để chờ đợi một cá nhân Instance để sao chép mà không cần phải đợi toàn bộ trò chơi được tải.