Hướng dẫn này phác thảo một số kỹ thuật để sử dụng phát trực tuyến phiên bản trong trò chơi một cách hiệu quả và hiệu quả. Mặc dù không có giải pháp "một kích cỡ phù hợp với tất cả" cho việc thiết kế một trò chơi phát trực tuyến, nhưng việc làm theo các bước cấp cao này sẽ giúp bạn đi được phần lớn con đường.
Thuộc tính phát trực tuyến
Khi StreamingEnabled được bật cho đối tượng Workspace trong Studio, hãy đặt các thuộc tính liên quan của nó thành các giá trị được khuyến nghị sau:
| Thuộc tính | Khuyến nghị |
|---|---|
| EnableSLIMAvatars | Sử dụng Enabled để hiển thị các avatar rig tiêu chuẩn dưới dạng các hình đại diện nhẹ, hoạt hình khi thích hợp. Xem avatar SLIM để biết thêm thông tin. |
| ModelStreamingBehavior | Sử dụng Improved để kích hoạt phát trực tuyến hiệu quả nhất cho Models có các hậu duệ BasePart. |
| StreamingIntegrityMode | Sử dụng PauseOutsideLoadedArea để cân bằng tính toàn vẹn của gameplay mà không tạm dừng không cần thiết hoặc quá thường xuyên. |
| StreamingMinRadius | Sử dụng mặc định là 64 để tối đa hóa khả năng mà engine có thể thu nhỏ trò chơi cho các thiết bị cấu hình thấp. |
| StreamingTargetRadius | Sử dụng mặc định là 1024 để đạt được sự cân bằng tốt giữa khả năng hiển thị cho người chơi trên các thiết bị cấu hình cao và một dấu chân bộ nhớ hợp lý. |
| StreamOutBehavior | Sử dụng Opportunistic để cho phép client thu gom nội dung một cách quyết liệt, giảm đáng kể việc sử dụng bộ nhớ và giúp ngăn ngừa sự cố hết bộ nhớ. |
Mức độ chi tiết của mô hình
Model.LevelOfDetail giúp lấp đầy nội dung Model không được phát trực tuyến bằng các lưới composite hoặc hình đại diện nhẹ, làm cho thế giới trông hoàn chỉnh về mặt hình ảnh. SLIM (Mô hình tương tác nhẹ có thể mở rộng) đặc biệt hiệu quả, vì người chơi thường không thể phân biệt một lưới SLIM với bản gốc đã được phát trực tuyến hoàn toàn.
Để đạt được kết quả tốt nhất:
- Nhóm các phần có liên quan về không gian và logic, ví dụ như tất cả các phần của một chiếc xe.
- Đặt LevelOfDetail thành SLIM trên các mô hình chứa các lưới và phần tĩnh. Các mô hình được sửa đổi trong thời gian chạy hoặc phát hoạt ảnh không được hỗ trợ.
- Giữ kích thước không gian của mỗi mô hình dưới ~64 studs khối để tăng khả năng toàn bộ mô hình thực sự được phát trực tuyến cùng nhau. Nếu một mô hình có kích thước rất lớn, hãy chia nó thành các mô hình mô-đun nhỏ hơn và áp dụng một LevelOfDetail phù hợp cho mỗi mô hình.
Cấu trúc mô hình
Ngoài việc thiết lập mức độ chi tiết của mô hình, cấu trúc và cài đặt của Models của bạn có ảnh hưởng đáng kể đến hiệu suất phát trực tuyến. Khi bạn xây dựng hoặc chuyển đổi một trò chơi hiện có:
Sử dụng mô hình nguyên tử để nhóm logic — Khi một script cần truy cập tất cả các phần trong một mô hình, hãy đặt ModelStreamingMode của nó thành Atomic. Điều này cho phép các script phía client truy cập an toàn các instance bên trong mô hình mà không sử dụng quá mức WaitForChild() (mặc dù các script như vậy vẫn phải sử dụng WaitForChild() cho mô hình nguyên tử tổng thể).
Giảm thiểu các mô hình bền vững — Các mô hình bền vững tải sau khi tham gia và không bao giờ phát trực tuyến ra, chiếm dụng bộ nhớ vĩnh viễn. Đặt ModelStreamingMode của một mô hình thành Persistent chỉ khi nó phải luôn có sẵn và có thể truy cập cho các script mọi lúc.
Phân tách các mô hình chứa — Một mẫu không phát trực tuyến phổ biến là một Model khổng lồ chứa nhiều NPC, props hoặc các nhóm tương tự. Dưới phát trực tuyến, các mô hình chứa giảm hiệu quả phát trực tuyến và chúng không tối ưu cho mức độ chi tiết của mô hình mà hoạt động tốt nhất với các instance được nhóm lại gần nhau. Phân tách các mô hình chứa thành các mô hình nhỏ hơn với các phần gần nhau về mặt vật lý hoặc có liên quan về mặt logic.
Avatar SLIM
Các avatar nền tảng bên ngoài khu vực đang được phát trực tuyến không hiển thị theo mặc định, nhưng việc bật Workspace.EnableSLIMAvatars sẽ hiển thị các avatar rig tiêu chuẩn dưới dạng các hình đại diện nhẹ, hoạt hình khi thích hợp. Về cơ bản, engine:
- Hiển thị một phiên bản SLIM khi một mô hình avatar thực tế phát trực tuyến ra.
- Hoán đổi giữa các đại diện SLIM và độ phân giải đầy đủ dựa trên tài nguyên có sẵn, ngay cả bên trong bán kính phát trực tuyến.
- Giới hạn hoạt ảnh SLIM dựa trên tầm quan trọng của cảnh và băng thông có sẵn.
Avatar SLIM hỗ trợ các nhân vật người chơi rig tiêu chuẩn R15 với cơ thể, đầu, quần áo lớp và phụ kiện. Avatar R6, NPC và avatar có tỷ lệ tùy chỉnh bị loại trừ. Để biết danh sách đầy đủ các cấu hình avatar được hỗ trợ và bị loại trừ, dữ liệu hiệu suất và mẹo khắc phục sự cố, hãy xem avatar SLIM.
Mẫu script
Các mẫu script sau đây thường bị ảnh hưởng bởi phát trực tuyến. Chiến lược đúng phụ thuộc vào ý định của mã, vì vậy mỗi mẫu liệt kê nhiều tùy chọn khi thích hợp.
Chỉ mục trực tiếp đến các hậu duệ
Việc chỉ mục vào các hậu duệ của Workspace bằng toán tử . sẽ ném ra lỗi nếu bất kỳ instance nào trong đường dẫn không được phát trực tuyến. Điều này cũng áp dụng cho FindFirstChild(), FindFirstChildWhichIsA() và FindFirstChildOfClass() mà trả về nil nếu đứa trẻ chưa được phát trực tuyến.
local house1 = workspace:FindFirstChild("House1") -- nil nếu "House1" chưa được phát trực tuyến
local door = workspace.House1.Door -- Hỏng nếu "House1" hoặc "Door" chưa được phát trực tuyếnMột mẫu tương tự là truy cập Humanoid hoặc các hậu duệ nhân vật khác trực tiếp bên trong một kết nối Player.CharacterAdded. Dưới phát trực tuyến, mô hình nhân vật được gán cho Workspace trước khi tất cả các hậu duệ của nó được sao chép, vì vậy việc chỉ mục trực tiếp sẽ thất bại.
local Players = game:GetService("Players")
local player = Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
local humanoid = character.Humanoid
end)Nếu script không thể tiến triển mà không có một instance, hãy chờ nó với WaitForChild():
local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")Các instance được gửi từ xa
Một tín hiệu RemoteEvent/RemoteFunction và instance mà nó tham chiếu di chuyển độc lập, vì vậy tín hiệu có thể đến client trước khi instance có mặt — hoặc instance có thể không bao giờ có mặt. Hai nguyên nhân có thể bao gồm:
Dưới phát trực tuyến, có thể có một chút độ trễ giữa khi một phần/mô hình được tạo trên server và khi nó được sao chép đến các client. Về cơ bản, một phần được tham chiếu bởi một RemoteEvent/RemoteFunction có thể đơn giản là chưa tồn tại, ngay cả bên trong một khu vực đã được phát trực tuyến.
Gửi một tham chiếu phần/mô hình từ server đến client thông qua một RemoteEvent hoặc RemoteFunction yêu cầu rằng instance được sao chép đến client nhận. Gửi một đường dẫn instance dưới dạng chuỗi có cùng vấn đề, vì đường dẫn có thể giải quyết đến một vị trí không tồn tại trên client:
Script Clientlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")remoteEvent.OnClientEvent:Connect(function(data)local checkpoint = data.checkpoint -- Lỗi nếu "checkpoint" chưa được phát trực tuyếnlocal level = workspace.Levels[data.levelPath] -- Lỗi nếu đường dẫn chưa được phát trực tuyếnend)
Nếu script của client nhận cần instance để tiếp tục, hãy bao gồm WaitForChild() trước khi sử dụng nó. Lưu ý rằng điều này có thể chờ vô thời hạn nếu instance không bao giờ được phát trực tuyến, vì vậy hãy xem xét việc thêm một thời gian chờ làm tham số thứ hai của WaitForChild().
Khách hàng không đồng bộ
Sự không đồng bộ phía client nên được coi là một ngoại lệ, không phải là một mẫu thiết kế tiêu chuẩn. Việc giới thiệu các bản sao chỉ dành cho client hoặc thay đổi vị trí các instance cục bộ có thể tạo ra các vấn đề nghiêm trọng. Kiểm tra mã của bạn cho những nơi phụ thuộc vào những loại thay đổi này tồn tại trên client.
Ví dụ, việc thay đổi vị trí một instance cục bộ từ ReplicatedStorage sang Workspace có thể khiến instance đó đủ điều kiện để được phát trực tuyến ra. Tương tự, việc sao chép một instance cục bộ (Instance:Clone()) từ ReplicatedStorage vào Workspace tạo ra một bản sao chỉ dành cho client không còn là một phần của quy trình sao chép server và sẽ không nhận được các cập nhật thuộc tính từ instance gốc thuộc server.
Khái niệm tương tự áp dụng khi gọi Instance:Destroy() trên client cho một đối tượng thuộc server. Điều này xóa instance cục bộ nhưng server vẫn có nó, vì vậy nó sẽ được phát trực tuyến trở lại với trạng thái gốc khi đủ điều kiện.
Phát trực tuyến chủ động
Khi điểm đến tiếp theo của người chơi có thể được dự đoán, hãy thực hiện các cuộc gọi phía server đến Player:RequestStreamAroundAsync() để phát trực tuyến các khu vực tạm thời cho việc tải tạm thời, hoặc sử dụng Player:AddReplicationFocus() trên cơ sở hạn chế cho các khu vực nên được giữ lại cho đến khi được giải phóng một cách rõ ràng.
Ví dụ, khi một nhân vật người chơi sắp sửa dịch chuyển bằng cách thay đổi CFrame đến nhà của một người chơi khác ở một vị trí xa, bạn có thể tiền lấy khu vực đích để giảm thiểu hiện tượng pop-in và cung cấp một chuyển tiếp mượt mà hơn. Script sau đây cho thấy cách một sự kiện từ xa từ client đến server có thể được phát để di chuyển một nhân vật người chơi bằng phương pháp tiền lấy. Nếu yêu cầu tiền lấy thành công khi hàm trả về, bán kính tối thiểu xung quanh vị trí mục tiêu nên có mặt trên client.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- Yêu cầu phát trực tuyến xung quanh vị trí mục tiêu
player:RequestStreamAroundAsync(teleportTarget)
-- Dịch chuyển nhân vật
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- Gọi hàm dịch chuyển khi client phát sự kiện từ xa
teleportEvent.OnServerEvent:Connect(teleportPlayer)Đọc thuộc tính instance
Khi một instance phát trực tuyến ra, các cập nhật thuộc tính của nó không còn được sao chép đến client đó nữa. Việc đọc các thuộc tính như BasePart.Position vẫn tiếp tục thành công nhưng trả về giá trị đã sao chép cuối cùng có thể đã lỗi thời.
local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Vị trí có thể đã lỗi thời nếu "target" đã phát trực tuyến ra
local dist = (target.Position - player.Character.HumanoidRootPart.Position).MagnitudeDi chuyển logic đến server, vì các script phía server thấy tất cả các instance mọi lúc. Đây thường là tùy chọn đáng tin cậy nhất cho các kiểm tra khoảng cách và các logic nhạy cảm với vị trí khác.
Chờ trên đường đi quan trọng
Một số trò chơi không phát trực tuyến tải bản đồ của chúng bằng cách sao chép nó từ ReplicatedStorage vào Workspace, sau đó chờ nó trên client trước khi bỏ qua màn hình tải và báo hiệu sẵn sàng. Dưới phát trực tuyến, điều này sẽ treo vô thời hạn — nhân vật của client chưa được sinh ra, vì vậy không có tập trung sao chép, và instance bản đồ không bao giờ được phát trực tuyến.
Di chuyển logic màn hình tải để nó không phụ thuộc vào một instance không gian cụ thể có mặt, ví dụ bằng cách báo hiệu sẵn sàng khi nhân vật đã sinh ra và khu vực xung quanh ngay lập tức đã được phát trực tuyến.
Xử lý thay đổi tín hiệu
Các tín hiệu như Instance.ChildAdded/Instance.ChildRemoved và các tín hiệu CollectionService như GetInstanceAddedSignal() hoặc GetInstanceRemovedSignal() cũng phát ra khi phát vào/ra, không thể phân biệt với các lần sinh/xóa thực sự. Các script nhận không thể phân biệt sự khác biệt chỉ từ tín hiệu, vì vậy logic giả định một tín hiệu tương ứng với một sự kiện "thực" cần được cập nhật.
Kiểm tra các script cho bất kỳ trình lắng nghe tín hiệu nào có thể bị hỏng hoặc thay đổi đáng kể khi được kích hoạt bởi phát vào và/hoặc phát ra. Ví dụ, nếu bạn phát âm thanh hoặc hiệu ứng hình ảnh khi một NPC kẻ thù lần đầu tiên xuất hiện vào thế giới, hãy gán cho mỗi kẻ thù một thuộc tính như Spawned khi lần sinh đầu tiên, và bỏ qua việc phát lại cùng âm thanh/hiệu ứng trong các lần phát vào sau của kẻ thù.
local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "Enemy"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- Đặt thuộc tính "Spawned" trên kẻ thù cho lần sinh đầu tiên
enemy:SetAttribute("Spawned", true)
-- Phát âm thanh/hiệu ứng hình ảnh cho lần sinh đầu tiên này
playSpawnEffects(enemy)
end
end)Lặp qua các bộ sưu tập
Các lần lặp qua bộ sưu tập phía client như Instance:GetChildren() và Instance:GetDescendants() chỉ trả về tập hợp các hậu duệ đã được phát vào. Điều này áp dụng ngay cả khi cha của nó luôn được sao chép, chẳng hạn như một Folder trực tiếp dưới Workspace mà các hậu duệ không gian của nó phát vào và ra.
local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Thư mục "Homes" luôn được sao chép nhưng các con của nó phát vào và ra
-- Vòng lặp này có thể bỏ lỡ những ngôi nhà không được phát vào hiện tại
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
endNếu cần một sự liệt kê hoàn chỉnh, hãy thực hiện quét trên server và truyền kết quả cho người chơi thông qua một RemoteEvent nếu cần.
Truy vấn không gian
Các truy vấn không gian phía client như WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox(), và Model:GetBoundingBox() chỉ phản ánh nội dung đã được phát vào. Việc đó có phải là một vấn đề hay không phụ thuộc vào mục đích sử dụng của truy vấn.
Sử dụng server cho các truy vấn mà kết quả của nó phải phản ánh toàn bộ thế giới, ví dụ như một raycast kiểm tra xem người chơi có tầm nhìn đến một mục tiêu xa hay không.
Các mẫu khác
Các mẫu sau đây cũng có thể áp dụng và nên được xem xét cẩn thận:
Một Sound hoặc AudioPlayer được gán cho một đối tượng 3D sẽ dừng lại khi đối tượng đó phát ra. Đối với âm thanh môi trường nên tồn tại bất kể phát trực tuyến, hãy gán bộ phát cho một mô hình bền vững hoặc cho một container không phát trực tuyến.
Các đối tượng UI trong trò chơi như BillboardGui hoặc SurfaceGui cũng như các hiệu ứng hình ảnh như Beams hoặc Highlights mà adornee hoặc gắn kết của chúng phát ra sẽ dừng lại việc hiển thị. Đây có thể là hành vi mong muốn, nhưng bạn nên xác minh điều đó.
Các sự kiện BasePart.Touched, ProximityPrompts, DragDetectors, và ClickDetectors không hoạt động cho những người chơi mà client của họ không có phần/mô hình liên quan được phát vào. Nếu tương tác phải có thể từ bất kỳ khoảng cách nào, mô hình cần phải bền vững hoặc tương tác cần một cơ chế khác.
Đối với PathfindingService và tìm đường phía client, bộ tìm đường chỉ thấy hình học đã được phát vào trên client và nó có thể đi qua các chướng ngại vật tồn tại trên server. Xem ở đây để biết các chiến lược.
Điều kiện kiểm tra thực tế
Khi các script đã được cập nhật, hãy kiểm tra trò chơi một cách kỹ lưỡng. Các lỗi phát trực tuyến thường chỉ xuất hiện ở các rìa của khu vực phát trực tuyến hoặc trong quá trình chuyển tiếp, vì vậy chỉ kiểm tra gần điểm sinh hoặc tại bán kính mục tiêu là không đủ.
Kiểm tra với Workspace.StreamingTargetRadius được đặt thành giá trị tối thiểu của nó (64). Một số lỗi phát trực tuyến chỉ xuất hiện khi khu vực phát trực tuyến nhỏ.
Chơi qua các mẫu di chuyển đầy đủ của trò chơi, dịch chuyển giữa các khu vực xa, và quay lại các khu vực sau khi rời khỏi chúng. Đây là những tình huống mà phát vào và phát ra được thực hiện nhiều nhất.
Sử dụng overlay gỡ lỗi phát trực tuyến để theo dõi các cài đặt phát trực tuyến đang hoạt động, các khu vực hiện đang được tải và trạng thái phát trực tuyến trong thời gian thực.
Theo dõi cửa sổ Output và Developer Console để tìm lỗi, vì nhiều mẫu script tạo ra lỗi thay vì hành vi sai lầm im lặng. Chú ý đặc biệt đến các lỗi có dạng attempt to index nil with ... thường chỉ ra một cuộc gọi WaitForChild() bị thiếu.
Trang bị và kích hoạt Tools, bắn vũ khí và kích hoạt các tương tác trò chơi khác nhau.
Kỹ năng chuyển đổi phát trực tuyến AI
Để hỗ trợ với việc chuyển đổi và tối ưu hóa phát trực tuyến, Roblox cung cấp một kỹ năng phát trực tuyến AI, có thể truy cập từ MCP server trong Studio. Kỹ năng này tự động đánh giá trò chơi của bạn, áp dụng các cấu hình được khuyến nghị và dọn dẹp các vấn đề tương thích, bao gồm:
- Cấu hình các cài đặt phát trực tuyến theo các tiêu chuẩn được khuyến nghị.
- Đặt mức độ chi tiết cho các mô hình thành SLIM khi có thể.
- Tái cấu trúc cấu trúc mô hình để đạt được kích thước và chất lượng hình ảnh tối ưu.
Để sử dụng kỹ năng AI trong trò chơi của bạn:
- QUAN TRỌNGSao lưu trò chơi của bạn. Quá trình chuyển đổi có thể phức tạp, vì vậy bạn nên luôn lưu một bản sao lưu (Tệp ⟩ Xuất bản đến Roblox Như) trước khi chạy kỹ năng.
Bạn có thể chạy kỹ năng này bằng bất kỳ LLM nào bạn thích thông qua Mô hình Ngữ cảnh Giao thức (MCP) trong Studio. Các mô hình AI cao cấp với các cửa sổ ngữ cảnh lớn được khuyến nghị; trong Claude Opus, quá trình chuyển đổi điển hình mất 20-30 phút và sử dụng khoảng 200.000 token ngữ cảnh.
- Mở trò chơi của bạn trong Studio.
- Tải xuống kỹ năng và, trong client AI của bạn, mở thư mục đã giải nén (roblox-streaming-conversion) như là dự án hiện tại.
- Chạy kỹ năng với /rbx-convert-to-streaming.
- Như với bất kỳ đầu ra AI nào, hãy xác minh kết quả và kiểm tra trò chơi của bạn một cách kỹ lưỡng dưới các điều kiện kiểm tra thực tế.

