How can I improve this script?

I’ve recently made a script on a “rasengan” attack (Pretty much a ball that does damage) but I feel it’s very janky and would lag. So, I came to the devforum to see how I can make this script more efficient.

Heres a video of what the script does:

And heres the script:

script.Parent.OnServerEvent:Connect(function(plr)
	local char = plr.Character
	local hand = char.RightHand
	local hum = char.Humanoid
	local debris = game:GetService("Debris")
	local rasengan = game.Lighting.RasenganPart:Clone()
	local weld = Instance.new("Weld")
	local db = false
	local blast = script.Parent.Parent.Blast:Clone()
	local tweenservice = game:GetService("TweenService")
	
	
	
	hum.WalkSpeed = 22
	rasengan.Parent = hand
	
	weld.Name = "RasenWeld"
	weld.Parent = hand
	weld.Part0 = hand
	weld.Part1 = rasengan
	weld.C0 = CFrame.new(0,-.7,0)
	
	wait(.5)
	
	spawn(function()
		while rasengan do
			for i,v in pairs(workspace:GetChildren()) do
				if v ~= char and db == false then
					if v:FindFirstChild("HumanoidRootPart") then
					if (char.HumanoidRootPart.CFrame.p - v.HumanoidRootPart.CFrame.p).Magnitude <= 6 then
						v.Humanoid:TakeDamage(35)
						db = true
						debris:AddItem(rasengan,.1)
						debris:AddItem(weld,.1)
						hum.WalkSpeed = 16

						
						
						hum.WalkSpeed = 16
						blast.Parent = workspace
						blast.CFrame = v.HumanoidRootPart.CFrame
						tweenservice:Create(blast,TweenInfo.new(.5),{Size =Vector3.new(15,15,15)}):Play()
						local BodyVelocity = Instance.new("BodyVelocity")
						BodyVelocity.Parent = v.HumanoidRootPart -- // Parent it to object you want to push
						BodyVelocity.MaxForce = Vector3.new(math.huge,math.huge,math.huge)

							BodyVelocity.Velocity = -(char.HumanoidRootPart.Position - v.HumanoidRootPart.Position).Unit * 30-- // the * 45 is POWER, so you can change it 
							local rayparams = RaycastParams.new()
							rayparams.FilterDescendantsInstances = {workspace.Ignore}
							rayparams.FilterType = Enum.RaycastFilterType.Blacklist

							local angle = 0
							for i=1, 15 do --Make sure second multiple is multiple of 360  360/15 = 24
								local size = math.random(3,5)
								local rock = script.Parent.Parent.Rocks:Clone()
								rock.Size = Vector3.new(size,size,size)
								rock.CFrame = v.HumanoidRootPart.CFrame * CFrame.fromEulerAnglesXYZ(0,math.rad(angle),0) * CFrame.new(0,1,-10)

								local ray = workspace:Raycast(rock.CFrame.p,rock.CFrame.UpVector * -5, rayparams) -- origin, direction, filter
								if ray then
									rock.CFrame = rock.CFrame * CFrame.new(0,-size+ -1,0)
									rock.Material = ray.Instance.Material
									rock.Color = ray.Instance.Color
									rock.Orientation = Vector3.new(math.random(-180,180),math.random(-180,180),math.random(-180,180))
									rock.Parent = workspace
									angle += 24
								end
								
								
								delay(.7,function()
									
						tweenservice:Create(blast,TweenInfo.new(1.5),{Transparency = 1}):Play()
						tweenservice:Create(rock,TweenInfo.new(1.5),{Transparency = 1}):Play()
				
						debris:AddItem(rock,3)
						debris:AddItem(BodyVelocity,.2)
									debris:AddItem(blast,2)
									end)

						
						
							end
						end
						end
				end
			end
			wait(.01)
		end
	end)
	
	wait(6)
	debris:AddItem(rasengan,.1)
	debris:AddItem(weld,.1)
	hum.WalkSpeed = 16
	
	
end)

Thank you so much.

2 Likes

Why do you need this while loop? From what I can see here, it’s possible for damage to stack up (unless I’m mistaken).

Also, you should move to the Code Review category.

Thank you for the category change. The while loop is to check if anyone gets in radius since it only checks once, I made a debounce once it finds someone so it doesn’t stack damage.

  1. You can establish these variables before connecting the event:

local debris = game:GetService(“Debris”)
local rasengan = game.Lighting.RasenganPart:Clone()
local tweenservice = game:GetService(“TweenService”)

  1. At this part:

weld.Name = “RasenWeld”
weld.Parent = hand
weld.Part0 = hand
weld.Part1 = rasengan
weld.C0 = CFrame.new(0,-.7,0)

You should set the parent last when creating a new instance to avoid replicating changes multiple times.

  1. When not using the deltatime wait() returns (espically if the argument is below 1) you should use task.wait() instead, as it’s more reliable.

  2. At the for i,v in pairs loops, you are establishing i but not using it. If you are not using it, you should replace it with an _ to save resources.

Example: for i,v in pairs(workspace:GetChildren()) do to for _,v in pairs(workspace:GetChildren()) do

How would changing a character “save” resources? You’re literally just changing a byte.

By changing i with _, you are not creating a variable and not counting loops

Oh really?

(my bad, i used pairs instead of ipairs but even that should have the same result as seen here:)

2 Likes

Interesting, I always thought _ wasn’t getting calculated

1 Like

Personally, for the smoothest result, you should do moves on the client like this:

Player uses move > Fire Remote to server > Fire to all clients > Do the move

This is called client-side rendering, on the server, you could have an invisible part that indicates the projectile or you can just use tables whichever you prefer.

Thanks everyone, the script feels more efficient now and less laggy, appreciate it and have a good day.

Personally, I use tables to collect my characters & Humanoid objects. It will drastically increase performance.

local humanoids = {} :: {Humanoid}
local characters = {} :: {Model}

for _, humanoid: Humanoid in pairs(workspace:GetDescendants()) do
	if humanoid:IsA("Humanoid") then
		table.insert(humanoids, humanoid)
		local model = humanoid.Parent
		if typeof(model) == 'Instance' and model:IsA("Model") then
			table.insert(characters, model)
		end
	end
end

workspace.DescendantAdded:Connect(function(humanoid: Humanoid): ()
	if humanoid:IsA("Humanoid") then
		table.insert(humanoids, humanoid)
		local model = humanoid.Parent
		if typeof(model) == 'Instance' and model:IsA("Model") then
			table.insert(characters, model)
		end
	end
end)