Luau song song

*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.

Với mô hình Parallel Luau lập trình, bạn có thể thiết lập mã trên nhiều luồng một lúc, ceo có thể tăng hiệu suất của trải nghiệm của bạn. Khi bạn mở rộng trải nghiệm của mình với nhiều nội dung hơn, bạn có thể chấp nhận mô hình này để giúp duy trì hiệu suất và

Mô Hình Lập Trình Điều Khiển

Mặc định, các script thực hiện theo thứ tự. Nếu trải nghiệm của bạn có độ phức tạp hoặc nội dung, chẳng hạn như nhân vật không phải người chơi (NPC), sự kiểm tra raycasting và tạo mô-đun, thì thực hiện theo thứ tự có thể gây ra th

Mô hình lập trình song song cũng thêm lợi ích an toàn cho mã của bạn. Bằng cách chia mã thành nhiều luồng, khi bạn chỉnh sửa mã ở một luồng, nó không ảnh hưởng đến các mã khác đang chạy song song. Điều này giảm thiểu nguy cơ có một lỗi trong mã của bạn làm cho toà

Việc áp dụng mô hình lập trình song song không có nghĩa là đặt mọi thứ vào nhiều luồng. Ví dụ, Raycasting Validation bên máy chủ cho mỗi người dùng từng cá nhân một sự kiện truyền tảng từ xa nhưng vẫn yêu cầu mã khởi đầu được thi hành song song để thay đổi c

Hầu hết thời gian bạn cần phải kết hợp các giai đoạn seri và paralel để đạt được kết quả mà bạn muốn, vì hiện tại có một số hoạt động không được hỗ trợ trên paralel mà có thể ngăn chặn việc thi hành các script, chẳng hạn như thay đổi các inst

Chia mã thành nhiều luồng

Để chạy các tập lệnh trong trải nghiệm của bạn trên nhiều luồng một lúc, bạn cần phải chia chúng thành các khối logic dưới các nhà diễn xuất khác nhau trong mô hình dữ liệu . Actor được di

Đặt Actor Instances

Bạn có thể đặt các diễn viên vào các container phù hợp hoặc sử dụng chúng để thay thế các loại instanti- top cấp của entities 3D của bạn như NPCs và raycasters, sau đó thêm các script tương ứng.

An example of a Script under an Actor

Đối với hầu hết các tình huống, bạn không nên đặt một người chơi là con của một người chơi khác trong mô hình dữ liệu. Tuy nhiên, nếu bạn quyết định đặt một script được ghép nhúc trong nhiều người chơi cho mục đích sử dụng cụ thể của bạn, script đó thuộc sở hữu của người chơ

A tree of actors and scripts that shows how a script is owned by its closest actor

Đồng bộ hóa những hilo

Mặc dù đặt các script dưới các nhân vật cho họ khả năng thi hành song song, mặc định mã vẫn chạy trên một luồng chính xác, điều này không cải thiện hiệu lựcsuất thời gian thực. Bạn cầ

Alternatively, you can use RBXScriptSignal:ConnectParallel() method when you want to schedule a signal callback to immediately run your code in parallel upon triggering. You don't need to call task.desynchronize() inside the signal callback.

Huỷ đồng bộ hóa một Thread

local RunService = game:GetService("RunService")
RunService.Heartbeat:ConnectParallel(function()
... -- Một số mã paralel tính toán một cập nhật trạng thái
task.synchronize()
... -- Một số mã seri thay đổi trạng thái của các instace
end)

Các kịch bản này luôn được thi hành theo thứ tự với nhau, vì vậy bạn cần nhiều kịch bản. Ví dụ, nếu bạn đặt tất cả các kịch bản kích hoạt paralel cho NPC của bạn trong một kịch bản, chúng vẫn được thi

Mã paralell trong Actor chạy song song trong một màn hình duy nhất
Mã paralell trong Actor chạy song song trên nhiều luồng

An toàn luồng

Trong khi thi hành song song, bạn có thể truy cập hầu hết các mục từ DataModel hiệp đấu như thường lệ, nhưng một số API properties và functions không an toàn để đọc hoặc viết. Nếu bạn sử dụng chúng trong mã paralel của bạn, động cơ Roblox có thể tự động phát hiện và ngăn chặn cá

Các thành viên API có một lớp an toàn chuỗi cho phép bạn biết có thể sử dụng chúng trong mã paralel của bạn, như bảng sau đề cập:

Cấp độ an toànĐối với Thuộc tínhĐối với chức năng
Không an toàn Không thể đọc hoặc viết song song.Không thể gọi trong paralel.
Đọc song song Có thể đọc nhưng không thể viết song song.Chưa có
Safe địa phương Có thể được sử dụng trong cùng một Actor; có thể được đọc nhưng không thể viết bởi một Class.Actor|Actors khác đồng thời.Có thể gọi trong cùng một Actor; không thể gọi bởi các Actors khác nhau trong cùng một lúc.
Safe Có thể đọc và viết.Có thể gọi.

Bạn có thể tìm thấy các thẻ an toàn chủ đề trên API reference . Khi sử dụng chúng, bạn cũng nên xem xét làm thế nào các gọi API hoặc thay đổi tính tùy chỉnh của API có thể tương tác giữa các luồng chủ đề paralel. Thông thường, nó là an toàn cho nhiều người chơi đọc cùng một

Giao tiếp Cross-Thread

Trong context multithreading, bạn vẫn có thể cho phép các script ở các nhà sản xuất khác nhau để trao đổi dữ liệu, phối hợp nhiệm vụ và xử lý hoạt động. Engine hỗ trợ các mécanism sau đây cho trao đổi giữa các sub-Thread:

Bạn có thể hỗ trợ nhiều cơ chế để đáp ứng các nhu cầu giao tiếp giữa các luồng dữ liệu của bạn. Ví dụ, bạn có thể gửi một bảng tổng quát qua Actor Messaging API.

Tin nhắn Actor

API Gửi Tin Nhắn Actor cho phép một script, either in a serial or parallel context, gửi dữ liệu đến một actor trong cùng một mô hình dữ liệu. Việc giao tiếp thông qua API này là asynchronous, trong đó người gửi không khối cho đến khi nhận tin nhắn.

Khi gửi thông điệp bằng cách sử dụng API này, bạn cần phải định nghĩa một chủ đề cho danh mục thông tin nhắn. Mỗi thông điệp chỉ có thể được gửi đến một người chơi, nhưng người chơi đó có thể nội tại có nhiều hồi kết được kết nối với mộ

API có các phương thức sau đây:

  • Actor:SendMessage() để gửi một thông điệp cho một nhà diễn.
  • Actor:BindToMessage() để kết nối một hồ sơ call Luau với một thông điệp có chủ đề được quy định trong một context seri.
  • Actor:BindToMessageParallel() để kết nối một hồ sơ trò chuyển Luau với một thông điệp có chủ đề được quy định trong một bối cảnh paralell.

Ví dụ sau đây cho thấy cách sử dụng Actor:SendMessage() để xác định một chủ đề và gửi một thông điệp đến kết thúchẹn của người gửi:

Người gửi thông điệp ví dụ

-- Gửi hai thông điệp cho nhân viên làm việc với chủ đề "Xin chào"
local workerActor = workspace.WorkerActor
workerActor:SendMessage("Greeting", "Hello World!")
workerActor:SendMessage("Greeting", "Welcome")
print("Sent messages")

Ví dụ sau đây cho thấy cách sử dụng Actor:BindToMessageParallel() để liên kết một hàm để gọi cho một chủ đề nhất định trong một ngữ cảnh paralel trên máy chủ:

Thiết Bị Phát Tin Nhắn Ví Dụ

-- Nhận nhà tài trợ của bố mẹ này tập trung
local actor = script:GetActor()
-- Lập một hành động gọi để đăng nhập "Xin chào"
actor:BindToMessageParallel("Greeting", function(greetingString)
print(actor.Name, "-", greetingString)
end)
print("Bound to messages")

Bảng chia sẻ

SharedTable là một cấu trúc dữ liệu giống như một bảng truy cập từ các script chạy dưới nhiều người chơi. Nó hữu ích cho các tình huống liên quan đến một lượng dữ liệu lớn và yêu cầu một trạng thái chung trong nhiều luồng. Ví dụ, khi nhiều người ch

Gửi một bảng dữ liệu chia sẻ đến một nhà khác không tạo ra bản sao của dữ liệu. Thay vào đó, các bảng dữ liệu chia sẻ cho phép các cập nhật an toàn và nguyên tử bởi nhiều script cùng một lúc. Mỗi lần cập nhật một bảng dữ liệu chia s��

Giao tiếp trực tiếp bản mô hình dữ liệu

Bạn cũng có thể dễ dàng thúc đẩy giao tiếp giữa các luồng dữ liệu bằng cách sử dụng mô hình dữ liệu, trong đó các nhà sản xuất khác nhau có thể viết và sau đó đọc các tính chất hoặc đặribut. Tuy nhiên, để duy trì an toàn của thread, các tập lệ

Ví dụ

Xác minh Raycasting bên máy chủ

Đối với một trải nghiệm chiến đấu và trận chiến, bạn cần phải bật raycasting cho vũ khí của người dùng của bạn. Với khách hàng simulate vũ khí để đạt được tốc độ nhanh tốt, máy chủ phải xác nhận trúng, cech động này bao gồm thực hi

Thay vì sử dụng một mã nguồn trung tâm đơn giản để kết nối với một sự kiện xa cục bằng cách kết nối với một đối tượng người dùng có một sự kiện xa cục riêng, bạn có thể thiết lập mỗi quá trình xác minh hit để được thiết lập trên bên máy chủ một cách tương tự với mọi nhân vật người d

Script phe máy chủ chạy dưới Class.Actor của nhân vật đó kết nối với sự kiện trực tiếp này bằng một kết nối paralel để chạy logica liên quan đến việc xác nhận hit. Nếu logica tìm thấy một hồ sơ xác nhận hit, sát thương được trừ, cech đó liên quan đến việ


local tool = script.Parent.Parent
local remoteEvent = Instance.new("RemoteEvent") -- Tạo một sự kiệnRemote mới và đặt nó làm cha của công cụ
remoteEvent.Name = "RemoteMouseEvent" -- Đổi tên nó để có thể tìm kiếm nó
remoteEvent.Parent = tool
local remoteEventConnection -- Tạo một tham chiếu cho kết nối sự kiện xa
-- Chức năng lắng nghe một sự kiện xa cơ xe
local function onRemoteMouseEvent(player: Player, clickLocation: CFrame)
-- SERIAL: Thiết lập mã thiết lập trong serial
local character = player.Character
-- Làm lơ nhân vật của người dùng trong khi phát sóng
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = { character }
-- ĐIỀU TƯƠNG TÁC: Thực hiện raycast song song
task.desynchronize()
local origin = tool.Handle.CFrame.Position
local epsilon = 0.01 -- Được sử dụng để mở rộng các ray một chút khi vị trí nhấp chuột có thể bị một chút lệch so với thể
local lookDirection = (1 + epsilon) * (clickLocation.Position - origin)
local raycastResult = workspace:Raycast(origin, lookDirection, params)
if raycastResult then
local hitPart = raycastResult.Instance
if hitPart and hitPart.Name == "block" then
local explosion = Instance.new("Explosion")
-- SERIAL: Mã bên dưới điều chỉnh trạng thái ngoài của nhà diễn viên
task.synchronize()
explosion.DestroyJointRadiusPercent = 0 -- Làm cho vụ nổ không chết
explosion.Position = clickLocation.Position
-- Nhiều nhà diễn xuất có thể nhận được cùng một phần trong một raycast và quyết định tiêu diệt nó
-- Điều này hoàn toàn an toàn nhưng sẽ dẫn đến hai vụ nổ cùng một lúc thay vì một
-- Các hành động sau đây kiểm tra xem có phải lần đầu tiên nó đến vào phần này không
if hitPart.Parent then
explosion.Parent = workspace
hitPart:Destroy() -- Phá hủy nó
end
end
end
end
-- Kết nối tín hiệu trong seri ban đầu vì một số mã cài đặt không thể chạy song song
remoteEventConnection = remoteEvent.OnServerEvent:Connect(onRemoteMouseEvent)

Server-Side Thủ tục địa hình

Để tạo ra một thế giới rộng lớn cho trải nghiệm của bạn, bạn có thể lấp đầy thế giới bằng cách thuật toán. Thông thường, thế giới tạo thủ tục thường tạo các khối địa hình độc lập, với máy chủ thực hiện các tính toán phức tạp cho địa hình đối tượ


-- Thi hành song song yêu cầu sử dụng các diễn viên
-- Cuộn dịch này tự clones; người ban đầu khởi xướng quá trình, trong khi clones làm việc như những người lao động
local actor = script:GetActor()
if actor == nil then
local workers = {}
for i = 1, 32 do
local actor = Instance.new("Actor")
script:Clone().Parent = actor
table.insert(workers, actor)
end
-- Phụ huynh tất cả các nhân vật dưới self
for _, actor in workers do
actor.Parent = script
end
-- Hướng dẫn các nhà diễn xuất tạo mô hình địa hình bằng cách gửi tin nhắn
-- Trong ví dụ này, các diễn viên được chọn ngẫu nhiên
task.defer(function()
local rand = Random.new()
local seed = rand:NextNumber()
local sz = 10
for x = -sz, sz do
for y = -sz, sz do
for z = -sz, sz do
workers[rand:NextInteger(1, #workers)]:SendMessage("GenerateChunk", x, y, z, seed)
end
end
end
end)
-- Thoát khỏi mã nguyên bản; phần còn lại của mã chạy trong mỗi nhà diễn
return
end
function makeNdArray(numDim, size, elemValue)
if numDim == 0 then
return elemValue
end
local result = {}
for i = 1, size do
result[i] = makeNdArray(numDim - 1, size, elemValue)
end
return result
end
function generateVoxelsWithSeed(xd, yd, zd, seed)
local matEnums = {Enum.Material.CrackedLava, Enum.Material.Basalt, Enum.Material.Asphalt}
local materials = makeNdArray(3, 4, Enum.Material.CrackedLava)
local occupancy = makeNdArray(3, 4, 1)
local rand = Random.new()
for x = 0, 3 do
for y = 0, 3 do
for z = 0, 3 do
occupancy[x + 1][y + 1][z + 1] = math.noise(xd + 0.25 * x, yd + 0.25 * y, zd + 0.25 * z)
materials[x + 1][y + 1][z + 1] = matEnums[rand:NextInteger(1, #matEnums)]
end
end
end
return {materials = materials, occupancy = occupancy}
end
-- Kết nối gọi lại để được gọi trong ngữ cảnh thi hành song song
actor:BindToMessageParallel("GenerateChunk", function(x, y, z, seed)
local voxels = generateVoxelsWithSeed(x, y, z, seed)
local corner = Vector3.new(x * 16, y * 16, z * 16)
-- Hiện tại, WriteVoxels() phải được gọi trong giai đoạn serial
task.synchronize()
workspace.Terrain:WriteVoxels(
Region3.new(corner, corner + Vector3.new(16, 16, 16)),
4,
voxels.materials,
voxels.occupancy
)
end)

Tốt nhất

Để áp dụng các lợi ích tối đa của công nghệ lập trình song song, hãy tham khảo những lưu ý tốt nhất sau đây khi thêm mã Lua của bạn:

  • Tránh các biểu tượng dài — Ngay cả trong paralel, các biểu tượng dài có thể chặn sự thi hành của các script khác và gây lag. Tránh sử dụng paralel programming để xử lý một lượng lớn các biểu tượng dài, không bị đánh giá cao.

    Diagram demonstrating how overloading the parallel execution phase can still cause lag
  • Sử dụng số lượng người chơi phù hợp — Đối với hiệu lựcsuất tốt nhất, hãy sử dụng nhiều hơn Actors . Ngay cả khi thiết bị có ít hơn Actors , granularity cho phép bố trí cân bằng tải điều khiển hơn giữa các

    Demonstration of how using more actors balances the load across cores

    Điều này không có nghĩ