I am attempting to make a movement system for various units in a RTS game. I’ve figure out how to use the pathfinding service, so that shouldn’t be a problem, however when I make more than one unit move to a spot, they inevitably end up pushing the units that arrive there first.
So to solve that, I am trying to figure out how to get a number of points (equal to the current number of units selected) near where the mouse clicked, with a given number of studs separation between them all. For example, 7 points might look like this: https://i.gyazo.com/a8746b5521eac969c9e1bffc326d8fa5.png
6 points like this: https://i.gyazo.com/17df4486d684761b81c507ff7c05fc8e.png
and so on. To complicate matters further, I also need to take into account obstacles, such as walls or buildings, which means it would need to result in something like this 7 points example: https://i.gyazo.com/95f30412cea70cab7659375391762cb9.png
(blue is the position clicked, red are invalid points, green are corrected points)
Only problem is, I have no clue how I would even start doing something like this. Any help, ideas, or tips would be greatly appreciated.
So… what have you tried so far?
As I said in the main post, I don’t know where I would even start.
You could probably use some sort of iterative spiral algorithm to figure out where to place units, and if the position is inside a part or just invalid in general, we can mark out that position and use the next one on the spiral instead.
Given a base equation r = θ
, we could plot points on the equation to give positions in a circular pattern, although not equidistant. So, something like this I guess:
local function generateUnitPosition(theta, size)
local spiralDistance = size * theta / (2 * math.pi)
return spiralDistance * Vector3.new(
math.cos(theta),
0,
math.sin(theta)
)
end
Using a simple linear for loop will cause points to be further away as your theta gets larger, however. I googled how to find equidistant points on a spiral, and I found a question about it on stack overflow: algorithm - Draw equidistant points on a spiral - Stack Overflow
The question says the input is the width of the loop, distance between points, and number of points, which is perfect for what you need. Good luck I guess.
Sorry for replying to you T0ny, it was an accident!
Ah, spirals. I hadn’t thought of that. Thanks a lot!
PathFinding also has ComputeAsynch and GetWayPoints which may be of help.
Alright, I looked at the python version, since that’s the easiest one to read, but I’m stuck at the “yield” part. Lua doesn’t have “yield”, or an equivalent, and I’m unsure how it works.Do you have any ideas?
Coroutines have similar behavior to this:
local co = coroutine.create(function(arc, separation)
--[[
generate points on an Archimedes' spiral
with `arc` giving the length of arc between two points
and `separation` giving the distance between consecutive
turnings
- approximate arc length with circle arc at given distance
- use a spiral equation r = b * phi
--]]
local arc = arc or 1
local separation = separation or 1
local function p2c(r, phi)
--polar to cartesian
return r * Vector3.new(math.cos(phi), 0, math.sin(phi))
end
coroutine.yield(Vector3.new())
local r = arc
local b = separation/(2*math.pi)
local phi = r/b
while true do
coroutine.yield(p2c(r, phi))
phi = phi + arc/r
r = b*phi
end
end)
while true do
local success, newPosition = coroutine.resume(co --[[, arc, separation]])
print(newPosition)
wait(1)
end
I read up on what yield
does real quick, and it basically makes a function return a value when it is called, but continue running after yield
when it is called again. Coroutines have this exact same behavior when using coroutine.resume
and coroutine.yield
.
That makes a lot of sense, and is kind of neat. I didn’t know there was such a thing as yield. It works quite well too. I think it’s exactly what I need. thanks for the help!
Nature has solved this problem with the use of a magical constant called Phi. Also called the Golden ratio. It is the most irrational number and used to make nicely spaced spiral like patterns of points. There is a good Roblox place that illustrates this that I’ll link below.