Hello, I’ve been programming RTS style movement system, but I am struggling how I would solve the ‘destination problem’, where group of units are all told to go to one position but end up ‘fighting’ each other to achieve the target position.
I have implemented a system previously where it takes the mid-point position of all the units selected and then calculate the distance of each unit to that mid-point, and then apply those distances as offsets to the end position. This work great except when there is a unit far away from the main group, it will stay far away from the end position.
To solve this, I could just tell the units to make a circle around the end position, but then the units will end up fighting to get to their assigned end positions, unless I turned canCollide off, but decided not to turn it off as it would not look good.
As of now I’m stuck on where to go from here. I could go back to the original mid-point distance offset system; I also was looking at implementing a Boids algorithm possibly but have no idea how going about implementing this.
If anyone has any idea who to go about solving this shared destination problem, it would be very helpful.
The following code is my unit movement function, which only tells the units to go the same endPosition where they will fight for in order to end their loops, there are no formations or anything to tell the groups to organize into something.
local MoveInstanceClass = {}
--Services
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local selectedUnits = 0
function MoveInstanceClass.moveToPosition(player, targetPos, selectedUnit)
for _, team in pairs(workspace.Teams:GetChildren()) do
if team.Name == player.Team.Name then
--Check if multiple Units are Selected
selectedUnits = 0
for _, unit in pairs(team.Units:GetChildren()) do
if unit:GetAttribute("selected") == true then
selectedUnits = selectedUnits + 1
if selectedUnits > 1 then
break
end
end
end
--Check if unit is selected, then assign properties
if selectedUnit:GetAttribute("selected") == true then
selectedUnit:SetAttribute("targetPoint", targetPos)
selectedUnit:SetAttribute("repeating", true)
selectedUnit.CollisionBox.AlignOrientation.CFrame = CFrame.lookAt(selectedUnit.PrimaryPart.Position, Vector3.new(selectedUnit:GetAttribute("targetPoint").X, selectedUnit.PrimaryPart.Position.Y, selectedUnit:GetAttribute("targetPoint").Z))
for _, wayPoint in pairs(selectedUnit.ObjectValues.wayPoints:GetChildren()) do
wayPoint:Destroy()
end
local wayPointPart = Instance.new("Part")
wayPointPart.Anchored = true
wayPointPart.Size = Vector3.new(1, 1, 1)
wayPointPart.CanCollide = false
wayPointPart.Transparency = .8
wayPointPart.Position = selectedUnit:GetAttribute("targetPoint")
wayPointPart.Parent = selectedUnit.ObjectValues.wayPoints
local attachment2 = Instance.new("Attachment")
attachment2.Parent = wayPointPart
attachment2.WorldCFrame = wayPointPart.CFrame
end
--Begin Unit Movmement Loop
local loop = true
if selectedUnits > 1 then
print("Multiple Units")
else
print("Single Unit")
while loop do
local allUnitsReachedTarget = true
for _, repeatingUnit in pairs(team.Units:GetChildren()) do
if repeatingUnit:GetAttribute("repeating") then
repeatingUnit.CollisionBox.UnitVelocity.PlaneVelocity = Vector2.new(repeatingUnit:GetAttribute("targetPoint").X - repeatingUnit.PrimaryPart.Position.X, repeatingUnit:GetAttribute("targetPoint").Z - repeatingUnit.PrimaryPart.Position.Z).Unit * 5
if (Vector3.new(repeatingUnit.PrimaryPart.Position.X, 0, repeatingUnit.PrimaryPart.Position.Z) - Vector3.new(repeatingUnit:GetAttribute("targetPoint").X, 0, repeatingUnit:GetAttribute("targetPoint").Z)).Magnitude > 1 then
allUnitsReachedTarget = false
repeatingUnit:SetAttribute("repeating", true)
else
repeatingUnit:SetAttribute("repeating", false)
repeatingUnit.CollisionBox.UnitVelocity.PlaneVelocity = Vector2.new(0, 0)
end
end
end
if allUnitsReachedTarget then
loop = false
end
task.wait()
end
end
end
end
end
return MoveInstanceClass
Ignoring if multiple units selected, this is what it would look like if the while loop to move the units are applied to all the units selected.