Serious amounts of fps drops on my portal game

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    At least a stable amount of FPS

  2. What is the issue? Include screenshots / videos if possible!

When going through a portal there is mass amounts of fps drops at first it doesn’t but after several portal uses it lags and sometimes crashes my game

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

i tried putting debounces on my script but it doesnt really work well i found out its the rendering but i dont know what part really lags the game

--// Need help? Go here: https://ig-studios.github.io/YuconFramework/
--// API: https://ig-studios.github.io/YuconFramework/API.html
--// Yucon uses the MIT license. Read more here: https://raw.githubusercontent.com/iG-Studios/YuconFramework/main/LICENSE
--// Updates: https://ig-studios.github.io/YuconFramework/Updates.html

local Framework = {}

--Variables

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ContextActionService = game:GetService("ContextActionService")
local Lighting = game:GetService("Lighting")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local PlayerService = game:GetService("Players")
local CAS = game:GetService("ContextActionService")
local ShootDebounce = false
local grabbing = false
local breakloop = false
local touching = false


local player = game.Players.LocalPlayer

local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:WaitForChild("HumanoidRootPart")


local world = game.Workspace.World

local Mouse = require(game.ReplicatedStorage.Mouse).new()


local portalA = game.Workspace.Portals.PortalA
local portalB = game.Workspace.Portals.PortalB

local vertices = require(ReplicatedStorage:WaitForChild("Vertices"))
local draw = require(ReplicatedStorage:WaitForChild("DrawClass")).new(workspace.Terrain)

local ZERO = Vector3.new(0, 0, 0)
local UNIT_X = Vector3.new(1, 0, 0)
local UNIT_Y = Vector3.new(0, 1, 0)
local UNIT_Z = Vector3.new(0, 0, 1)
local XY_VEC = Vector3.new(1, 1, 0)

local EXTRASPIN = CFrame.fromEulerAnglesXYZ(0, math.pi/2, 0)

local ROTATE = CFrame.fromEulerAnglesXYZ(0, math.pi, 0)

--Instances


local FrameworkFolder = ReplicatedStorage:WaitForChild("Framework")
local WeaponsFolder = FrameworkFolder:WaitForChild("Weapons")
local ModuleFolder = FrameworkFolder:WaitForChild("Modules")

local Player = PlayerService.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Camera = workspace.CurrentCamera



--Misc
local CurrentEquipped
local CurrentModuleEquipped

local clicking = false

local Primary = "Portal"





--Functions



local function IdleAnimation()
	local Animations = CurrentEquipped.Anims
	local AnimationController = CurrentEquipped:FindFirstChild("Humanoid")
	local IdleAnim = AnimationController:LoadAnimation(Animations.Idle)

	IdleAnim:Play()

end



local function ShootAnimation()
	local Animations = CurrentEquipped.Anims
	local AnimationController = CurrentEquipped:FindFirstChild("Humanoid")
	local ShootAnim = AnimationController:LoadAnimation(Animations.Shoot)

	ShootAnim:Play()

end

local function InspectAnimation()
	local Animations = CurrentEquipped.Anims
	local AnimationController = CurrentEquipped:FindFirstChild("Humanoid")
	local inspect = "rbxassetid://9267239047"
	local InspectAnim = AnimationController:LoadAnimation(Animations.Inspect)

	return InspectAnim

end

local function vec3Func(f, ...)
	local x, y, z = {}, {}, {}
	for i, v in next, {...} do
		x[i], y[i], z[i] = v.x, v.y, v.z
	end
	return Vector3.new(f(unpack(x)), f(unpack(y)), f(unpack(z)))
end

local function getRotationBetween(u, v, axis)
	local dot, uxv = u:Dot(v), u:Cross(v)
	if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
	return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end

local function getSurfaceCF(part, lnormal)
	local pcf, size2 = part.CFrame, part.Size/2
	local transition = getRotationBetween(UNIT_Z, lnormal, UNIT_Y)
	local size = vec3Func(math.abs, transition:VectorToWorldSpace(part.Size))
	return (pcf * transition) * CFrame.new(size/2 * Vector3.new(0, 0, 1)), size
end




local function Equip(weaponName)
	for _, Child in pairs(Camera:GetChildren()) do
		if Child:IsA("Model") then
			Child.Parent = WeaponsFolder
		end
	end
	local FoundWeapon = WeaponsFolder:FindFirstChild(weaponName)
	if not FoundWeapon then return end

	CurrentEquipped = FoundWeapon
	CurrentEquipped.Parent = workspace.CurrentCamera

	IdleAnimation()
end



type Array<t> = {[number]:t} -- Array variable type
type Dictionary<t> = {[string]:t} -- Dictionary variable type

function Framework:Preload()

end

function Particles(part)




	CurrentEquipped.PortalGun.Parts.Flash.Beam.Enabled = true
	CurrentEquipped.PortalGun.Parts.Flash.Beam2.Enabled = true
	CurrentEquipped.PortalGun.Parts.Flash.Beam3.Enabled = true
	CurrentEquipped.PortalGun.Parts.Flash.Beam4.Enabled = true
	CurrentEquipped.PortalGun.Parts.Flash.Fire.Enabled = true
	CurrentEquipped.PortalGun.Parts.Flash.PointLight.Enabled = true
	task.wait(0.5)
	CurrentEquipped.PortalGun.Parts.Flash.Beam.Enabled = false
	CurrentEquipped.PortalGun.Parts.Flash.Beam2.Enabled = false
	CurrentEquipped.PortalGun.Parts.Flash.Beam3.Enabled = false
	CurrentEquipped.PortalGun.Parts.Flash.Beam4.Enabled = false
	CurrentEquipped.PortalGun.Parts.Flash.Fire.Enabled = false
	CurrentEquipped.PortalGun.Parts.Flash.PointLight.Enabled = false

end

function Grab(target)
	while breakloop == false do
		local box = target
		grabbing = true
		wait()
		print(target)


		target.Anchored = true


		box.CFrame = CFrame.new(CurrentEquipped.PortalGun.Handle.PartPosition.Position)
		local CF = CurrentEquipped.PortalGun.Handle.PartPosition.CFrame
		local pos = CF



		for i, touching in pairs(workspace:GetPartsInPart(target)) do
			if touching:IsA("BasePart") then
				if touching.Name == "Microwave" then
					game.ReplicatedStorage.Position:FireServer(target, pos)

					CurrentEquipped.PortalGun.Parts.Flash.Beam.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam2.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam3.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam4.Enabled = false
					grabbing = false
					breakloop = true

				end

			end
		end

	end


end



function Framework:Render(Delta:number)
	if CurrentEquipped ~= nil then
		CurrentEquipped:SetPrimaryPartCFrame(Camera.CFrame)
	end


end




function Framework:Step(Delta:number)

end

function Framework:Start()


	game.Workspace.Portals.PortalACollider:Destroy()
	game.Workspace.Portals.PortalBCollider:Destroy()

	Equip(Primary)

	player.PlayerGui.SurfaceGui.Name = "SurfaceGui2"

	local blue = script.Blue:Clone()
	local orange = script.Orange:Clone()

	blue.Parent = portalA
	orange.Parent = portalB



	UserInputService.InputBegan:Connect(function(keyPressed, Chat)

		if keyPressed.KeyCode == Enum.KeyCode.F then
			local anim = InspectAnimation()
			InspectAnimation():Play()


		end

		if keyPressed.KeyCode == Enum.KeyCode.E then
			if Chat then return end
			if grabbing == false then
				local target = Mouse.Target

				local CF = CurrentEquipped.PortalGun.Handle.PartPosition.CFrame
				local pos = CF

				if target.Parent.Parent.Name == "Box" then

					local CF = CurrentEquipped.PortalGun.Handle.PartPosition.CFrame
					breakloop = false
					print(Mouse.Target)
					grabbing = true
					print("box")
					CurrentEquipped.PortalGun.Parts.Flash.Beam.Enabled = true
					CurrentEquipped.PortalGun.Parts.Flash.Beam2.Enabled = true
					CurrentEquipped.PortalGun.Parts.Flash.Beam3.Enabled = true
					CurrentEquipped.PortalGun.Parts.Flash.Beam4.Enabled = true
					local MouseTarget = Mouse.Target
					print(MouseTarget)
					local humanoidRootPart = MouseTarget.Parent.Parent:FindFirstChild("HumanoidRootPart") or MouseTarget.Parent:FindFirstChild("HumanoidRootPart")
					print(humanoidRootPart)





					Grab(humanoidRootPart)




				else
					print("target " .. Mouse.Target.Name .. " Is not a box")

				end
			else
				if grabbing == true then
					if Chat then return end

					breakloop = true


					local CF = CurrentEquipped.PortalGun.Handle.PartPosition.CFrame

					local MouseTarget = Mouse.Target

					local target = MouseTarget.Parent.Parent.PrimaryPart or MouseTarget.Parent.PrimaryPart
					target.Anchored = false

					local pos = CF


					print("Unanchored")


					grabbing = false
					print(pos)
					print(target)
					print("breaking")
					wait()
					CurrentEquipped.PortalGun.Parts.Flash.Beam.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam2.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam3.Enabled = false
					CurrentEquipped.PortalGun.Parts.Flash.Beam4.Enabled = false
					target.Anchored = false
					breakloop = false
					game.ReplicatedStorage.Position:FireServer(target, pos)


				end
			end
		end

		Mouse.Button1Down:Connect(function()

			local target = Mouse.Target
			print(target)

			if (target) then
				if grabbing == true then return end
				if target.Parent.Name == "Placeable" then
					local normal = Mouse.TargetSurfaceNormal
					local rotation, surfaceSize = getSurfaceCF(target, target.CFrame:VectorToObjectSpace(normal))
					local camCF = rotation:ToObjectSpace(workspace.CurrentCamera.CFrame)
					local rVec = (camCF.RightVector * XY_VEC).Unit
					local uVec = UNIT_Z:Cross(rVec).Unit
					local surfaceCF = CFrame.fromMatrix(ZERO, rVec, uVec)
					local portalPart = portalA 

					local corners = vertices.Block(surfaceCF, portalPart.Size/2)
					local max = vec3Func(math.max, unpack(corners))
					local min = vec3Func(math.min, unpack(corners))
					local pSize = max - min

					if (pSize.x > surfaceSize.x or pSize.y > surfaceSize.y) then
						-- can't place item (won't fit)
						return
					end

					local pos = rotation:PointToObjectSpace(Mouse.Hit.p)
					pos = rotation:PointToWorldSpace(Vector3.new(
						math.clamp(pos.x, -surfaceSize.x/2 + pSize.x/2, surfaceSize.x/2 - pSize.x/2),
						math.clamp(pos.y, -surfaceSize.y/2 + pSize.y/2, surfaceSize.y/2 - pSize.y/2),
						pos.z
						))


					portalPart.CFrame = (rotation - rotation.p) * surfaceCF + pos + normal*pSize.z/2
					portalPart.CFrame = portalPart.CFrame * CFrame.Angles(0, math.rad(180), 0)
					portalPart.CanCollide = false


					ShootAnimation()
					CurrentEquipped.Blue:Play()

					Particles(portalPart)


					portalPart.Touched:Connect(function(hit)
						print("touching")
						if touching == false then
							if hit.Parent:FindFirstChild("Humanoid") and hit.Parent == Character then
								touching = true
								if target.CanCollide == true then
									print(touching)
									target.CanCollide = false
								end
							end





							portalPart.TouchEnded:Connect(function(hit)
								print("not touching")
								if touching == true then
									if target.CanCollide == false then
										touching = false
										print(touching)
										task.wait(0.15)
										target.CanCollide = true
									end
								end
								
							end)
						end
					end)
				end
			end
		end)

		Mouse.Button2Down:Connect(function()
			local target2 = Mouse.Target

			print(target2)
			if (target2) then
				if grabbing == true then return end
				if target2.Parent.Name == "Placeable" then
					local normal2 = Mouse.TargetSurfaceNormal
					local rotation, surfaceSize = getSurfaceCF(target2, target2.CFrame:VectorToObjectSpace(normal2))
					local camCF = rotation:ToObjectSpace(workspace.CurrentCamera.CFrame)
					local rVec = (camCF.RightVector * XY_VEC).Unit
					local uVec = UNIT_Z:Cross(rVec).Unit
					local surfaceCF = CFrame.fromMatrix(ZERO, rVec, uVec)
					local portalPart = portalB

					local corners = vertices.Block(surfaceCF, portalPart.Size/2)
					local max = vec3Func(math.max, unpack(corners))
					local min = vec3Func(math.min, unpack(corners))
					local pSize = max - min

					if (pSize.x > surfaceSize.x or pSize.y > surfaceSize.y) then
						-- can't place item (won't fit)
						return
					end

					local pos = rotation:PointToObjectSpace(Mouse.Hit.p)
					pos = rotation:PointToWorldSpace(Vector3.new(
						math.clamp(pos.x, -surfaceSize.x/2 + pSize.x/2, surfaceSize.x/2 - pSize.x/2),
						math.clamp(pos.y, -surfaceSize.y/2 + pSize.y/2, surfaceSize.y/2 - pSize.y/2),
						pos.z
						))


					portalPart.CFrame = (rotation - rotation.p) * surfaceCF + pos + normal2*pSize.z/2
					portalPart.CFrame = portalPart.CFrame * CFrame.Angles(0, math.rad(180), 0)
					portalPart.CanCollide = false
					game.Workspace.Portals.PortalACollider.CanCollide = false
					game.Workspace.Portals.PortalBCollider.CanCollide = false

					ShootAnimation()
					CurrentEquipped.Orange:Play()

					Particles(portalPart)





					portalPart.Touched:Connect(function(hit)
						if touching == false then
							if hit.Parent:FindFirstChild("Humanoid") and hit.Parent == Character then
								touching = true
								if target2.CanCollide == true then
									target2.CanCollide = false
								end
							end
						




							portalPart.TouchEnded:Connect(function(hit)
								if touching == true then
									if target2.CanCollide == false then
										touching = false
										task.wait(0.15)
										target2.CanCollide = true
									end
								end
								
							end)
						end
					end)
				end
			end
		end)
	end)
end













game.Lighting.Ambient = Color3.new(0.27451, 0.27451, 0.27451)
game.Lighting.Brightness = 2
game.Lighting.ColorShift_Top = Color3.new(0, 0, 0)
game.Lighting.ColorShift_Bottom = Color3.new(0, 0, 0)
game.Lighting.EnvironmentDiffuseScale = 0
game.Lighting.EnvironmentSpecularScale = 1
game.Lighting.OutdoorAmbient = Color3.new(0.27451, 0.27451, 0.27451)
game.Lighting.ShadowSoftness = 0






return Framework

It also reaches 400+ rates/s on the script performance tab

I am sure its a loop issue or you are calling your functions continuously.
Try adding task.wait() in each function [task.wait() is better in performance than wait()]

And search your every loop, especially while loops. Make sure they have wait into them.

1 Like

Alright ill try that thanks ill tell if it works