Help with reviewing this flight code

Provide an overview of:
What does the code do and what are you not satisfied with?
it gives the plr the ability to fly and the plr’s rotation along with it’s particles replicates to other clients, however i think it is pretty bad performance wise, it is my first time trying something like this so im not sure how i should approach this issue.
by what i had checked in the script performance tab it has an activity of 4-6%

What potential improvements have you considered?
i’ve considered limiting the amount of times i send data over to the server but im not sure if that would change much since im using an unreliable remote event (which i think already does that?)

How (specifically) do you want to improve the code?
if possible i’d like to know how to improve it performance wise and get tips for future work

function Flight()
	local Char = Plr.Character or Plr.CharacterAdded:Wait()
	local Root = Char:FindFirstChild("HumanoidRootPart")
	local Hum = Char:FindFirstChildOfClass("Humanoid")

	if Hum:GetAttribute("IsFlying") ~= nil or Hum:GetAttribute("Dash") ~= nil then return end

	local FilterTable = {Char}
	local RayParams = RaycastParams.new()
	RayParams.FilterDescendantsInstances = FilterTable
	RayParams.FilterType = Enum.RaycastFilterType.Exclude
	RayParams.IgnoreWater = false

	local FloorCast = workspace:Raycast(Root.Position, Root.CFrame.UpVector * - (Root.Size.Y/2 + Char["Left Leg"].Size.Y + 0.5), RayParams)
	if FloorCast and FloorCast.Instance then return end

	Hum:SetAttribute("IsFlying", true)
	Hum.AutoRotate = false	


	local Attach = Instance.new("Attachment")
	Attach.Name = "FlightAttach"
	Attach.Parent = Root

	local LinearVelocity = Instance.new("LinearVelocity")
	LinearVelocity.Attachment0 = Attach
	LinearVelocity.MaxForce = 100000
	LinearVelocity.VectorVelocity = Vector3.new(0, 10, 0)
	LinearVelocity.Parent = Attach

	local OldDirection = ""

	local SpeedMultiplier = 1
	local UpVector = Vector3.new(0, 0, 0)
	local LookAtCFrame = Root.Position + Root.CFrame.LookVector * 40

	ToDisconnect["UponDeath"] = Hum.HealthChanged:Connect(function()
		if Hum.Health <= 0 then
			Undo(Root, Hum)
		end
	end)

	ToDisconnect["RotationFunction"] = RunService.RenderStepped:Connect(function()
		if UpVector ~= Vector3.new(0, 0, 0) then
			Root.RootJoint.C0 = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(90), math.rad(180), 0)
			LookAtCFrame = Vector3.new(Camera.CFrame.LookVector.X * 900000, Root.Position.Y, Camera.CFrame.LookVector.Z * 900000)
			Root.CFrame = CFrame.new(Root.Position, LookAtCFrame)
		elseif Hum.MoveDirection == Vector3.new(0, 0, 0) then
			Root.CFrame = CFrame.new(Root.Position, LookAtCFrame)
		else
			local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).LookVector	

			Root.RootJoint.C0 = CFrame.new(0, 0, 0) * CFrame.Angles((90 + (CameraDirection.Y * 1.5) - .35), math.rad(-180), 0)
			LookAtCFrame = Vector3.new(Camera.CFrame.LookVector.X * 900000, Root.Position.Y, Camera.CFrame.LookVector.Z * 900000)
			Root.CFrame = CFrame.new(Root.Position, LookAtCFrame)
		end

		if Root and Root:FindFirstChild("RootJoint") then
			ReplicatedStorage.RemoteEvents.FlightUpdate:FireServer(Root.RootJoint.C0, SpeedMultiplier)
		end
	end)


	RunService:BindToRenderStep("Fly", 150, function()
		local ray = workspace:Raycast(Root.Position, Root.CFrame.UpVector * - (Root.Size.Y/2 + Char["Left Leg"].Size.Y + 0.3), RayParams)
		if ray and ray.Instance then

			local Part = ray.Instance			
			if Part.Parent:FindFirstChildOfClass("Humanoid") then
				table.insert(FilterTable, Part.Parent)
			else

				if Part:IsA("Part") then
					if Root.Position.Y >= Part.Position.Y + Part.Size.Y/2 then
						Undo(Root, Hum)
					end

				else
					Undo(Root, Hum)
				end

			end
		end


		local MoveVector = ControlModule:GetMoveVector()
		if MoveVector:Dot(MoveVector) == 0 or UpVector ~= Vector3.new(0, 0, 0) then 
			TweenService:Create(LinearVelocity, TweenInfo.new(.1, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out), {VectorVelocity = Vector3.new(0, 0, 0) + UpVector * SpeedMultiplier}):Play()

			if OldDirection ~= "Idle" and UpVector.Y == 0 then
				OldDirection = "Idle"
				ChangeAnim("Idle", Char, Hum)
			elseif OldDirection ~= "Down" and UpVector.Y < 0 then
				OldDirection = "Down"
				ChangeAnim("Down", Char, Hum)
			elseif OldDirection ~= "Up" and UpVector.Y > 0 then
				OldDirection = "Up"
				ChangeAnim("Up", Char, Hum)
			end
		else
			local CurrentDirection
			if math.abs(MoveVector.X) > math.abs(MoveVector.Z) then
				CurrentDirection = MoveVector.X > 0 and "Right" or "Left"
			else
				CurrentDirection = MoveVector.Z > 0 and "Backwards" or "Forward"
			end

			if CurrentDirection == "Forward" and SpeedMultiplier ~= 1 then
				if Anims.Forward == "rbxassetid://15924762835" then
					Anims.Forward = "rbxassetid://16465164805"
					ChangeAnim(CurrentDirection, Char, Hum)
				end

			elseif CurrentDirection == "Forward" and SpeedMultiplier == 1 then
				if Anims.Forward == "rbxassetid://16465164805" then
					Anims.Forward = "rbxassetid://15924762835"
					ChangeAnim(CurrentDirection, Char, Hum)
				end
			end

			if CurrentDirection ~= OldDirection then
				OldDirection = CurrentDirection
				ChangeAnim(CurrentDirection, Char, Hum)
			end
		end

		if MoveVector:Dot(MoveVector) ~= 0 then
			local Direction = CFrame.new(Camera.CFrame.Position, (Camera.CFrame * CFrame.new(MoveVector)).Position)
			local TotalVector
			if UpVector ~= Vector3.new(0, 0, 0) then		
				TotalVector = (Direction.LookVector * 50) * Vector3.new(1, 0, 1) + UpVector
			else
				TotalVector = (Direction.LookVector * 50)
			end

			TotalVector = Vector3.new(TotalVector.X, math.clamp(TotalVector.Y, -50, 50), TotalVector.Z)
			TweenService:Create(LinearVelocity, TweenInfo.new(.1, Enum.EasingStyle.Linear), {VectorVelocity = TotalVector * SpeedMultiplier}):Play()

		end

	end)

	local CurrentButton = nil
	ToDisconnect["InputFunction"] = InputService.InputBegan:Connect(function(Input, Processed)
		if Processed and Input.KeyCode ~= Enum.KeyCode.LeftShift then return end
		-- Fast flight
		if Input.KeyCode == Enum.KeyCode.LeftShift and (Hum.MoveDirection ~= Vector3.new(0, 0, 0) or UpVector ~= Vector3.new(0, 0, 0)) and Plr:GetAttribute("FastFlight") == nil then
			Plr:SetAttribute("FastFlight", true)

			ToDisconnect["FastFlight"] = task.spawn(function()
				local EffectPart = ReplicatedStorage["Fly Effect"]:Clone()
				EffectPart.CFrame = Char.HumanoidRootPart.CFrame
				EffectPart.Parent = Char

				local ActivationSFX = Instance.new("Sound")
				ActivationSFX.SoundId = Sounds.Activation
				ActivationSFX.Parent = Char
				ActivationSFX.Volume = 2
				ActivationSFX:Play()
				Debris:AddItem(ActivationSFX, 2)

				local LoopSFX = Instance.new("Sound")
				LoopSFX.SoundId = Sounds.FastFlight
				LoopSFX.Parent = EffectPart
				LoopSFX.Looped = true
				LoopSFX.Volume = 2
				LoopSFX:Play()

				task.wait()
				for _, Effect in pairs(EffectPart:GetDescendants()) do
					if Effect:IsA("ParticleEmitter") then
						Effect:Emit(Effect:GetAttribute("EmitCount"))
					end
				end

				repeat
					task.wait()
					SpeedMultiplier = math.clamp(SpeedMultiplier + .1, 1, 3)
					EffectPart.CFrame = CFrame.new(Root.Position, Root.Position + (LinearVelocity.VectorVelocity.Unit * 5))
				until InputService:IsKeyDown(Enum.KeyCode.LeftShift) == false or (Hum.MoveDirection == Vector3.new(0, 0, 0) and UpVector == Vector3.new(0, 0, 0))

				EffectPart.Anchored = false
				LoopSFX:Destroy()

				local Weld = Instance.new("WeldConstraint")
				Weld.Part0 = Char.HumanoidRootPart
				Weld.Part1 = EffectPart
				Weld.Parent = EffectPart

				local StopSFX = Instance.new("Sound")
				StopSFX.SoundId = Sounds.Stop
				StopSFX.Parent = Char
				StopSFX.Volume = 2
				StopSFX:Play()
				Debris:AddItem(StopSFX, 2)

				if EffectPart["Dark Speed Effect"].Enabled == true then
					for _, Effect in pairs(EffectPart:GetDescendants()) do
						if Effect:IsA("ParticleEmitter") then
							Effect.Enabled = false
							if Effect:GetAttribute("EmitCount") > 0 then
								Effect:Emit(Effect:GetAttribute("EmitCount"))
							end
						elseif Effect:IsA("Trail") then
							Effect.Lifetime = 0 
						end
					end

					Debris:AddItem(EffectPart, 0.5)
				end

				SpeedMultiplier = 1

				task.wait(0.3)
				Plr:SetAttribute("FastFlight", nil)
			end)
		end

		-- Up and down
		if Input.KeyCode == Enum.KeyCode.LeftControl then
			CurrentButton = "LeftControl"
			ToDisconnect["DownFlight"] = task.spawn(function()
				repeat
					UpVector = Vector3.new(0, -50, 0)
					task.wait()
				until CurrentButton ~= "LeftControl" or InputService:IsKeyDown(Enum.KeyCode.LeftControl) == false
				UpVector = Vector3.new(0, 0, 0)
			end)

		elseif Input.KeyCode == Enum.KeyCode.Space then
			CurrentButton = "Space"
			ToDisconnect["UpFlight"] = task.spawn(function()
				repeat
					UpVector = Vector3.new(0, 50, 0)
					task.wait()
				until CurrentButton ~= "Space" or InputService:IsKeyDown(Enum.KeyCode.Space) == false
				UpVector = Vector3.new(0, 0, 0)
			end)
		end
	end)

end
1 Like

Check out this video, it’s very well explained and seems to do exactly what you’re looking for:

Script shown in the video works great and is very performant. In theory you shouldn’t really need any server checks / or client-server/server-client networking

2 Likes