Ive been working on this script for about a week now. I'm trying to create a custom particle system that can do way more then the default particle effect.
local RunService = game:GetService("RunService")
local sigma = 10
local rho = 28
local beta = 8/3
function GenerateVectorField(style, scaleX, scaleY, scaleZ)
local magnitudetable = {}
for i=1, scaleX do
for j=1, scaleY do
for k=1, scaleZ do
local x = (scaleX/2)*(-1)+i
local y = (scaleY/2)*(-1)+j
local z = (scaleZ/2)*(-1)+k
if (Vector3.new(x, y, z) - Vector3.new(0, 0, 0)).Magnitude > 0 then
table.insert(magnitudetable, i, (Vector3.new(x, y, z) - Vector3.new(0, 0, 0)).Magnitude)
end
end
end
end
local scale = math.max(unpack(magnitudetable))
local VectorField = {}
if style == 0 then -- f(x,y,z) = [x,y,z]
for i=1, scaleX do
for j=1, scaleY do
for k=1, scaleZ do
local x = (scaleX/2)*(-1)+i
local y = (scaleY/2)*(-1)+j
local z = (scaleZ/2)*(-1)+k
local Vector = CFrame.new(Vector3.new(x, y, z)) * CFrame.fromAxisAngle(Vector3.new(x, y, z), 1)
table.insert(VectorField, i, Vector)
end
end
end
end
if style == 1 then
for i=1, scaleX do
for j=1, scaleY do
for k=1, scaleZ do
local x = (scaleX/2)*(-1)+i
local y = (scaleY/2)*(-1)+j
local z = (scaleZ/2)*(-1)+k
local Vector = CFrame.new(Vector3.new(x, y, z)) * CFrame.fromAxisAngle(Vector3.new(y * z, x * z, x * y), 1)
table.insert(VectorField, i, Vector)
end
end
end
end
if style == 2 then -- f(x,y,z) = [sin(x),sin(y),sin(z)]
for i=1, scaleX do
for j=1, scaleY do
for k=1, scaleZ do
local x = (scaleX/2)*(-1)+i
local y = (scaleY/2)*(-1)+j
local z = (scaleZ/2)*(-1)+k
local Vector = CFrame.new(Vector3.new(x, y, z)) * CFrame.fromAxisAngle(Vector3.new(math.sign(x), math.sign(y), math.sign(z)), 1)
table.insert(VectorField, i, Vector)
end
end
end
end
if style == 3 then -- f(x,y,z) = [sigma * (y - x), rho * x - y - x * z, x * y - beta * z]
for i=1, scaleX do
for j=1, scaleY do
for k=1, scaleZ do
local x = (scaleX/2)*(-1)+i
local y = (scaleY/2)*(-1)+j
local z = (scaleZ/2)*(-1)+k
local Vector = CFrame.new(Vector3.new(x, y, z)) * CFrame.fromAxisAngle(Vector3.new(sigma * (y - x), rho * x - y - x * z, x * y - beta * z) * (-1), 1)
table.insert(VectorField, i, Vector)
end
end
end
end
return VectorField, scale
end
local VectorField, scale = GenerateVectorField(1, 10, 10, 10)
for i=1,#VectorField do
local part = Instance.new("Part", workspace.Vectors)
local vector = Instance.new("Vector3Value", part)
part.Size = Vector3.new(1,1,1)
part.CFrame = VectorField[i]
vector.Value = part.Orientation
part.Orientation = Vector3.new(0, 0, 0)
part.Anchored = true
part.Transparency = 1
part.CanCollide = false
if true then
local part = Instance.new("Part", workspace.Visuals)
local vector = Instance.new("VectorForce", part)
part.Size = Vector3.new(0.05,0.05,0.05)
part.CFrame = VectorField[i]
-- vector.Force = part.Orientation
-- vector.Visible = true
-- vector.Enabled = true
-- part.Orientation = Vector3.new(0,0,0)
part.Anchored = true
part.Transparency = 1
part.CanCollide = false
local Cone = script.ConeHandleAdornment:Clone()
Cone.Parent = part
Cone.Adornee = part
-- Cone.Color3 = Color3.fromHSV((part.Position - Vector3.new(0, 0, 0)).Magnitude / scale, 1, 1)
Cone.Height = (part.Position - Vector3.new(0, 0, 0)).Magnitude / scale
local Cylinder = script.CylinderHandleAdornment:Clone()
Cylinder.Parent = part
Cylinder.Adornee = part
-- Cylinder.Color3 = Color3.fromHSV((part.Position - Vector3.new(0, 0, 0)).Magnitude / scale, 1, 1)
Cylinder.Height = (part.Position - Vector3.new(0, 0, 0)).Magnitude / scale
end
end
RunService.Heartbeat:Connect(function()
for i=1,1 do
local part = script.Part:Clone()
part.Parent = workspace.Particles
part.Velocity = Vector3.new(math.random(-10,10)/10,math.random(-10,10)/10,math.random(-10,10)/10)
end
end)
Basically what this does is make an array of vectors (function GenerateVectorField), then construct them into a vector field. And spawn particles to simulate on the vector field. The only real important stuff is on lines 28 - 32, 42 - 46, 56 - 60, 70 - 74 and 85 - 115.
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function()
local particles = workspace.Particles:GetChildren()
local ignore = workspace.Vectors:GetChildren()
for i=1,#particles do
local currentvector = workspace:FindPartsInRegion3WithWhiteList(Region3.new(particles[i].Position - (0.5 * particles[i].Size), particles[i].Position + (0.5 * particles[i].Size)), ignore)
for j=1,#currentvector do
local goal = {}
goal.Velocity = (currentvector[j].Value.Value / 10)
local tweenInfo = TweenInfo.new(1)
local tween = TweenService:Create(particles[i], tweenInfo, goal)
tween:Play()
end
if (particles[i].Position - Vector3.new(0,0,0)).Magnitude > 10 then
particles[i]:Destroy()
end
end
end)
Basically what this does is find a vector that is in range of a particle and set the velocity of the particle to the vector.
I'm not sure if the vectors are not displaying properly or my coding is just incorrect.
Ive tried HandleAdornments and setting the orientation to show the vectors but they don't even seem to point in the correct direction according to other simulations (Ex. f(x,y,z) = [x,y,z]) or even the way particles move when they intersect (Ex. f(x,y,z) = [sigma * (y - x), rho * x - y - x * z, x * y - beta * z]). I've tried visible VectorForces, which works exactly as I need, but they don't show up ingame so they are completely useless. I've tried hundreds of things but none of them work.
But on the other hand this is my first time really getting deep into Roblox vectors and with vector fields. So the code could be wrong.
TLDR: Script is showing vectors incorrectly, is my math wrong or is it adornments to blame? And for ether how could I fix it?
I played around with the code a little and discovered I needed to multiply by pi, that fixed the direction of the vectors.
