How can I optimize my VFX code?

Hi there!

Back at it again with some more outstanding issues (woohoo)

I have a problem with my VFX script. I have been working on it with some great folks over this topic and a great problem has spawned. For some reason, my script is REALLY lagging the game when I run. I’m not sure why. Here’s footage of it in action.

Here are the scripts in question:

OnAction located in StarterPlayerScripts

local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local root = char:WaitForChild("HumanoidRootPart")
local fallDistance
local VFXController = require(game:GetService("ReplicatedFirst").Modules.VFXController)

if humanoid and root then
    local headHeight
    humanoid.FreeFalling:Connect(function(state)
        if state then
            headHeight = root.Position.Y
        elseif not state and headHeight ~= nil then
            fallDistance = headHeight - root.Position.Y
            --print("Fall distance: " .. fallDistance)
        end
    end)
end

humanoid.StateChanged:Connect(function(old, new)
    if old == Enum.HumanoidStateType.Freefall and new == Enum.HumanoidStateType.Landed and fallDistance >= 22 then
        local animation = script.Parent:WaitForChild("Animate").land.landAnim
        local dance = humanoid:LoadAnimation(animation)
        dance:Play()
        VFXController.Action("Stomp", false)
        task.wait(0.2)
    end
end)

local isIdle = false

local db = true

game:GetService("RunService").RenderStepped:Connect(function()
    while humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air do
        print(humanoid.FloorMaterial)
        print("Person is running")
        VFXController.Action("Run", true)
        task.wait(0.2)
    end
end)

VFXController (ModuleScript in ReplicatedFirst)

local VFX = {}

-- Variables

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Player = game.Players.LocalPlayer
local Effects = ReplicatedStorage.VFX.Effects
local Actions = ReplicatedStorage.VFX.Actions

local UserRunning = false

-- Functions

--  When user stomps it activates the VFX related to it
local function Stomp()
    local VFXFolder = Actions.Stomp
    local InitialSize = Vector3.new(0.15, 1, 2.309)
    
    for _, VFXContent in pairs(VFXFolder:GetChildren()) do
        if VFXContent:isA("Model") and VFXContent.Name == "Triangles" then
            local SparkEffect = Effects.Spark:Clone()
            SparkEffect.Parent = Player.Character:WaitForChild("Torso")
            local ModelClone = VFXContent:Clone()
            ModelClone.Parent = workspace
            ModelClone:MoveTo(Vector3.new(Player.Character:WaitForChild("Torso").Position.X, Player.Character:WaitForChild("Torso").Position.Y - 7, Player.Character:WaitForChild("Torso").Position.Z))

            for _, VFXDescendant in pairs(ModelClone:GetChildren()) do
                VFXDescendant.Size = InitialSize
                local RandomSize = math.random(4, 8)
                local ShowTween = TweenService:Create(VFXDescendant, TweenInfo.new(0.2, Enum.EasingStyle.Quint, Enum.EasingDirection.InOut), {Size = Vector3.new(VFXDescendant.Size.X, RandomSize, VFXDescendant.Size.Z)})
                ShowTween:Play()
                SparkEffect.Enabled = true
            end
            task.wait(0.2)
            for _, VFXDescendants in pairs(ModelClone:GetChildren()) do
                local HideTween = TweenService:Create(VFXDescendants, TweenInfo.new(0.1, Enum.EasingStyle.Quint, Enum.EasingDirection.InOut), {Size = Vector3.new(InitialSize)})
                HideTween:Play()
                SparkEffect:Destroy()
            end
            task.wait(0.1)
            ModelClone:Destroy()
        end
    end
end

local funcRunning = false

--  When user runs it activates the VFX related to it
local function Run()
    local VFXFolder = Actions.Run

    if funcRunning  then return end
    funcRunning  = true

    for _, VFXContent in VFXFolder:GetChildren() do
        local Leg = math.random(0,1)
        local VFXDescendant = VFXContent:Clone()
        if Leg == 0 then
            VFXDescendant.Parent = game.Players.LocalPlayer.Character:WaitForChild("Left Leg")
            VFXDescendant.Position = game.Players.LocalPlayer.Character:WaitForChild("Left Leg").Position
        else
            VFXDescendant.Parent = game.Players.LocalPlayer.Character:WaitForChild("Right Leg")
            VFXDescendant.Position = game.Players.LocalPlayer.Character:WaitForChild("Right Leg").Position
        end
        local RunningTween = TweenService:Create(VFXDescendant, TweenInfo.new(0.5, Enum.EasingStyle.Quint, Enum.EasingDirection.Out), {Transparency = 1, Orientation = Vector3.new(math.random(0, 360),math.random(0, 360),math.random(0, 360))})
        RunningTween:Play()
        RunningTween.Completed:Connect(function()
            VFXDescendant:Destroy()
        end)
        task.wait(0.1)
    end
    funcRunning = false
end

local function Idle(Condition)
    return
end

-- On Fired

function VFX.Action(Action, isRunning)
    UserRunning = isRunning
    if Action == "Stomp" then
        Stomp()
    end

    if Action == "Run" then
        Run()
    end

    if Action == "Idle" then
        Idle()
    end
end

return VFX

Thanks,
Aki

2 Likes

Are you sure its not because it checks if person is running every second?

2 Likes

Woah woah woah! Remember what I said about double loops?


game:GetService("RunService").RenderStepped:Connect(function()
    while humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air do
        print(humanoid.FloorMaterial)
        print("Person is running")
        VFXController.Action("Run", true)
        task.wait(0.2)
    end
end)

You don’t need the RunService part anymore. You just need the while loop.

while humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air do
      print(humanoid.FloorMaterial)
      print("Person is running")
      VFXController.Action("Run", true)
      task.wait(0.2)
 end

It wasn’t doing this before the latest update, so I don’t think so?..

2 Likes

oops. I did not follow my homework. I’ll fix that!

Update: Fixed

2 Likes

Does it still lag? I’m fairly sure this is the root of the problem.
The reason why double loops are so deadly is because you’re executing a really performance-hungry loop inside another really performance-hungry loop. If you are the script, you’ve got a lot of processing to do.

Now none of it is working?? Nevermind stomp works.

1 Like

Does it print the “Person is running” part and floor material?

No, not at all. Not even once.

Can I see your new code?
charscharschars

im pretty sure its because you only checked to see if you should start the while loop once and if the criteria arent met it wont try to check again. you do need to nest the loop into another loop but instead you should check for the conditions and if they arent met, tell the script to wait until it is.

1 Like
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")
local root = char:WaitForChild("HumanoidRootPart")
local fallDistance
local VFXController = require(game:GetService("ReplicatedFirst").Modules.VFXController)

if humanoid and root then
    local headHeight
    humanoid.FreeFalling:Connect(function(state)
        if state then
            headHeight = root.Position.Y
        elseif not state and headHeight ~= nil then
            fallDistance = headHeight - root.Position.Y
            --print("Fall distance: " .. fallDistance)
        end
    end)
end

humanoid.StateChanged:Connect(function(old, new)
    if old == Enum.HumanoidStateType.Freefall and new == Enum.HumanoidStateType.Landed and fallDistance >= 22 then
        local animation = script.Parent:WaitForChild("Animate").land.landAnim
        local dance = humanoid:LoadAnimation(animation)
        dance:Play()
        VFXController.Action("Stomp", false)
        task.wait(0.2)
    end
end)

local isIdle = false

local db = true

while humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air do
    print(humanoid.FloorMaterial)
    print("Person is running")
    VFXController.Action("Run", true)
    task.wait(0.2)
end

smh yeah i am an idiot (again). You’re completely right, we need to change the while loop slightly:

while task.wait(0.2) do
    if humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air then
        print(humanoid.FloorMaterial)
        print("Person is running")
        VFXController.Action("Run", true)
    end
end
3 Likes

i think waiting will also optimise the script

1 Like

It’s not lagging at all which is great! Finally, maybe I can consider this dang situation done for once after these 2 days.

1 Like

worked :+1:
\\\\\\\\\\\\

2 Likes

This was mostly my fault, I overcomplicated things wayyyy too much and made a ton of stupid mistakes :man_facepalming: sorry for the wasted time :confused:

Dude you’re fine! I’ve learnt a few things along the way so I really appreciate it! Plus you spent 2 days with me trying to fix problem so thank you! :slight_smile:

1 Like

Yeah, no problem (i had absolutely nothing to do and i was really just bored :/). Good luck on your game though!

Thank you so much!!! :smiley: ///////

2 Likes