How do I make the parts sucked into the tornado stop clumping?

  1. What do you want to achieve? Keep it simple and clear!
    Stop the parts from clumping, and make them be thrown more like this
    https://www.youtube.com/watch?v=fYestXaJmlA

  2. What is the issue? Include screenshots / videos if possible!
    the parts are clumping up
    Screenshot 2025-03-30 210619

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried using the original script/adapting it to fit the tornado/adapting the tornado to fit it, neither worked.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Here are the scripts:
Hazard -

local tor = script.Parent
local debounce = false
local attackrange = 1

local near = coroutine.resume(coroutine.create(function()
	while wait() do
		local region = Region3.new(
			Vector3.new(tor.Position.X - tor.Size.X/2 - attackrange, tor.Position.Y - tor.Size.Y/2 - attackrange, tor.Position.Z - tor.Size.Z/2 - attackrange),
	  		Vector3.new(tor.Position.X + tor.Size.X/2 + attackrange, tor.Position.Y + tor.Size.Y/2 + attackrange, tor.Position.Z + tor.Size.Z/2 + attackrange)
		)
		local parts = workspace:FindPartsInRegion3(region)
		for i,p in pairs(parts) do
			if p:IsA("BasePart") and p.CanCollide == true and p:GetMass() < 1000000 then
				if not p:FindFirstChild("TornadoSuckingForce") then
					-- enssential stuff
					local bp = Instance.new("BodyPosition")
					bp.Name = "TornadoSuckingForce"
					bp.MaxForce = Vector3.new(2000 * p:GetMass(), 2000 * p:GetMass(), 2000 * p:GetMass())
					bp.Parent = p
					-- this will let the parts handle itself, instead of a whole script handling everything to reduce lag
					local torvalue = Instance.new("ObjectValue")
					torvalue.Name = "WhichTornado"
					torvalue.Value = tor
					torvalue.Parent = p
					local scr = script.SuckingScript:Clone()
					scr.Parent = p
					scr.Disabled = false
					-- extra stuff
					local bav = Instance.new("BodyAngularVelocity")
					bav.Name = "SuckingRotation"
					bav.MaxTorque = Vector3.new(4000 * p:GetMass(), 4000 * p:GetMass(), 4000 * p:GetMass())
					bav.AngularVelocity = Vector3.new(math.random(1,25), math.random(1,25), math.random(1,25))
					bav.Parent = p
				end
			end
		end
	end
end))

--tor.Touched:connect(onTouched)

Sucking Script -

local sp = script.Parent
repeat
	wait()
until sp:FindFirstChild("WhichTornado")
local tor = sp:FindFirstChild("WhichTornado").Value
local bp = sp:FindFirstChild("TornadoSuckingForce")

sp.Anchored = false
sp:BreakJoints()
game.Debris:AddItem(sp, 25)
local height = 0
	repeat
		bp.Position = (CFrame.new(tor.Position - Vector3.new(0, tor.Size.Y/2, 0))*CFrame.Angles(0,math.pi*2*((tick()/5)%1),0)*CFrame.new(tor.Size.X/1 + height/75, height, 0)).p -- the x will make the parts get farther away from the tornado, and y will make it move up
		height = height + (tor.Size.Y/25*0.5) -- aka 2% of it's Y size
		wait()
	until height == tor.Size.Y -- a very large number but it might fit the looks
sp:Destroy()

P.S. Neither of the scripts are mine, rather free ones I searched tutorials and changed a bit, I’m an amateur at scripting, but I can usually read them pretty fine.

2 Likes

It looks like in the Sucking Script you’ve got line 13 bp.Position = which has a description at the end about how far the parts will be from the tornado according to the X value. The way the code reads is tor.Size.X/1. Try changing /1 to other values (I’d try .1 first) to see if that changes how far away they end up.

2 Likes

You could try introduce a body force to launch the parts when sucked.
Modification of the sucking script :

local sp = script.Parent
repeat
    wait()
until sp:FindFirstChild("WhichTornado")
local tor = sp:FindFirstChild("WhichTornado").Value
local bp = sp:FindFirstChild("TornadoSuckingForce")
local bav = sp:FindFirstChild("SuckingRotation") -- Assuming you want to keep rotation

sp.Anchored = false
sp:BreakJoints()
game.Debris:AddItem(sp, 25)

-- Create BodyForce for upward and outward push
local bf = Instance.new("BodyForce")
bf.Name = "TornadoLaunchForce"
bf.Parent = sp

local height = 0
local maxSuckHeight = tor.Size.Y

repeat
    -- Calculate the relative position to the tornado's center (on the Y axis)
    local relativeY = sp.Position.Y - (tor.Position.Y - tor.Size.Y / 2)

    -- Calculate outward force based on height (further up, more outward)
    local outwardStrength = relativeY / maxSuckHeight * 5000 * sp:GetMass() -- Adjust multiplier as needed
    local outwardDirection = (sp.Position - tor.Position) * Vector3.new(1, 0, 1) -- Project onto XZ plane
    if outwardDirection.Magnitude > 0 then
        outwardDirection = outwardDirection.Unit * outwardStrength
    end

    -- Apply upward force (constant or increasing with height)
    local upwardStrength = 2000 * sp:GetMass() + (relativeY / maxSuckHeight * 3000 * sp:GetMass()) -- Adjust multipliers
    local upwardForce = Vector3.new(0, upwardStrength, 0)

    bf.Force = upwardForce + outwardDirection

    -- Update BodyPosition to guide towards the center with a radial offset
    local radialOffset = tor.Size.X/1 + height/75
    local targetPosition = (CFrame.new(tor.Position - Vector3.new(0, tor.Size.Y/2, 0)) * CFrame.Angles(0,math.pi*2*((tick()/5)%1),0) * CFrame.new(radialOffset, height, 0)).p
    bp.Position = targetPosition

    height = height + (tor.Size.Y/25*0.5) -- aka 2% of it's Y size
    wait()
until height >= maxSuckHeight -- Use >= to ensure it finishes even if height slightly exceeds

sp:Destroy()
1 Like

I did try that, but for whatever reason it didn’t make much difference.

Thanks so much! I adjusted the values until it did what I wanted. Although how would I go about making the parts fall to the ground afterwards?
I added this onto the end

if height >= maxSuckHeight then
	sp.velocity = Vector3.new(0, script.Parent:GetMass() * (workspace.Gravity / 1.1), 0)
end

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.