How to make scripts run more efficiently

I need to know how to make this script run more efficiently

local RayCastCount = 0

local function TowerPlacing(TowerModel, RayCast)
	RayCastCount += 1
	RayCast = MouseRayCast({TowerModel, Enemies, Towers, PlayerModels})
	if RayCast then
		TweenService:Create(TowerModel.PrimaryPart, TweenInfo.new(0.125, Enum.EasingStyle.Sine), {CFrame = CFrame.new(RayCast.Position + Vector3.new(0, _G.TowerDataBase.Placing[1].YOffset, 0)) * CFrame.Angles(0, math.rad(PlacingTowerRotation.Value), 0)}):Play()
	end
	if RayCastCount >= 3 then
		RayCastCount = 0
		RayCheck(TowerInfoDataBase[TowerModel.Name].Range, TowerModel)
	end
end
---Script that calls the function if a tower is placing

The ray check thing looks weird if it is updated every 0.1 seconds

local function RayCheck(RangeValue, Tower)
	local Degrees = 36 / RangeValue
	local RayCastResult1, RayCastResult2, RayCastResult3
	for Degree = Degrees, 360 + 0.001, Degrees do
		RayCastResult1 = workspace:Raycast(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), (CFrame.new(Tower.PrimaryPart.Position) * CFrame.Angles(0, math.rad(Degree - 90), 0)).lookVector * RangeValue, RaycastParamsRay)
		RayCastResult2 = workspace:Raycast(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), (CFrame.new(Tower.PrimaryPart.Position) * CFrame.Angles(0, math.rad(Degree - 90 + (Degrees/2)), 0)).lookVector * RangeValue, RaycastParamsRay)
		RayCastResult3 = workspace:Raycast(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), (CFrame.new(Tower.PrimaryPart.Position) * CFrame.Angles(0, math.rad(Degree - 90 + Degrees), 0)).lookVector * RangeValue, RaycastParamsRay)
		
		if RayCastResult1 or RayCastResult2 or RayCastResult3 then
			if RayCastResult1 then
				if RayCastResult2 then
					DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult1.Distance, -Degree), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), false, nil, Degree)
					if RayCastResult3 then
						DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult3.Distance, -Degree - Degrees), false, nil, Degree, true)
					else
						DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - Degrees), false, nil, Degree, true)
					end
				else
					DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult1.Distance, -Degree), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), false, nil, Degree)
					
					DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - Degrees), false, nil, Degree, true)
				end
			elseif RayCastResult2 then
				DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), false, nil, Degree)
				if RayCastResult3 then
					DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult3.Distance, -Degree - Degrees), false, nil, Degree, true)
				else
					DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult2.Distance, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - Degrees), false, nil, Degree, true)
				end
			elseif RayCastResult3 then
				DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), false, nil, Degree)
				DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RayCastResult3.Distance, -Degree - Degrees), false, nil, Degree, true)
			end
		else
			DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), true, nil, Degree)
			DrawRangeCircle(Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - (Degrees/2)), Vector3.new(Tower.PrimaryPart.Position.X, RangeY, Tower.PrimaryPart.Position.Z) + GetPointOnCircle(RangeValue, -Degree - Degrees), true, nil, Degree, true)
		end
	end
end

Then the part which makes the game lag

local function DrawRangeCircle(a, b, c, NoHit, Setup, Degrees, Filler)
	local ab, ac, bc = b - a, c - a, c - b;
	local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc)
	local Wedge = RangeWedge1
	
	if NoHit == false then
		Wedge = RangeWedge2
		if (abd > acd and abd > bcd) then
			c, a = a, c
		elseif (acd > bcd and acd > abd) then
			a, b = b, a
		end
		
		ab, ac, bc = b - a, c - a, c - b
	end
	
	local Right = ac:Cross(ab).unit
	local Up = bc:Cross(Right).unit
	local Back = bc.unit
	
	local Height = math.abs(ab:Dot(Up))
	local w1, w2
	if Setup then
		w1 = Wedge:Clone()
		w2 = Wedge:Clone()
	elseif NoHit and not Setup and not Filler then
		w1 = RangePartsNoHit[Degrees..1]
		w2 = RangePartsNoHit[Degrees..2]

		RangePartsHit[Degrees..1].Transparency = 1
		RangePartsHit[Degrees..2].Transparency = 1
	elseif not NoHit and not Setup and not Filler then
		w1 = RangePartsHit[Degrees..1]
		w2 = RangePartsHit[Degrees..2]

		RangePartsNoHit[Degrees..1].Transparency = 1
		RangePartsNoHit[Degrees..2].Transparency = 1
	elseif NoHit and not Setup and Filler then
		w1 = RangePartsNoHit[Degrees..11]
		w2 = RangePartsNoHit[Degrees..12]

		RangePartsHit[Degrees..11].Transparency = 1
		RangePartsHit[Degrees..12].Transparency = 1
	elseif not NoHit and not Setup and Filler then
		w1 = RangePartsHit[Degrees..11]
		w2 = RangePartsHit[Degrees..12]

		RangePartsNoHit[Degrees..11].Transparency = 1
		RangePartsNoHit[Degrees..12].Transparency = 1
	end
	
	w1.Size = Vector3.new(0.1, Height, math.abs(ab:Dot(Back)))
	w1.CFrame = CFrame.fromMatrix((a + b) / 2, Right, Up, Back)
	
	w2.Size = Vector3.new(0.1, Height, math.abs(ac:Dot(Back)))
	w2.CFrame = CFrame.fromMatrix((a + c) / 2, -Right, Up, -Back)
	
	if Setup then
		if NoHit and not Filler then
			w1.Parent = RangePartsNoHit
			w2.Parent = RangePartsNoHit

			w1.Name = Degrees..1
			w2.Name = Degrees..2

			w1.Transparency = 1
			w2.Transparency = 1
		elseif not NoHit and not Filler then
			w1.Parent = RangePartsHit
			w2.Parent = RangePartsHit

			w1.Name = Degrees..1
			w2.Name = Degrees..2

			w1.Transparency = 1
			w2.Transparency = 1
		elseif NoHit and Filler then
			w1.Parent = RangePartsNoHit
			w2.Parent = RangePartsNoHit

			w1.Name = Degrees..11
			w2.Name = Degrees..12

			w1.Transparency = 1
			w2.Transparency = 1
		elseif not NoHit and Filler then
			w1.Parent = RangePartsHit
			w2.Parent = RangePartsHit

			w1.Name = Degrees..11
			w2.Name = Degrees..12

			w1.Transparency = 1
			w2.Transparency = 1
		end
	else
		w1.Transparency = 0.75
		w2.Transparency = 0.75
	end
end

Now I have tested it without the 3rd function, and it works fine, but I need the range to be visible and accurate. I now have it updating evey 3 frames, which is the maximum I will make it go to.
I’m just not sure how to make it work more accurately. Using Runservice:BindToRenderStep() for the towerplacing function

2 Likes

Use the and keyword to reduce the amount of if statement in the RayCheck function. Also handle moving the range circles with AlignPosition.

1 Like

that makes it laggy though. Align position also makes a lot of lag. Might i also say that its not one range circle. its multiple different triangles to make a circle, due to line of sight range. However it’s just the moving of the range circle that makes it lag.