I’ve been working on a hyperspace effect and came across this video recently:

I’m not confused on the warped mesh portion, but rather with the positioning of the origin of the initial trails. I could manually do this, but there has to be a way to procedurally generate this radial-like pattern, ie:

The actual ray segments, since they are trails, would not have to be extended/long (I’ll programmatically speed/slow the parts/attachments up during the transition phase).

I’ve been brainstorming for a few days now and am stumped. Would appreciate any assistance!

I think you could use code like this to generate a bunch of random points around a certain position.

local MAX_POINTS = 10
local RADIUS = 2
local POSITION = Vector3.new(0, 5, 0)
local function VisualizeVector3(Point: Vector3)
local Part = Instance.new("Part")
Part.Position = Point
Part.Size = Vector3.new(0.5, 0.5, 0.5)
Part.Anchored = true
Part.Parent = workspace
end
for i = 1, MAX_POINTS do
local RandomGen = Random.new()
local X = RandomGen:NextNumber(-RADIUS, RADIUS)
local Y = RandomGen:NextNumber(-RADIUS, RADIUS)
print(X)
print(Y)
local NewPosition = Vector3.new(X, Y).Unit * RADIUS + POSITION
VisualizeVector3(NewPosition)
end

Interesting, thanks for the tips. If you refer to the image however, you’ll notice that it is more of a cluster than a perfect circle with nodes, as yours does.

I added just a little extra variance so it still makes a rough circle:

function GenerateRoughCircle(Radius: number, Position: Vector3, NumPoints: number)
for i = 1, NumPoints do
local RandomGen = Random.new()
local X = RandomGen:NextNumber(-Radius, Radius)
local Y = RandomGen:NextNumber(-Radius, Radius)
local XVariance = RandomGen:NextNumber(-0.5, 0.5)
local YVariance = RandomGen:NextNumber(-0.5, 0.5)
local ExtraVariance = Vector3.new(XVariance, YVariance)
print(X)
print(Y)
local NewPosition = Vector3.new(X, Y).Unit * Radius + POSITION + ExtraVariance
VisualizeVector3(NewPosition)
end
end

You could probably just use a for loop kinda like:

for i = 1, NUM_LOOPS do
GenerateRoughCircles(i * 3, Center, i * 10)
end

As for the clipping problem, you could store all the previous positions in a table, and each time you generate a new position, check through the table to see if any of the positions are close to the new position. If so, generate a new position. This is probably a messy, laggy approach, but it is the only one I can think of.

Smaller radius would be further way, and have moving … tweened parts moving to a point at a higher radius value, closer to the camera.

Here’s what I use, as far as the function is concerned (not this gives you a top down circle with Y as 0… you might just need to swap out Z and Y or X of the Vector3 for your purposes.:

local function GetPointOnCircle(CircleRadius, Degrees)
return Vector3.new(math.cos(math.rad(Degrees)) * CircleRadius, 0, math.sin(math.rad(Degrees)) * CircleRadius)
end