Alright, so I’ve been working on this battle simulation lately, and have been scouting out for ways to improve the performance. One thing I came across that could majorly benefit me is roblox’s new parallel computing usage. Only problem is, I DON’T KNOW WHERE TO APPLY IT!
Now, I’m not a math genius or a logistical genius by any means, but I try my best to figure this stuff out. I researched how parallel computing worked, and I only kind of understood it. There are so many tutorials telling you how it works, but they never tell you how to apply it.
If anyone could just look at this short script I have and try and help me pinpoint spots where I could implement this, it would be incredibly appreciated!
PS: I don’t want it to seem like I’m just dumping code and asking for someone to fix it. You don’t have to look at all or any of this code if you don’t want to. I just dropped it here for anyone who wants to see how I could use it. If you don’t want to read all of it I totally understand that, and you could just help me figure out how the hell to do this
-- MAIN SCRIPT (MANIPULATOR)
local RunService = game:GetService("RunService")
local DOS = require(game.ReplicatedStorage.DynamicOctreeSystem)
local Debris = game:GetService("Debris")
local MainModule = require(game.ReplicatedStorage.CharacterHandoffFunctions)
local DosGrid = DOS.New("Name", 4, 400);
local NUM_NPCS = 400
local Teams = {
["Team1"] = {},
["Team2"] = {},
}
RunService.Heartbeat:Connect(function(DT)
for Team,NPCs in pairs(Teams) do
for NPC,Attributes in pairs(NPCs) do
if Attributes["Target"] then
local MoveVector = MainModule.MoveTo(Teams,DT,NPC,Attributes)
--NPC.Humanoid:Move(MoveVector)
--NPC.Humanoid.WalkSpeed = Attributes["Velocity"]
if (NPC.PrimaryPart.Position - Attributes["Target"].PrimaryPart.Position).Magnitude < 5 then
MainModule.Attack(DT,Teams,NPC,Attributes["Target"])
end
end
end
end
end)
for i = 1,NUM_NPCS do
local NPC1 = MainModule.AddNPC(Teams,"Team1",Vector3.new(math.random(-400,400),2,math.random(-400,400)) + Vector3.new(500,0,-500))
local NPC2 = MainModule.AddNPC(Teams,"Team2",Vector3.new(math.random(-400,400),2,math.random(-400,400)) + Vector3.new(500,0,500))
Teams["Team1"][NPC1] = {
["GoalPos"] = nil,
["Direction"] = Vector3.new(0,0,0),
["Target"] = nil,
["Position"] = Vector3.new(0,0,0),
["Instance"] = NPC1,
["MaxVelocity"] = 15,
["Velocity"] = 15,
["StrafeDirection"] = "Left",
}
Teams["Team2"][NPC2] = {
["GoalPos"] = nil,
["Direction"] = Vector3.new(0,0,0),
["Target"] = nil,
["Position"] = Vector3.new(0,0,0),
["Instance"] = NPC1,
["MaxVelocity"] = 15,
["Velocity"] = 15,
["StrafeDirection"] = "Left",
}
end
local WaitIndex = 0
local MaxIndex = NUM_NPCS/5
while task.wait() do
for Team,NPCs in pairs(Teams) do
for NPC,Attributes in pairs(NPCs) do
local Closest = MainModule.FindClosest(Teams,NPC,Attributes)
Teams[Team][NPC]["Target"] = Closest
WaitIndex += 1
if WaitIndex >= MaxIndex then
WaitIndex = 0
task.wait()
end
end
end
end
-- Module script (function handler)
local Module = {}
local DOS = require(game.ReplicatedStorage.DynamicOctreeSystem)
local DosGrid = DOS.New("Name", 4, 400);
local Debris = game:GetService("Debris")
Module.FindClosest = function(Teams,Unit,Attributes)
task.desynchronize()
local TargetTeam = nil
if Unit.Team.Value == "Team1" then
TargetTeam = "Team2"
else
TargetTeam = "Team1"
end
local PotentialTargets = {}
local Close = DosGrid.Tree:RadiusSearch(Unit.PrimaryPart.Position,15)
for _, Object in pairs(Close) do
if Object.Parent ~= Unit and Object.Name == "HumanoidRootPart" then
if Object.Parent.Team.Value ~= Unit.Team.Value then
table.insert(PotentialTargets,Object.Parent)
end
end
end
local ClosestTarget = nil
local MinDistance = math.huge
local MaxSearch = 50
local Search = 1
if #PotentialTargets == 0 then
PotentialTargets = Teams[TargetTeam]
for Target, Attributes in pairs(PotentialTargets) do
local RcSkip = math.random(1,2)
if RcSkip ~= 1 then continue end
local Distance = (Unit.PrimaryPart.Position - Target.PrimaryPart.Position).Magnitude
if Distance < MinDistance then
MinDistance = Distance
ClosestTarget = Target
end
Search += 1
if Search >= MaxSearch then
break
end
end
else
for _, Target in pairs(PotentialTargets) do
local Distance = (Unit.PrimaryPart.Position - Target.PrimaryPart.Position).Magnitude
if Distance < MinDistance then
MinDistance = Distance
ClosestTarget = Target
end
end
end
task.synchronize()
return ClosestTarget, MinDistance
end
function CheckDeath(Teams,Unit)
if Unit.HP.Value <= 0 then
Teams[Unit.Team.Value][Unit] = nil
Unit:PivotTo(CFrame.new(0,1000,0))
Debris:AddItem(Unit,1)
end
end
Module.Attack = function(DT,Teams,Unit,Target)
local RandomChance = math.random(1,1000 * DT)
if RandomChance == 1 then
Target.HP.Value -= math.random(10,30)
CheckDeath(Teams,Unit)
Target.Head.Color = Color3.fromRGB(255,255,255)
delay(.1,function()
if Target then
if Target.Team.Value == "Team1" then
Target.Head.Color = Color3.fromRGB(255,0,0)
else
Target.Head.Color = Color3.fromRGB(0,0,255)
end
end
end)
end
end
function IsBetween(FriendlyA, FriendlyB, Target)
-- Default to 10 degrees if no angleThreshold is provided
local angleThreshold = 5
local v1 = (FriendlyB - FriendlyA).Unit
local v2 = (Target - FriendlyA).Unit
local dotProduct = v1:Dot(v2)
-- Calculate cosine of the angleThreshold
local cosThreshold = math.cos(math.rad(angleThreshold))
if dotProduct > cosThreshold and v1.Magnitude <= v2.Magnitude then
return true
else
return false
end
end
Module.MoveTo = function(Teams,DT,NPC,Attributes)
local FriendlyInBetween = false
local TargetPos = Attributes["Target"].PrimaryPart.Position
local NPCPos = NPC.PrimaryPart.Position
local Dist = (NPC.PrimaryPart.Position - TargetPos).Magnitude
-- Avoidance
local Close = DosGrid.Tree:RadiusSearch(NPCPos,15)
local goalDirection = (TargetPos - NPCPos).Unit
for _, closeNPC in ipairs(Close) do
if closeNPC.Name == "HumanoidRootPart" and closeNPC.Parent ~= NPC then
if closeNPC.Parent.Team.Value ~= NPC.Team.Value then
continue
end
local avoidDistance = (NPCPos - closeNPC.Position).Magnitude
local avoidDirection = (NPCPos - closeNPC.Position).Unit
avoidDirection = Vector3.new(avoidDirection.X,0,avoidDirection.Z)
goalDirection += avoidDirection * (1/avoidDistance) * 2
if IsBetween(NPCPos, closeNPC.Position, TargetPos) and (NPC.Team.Value == closeNPC.Parent.Team.Value) then
FriendlyInBetween = true
end
end
end
goalDirection = goalDirection.Unit
-- Strafing
if (NPCPos - TargetPos).Magnitude < 5 then
local perpDirection = nil
if Attributes["StrafeDirection"] == "Left" then
goalDirection = Vector3.new(0, 1, 0):Cross(goalDirection)
else
goalDirection = Vector3.new(0, -1, 0):Cross(goalDirection)
end
local StrafeChange = math.random(1,10)
if StrafeChange == 1 then
if Attributes["StrafeDirection"] == "Left" then
Attributes["StrafeDirection"] = "Right"
else
Attributes["StrafeDirection"] = "Left"
end
end
end
local MoveVector = (Vector3.new(goalDirection.X,0,goalDirection.Z) * DT * 321321)
-- Speed
if Dist > 40 then
if Attributes["Velocity"] < Attributes["MaxVelocity"] then
Teams[NPC.Team.Value][NPC]["Velocity"] += 2.5 * DT
end
elseif Dist > 20 then
if Attributes["Velocity"] < Attributes["MaxVelocity"] then
Teams[NPC.Team.Value][NPC]["Velocity"] += 1.5 * DT
end
end
if FriendlyInBetween == true and Attributes["Velocity"] > 5 then
Teams[NPC.Team.Value][NPC]["Velocity"] -= (Attributes["Velocity"]/12)
end
return MoveVector
--NPC.Humanoid:Move(Vector3.new(goalDirection.X,0,goalDirection.Z) * DT * 321321)
--NPC.Humanoid.WalkSpeed = Attributes["Velocity"]
end
Module.AddNPC = function(Teams,Team,Pos)
local NPC = game.ReplicatedStorage.CharacterNPC:Clone()
NPC.Parent = game.Workspace
NPC:PivotTo(CFrame.new(Pos))
Teams[Team][NPC] = {
["GoalPos"] = nil,
["Direction"] = Vector3.new(0,0,0),
["Target"] = nil,
["Position"] = Vector3.new(0,0,0),
["Instance"] = NPC,
["MaxVelocity"] = 15,
["Velocity"] = 15,
["StrafeDirection"] = "Left",
}
NPC.Team.Value = Team
DosGrid:Track(NPC.HumanoidRootPart, .25)
if NPC.Team.Value == "Team1" then
NPC.Head.Color = Color3.fromRGB(255,0,0)
else
NPC.Head.Color = Color3.fromRGB(0,0,255)
end
return NPC
end
return Module