How could I optimize / improve this script?

Hi! I’m sorry for providing a large amount of code, but I was wondering if anyone would be able to give any suggestions as to how I would improve / make this code more efficient?

-- Services --
local ContactActionService = game:GetService("ContextActionService")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer
local Character = Player.Character
local Humanoid = Character:WaitForChild("Humanoid")

-- Event Names --
local ToggleSprint = "ToggleSprint"
local ToggleCrawl = "ToggleCrawl"

-- Animations --
local AnimationsFolder = script:WaitForChild("Animations")
local Animator = Humanoid:WaitForChild("Animator")

local CrowchingAnimations  = { -- Crawling Animations
	["Transition"] = Animator:LoadAnimation(AnimationsFolder.Crawling:WaitForChild("Transition")),
	["Walking"] = Animator:LoadAnimation(AnimationsFolder.Crawling:WaitForChild("Walking")),
	["Idle"] = Animator:LoadAnimation(AnimationsFolder.Crawling:WaitForChild("Idle"))
}

local WalkingAnimations = { -- Walking Animations
	["TransitionS"] = Animator:LoadAnimation(AnimationsFolder.Walking:WaitForChild("Transition (Sprinting)")),
	["TransitionC"] = Animator:LoadAnimation(AnimationsFolder.Walking:WaitForChild("Transition (Crouching)")),
	["Walking"] = Animator:LoadAnimation(AnimationsFolder.Walking:WaitForChild("Walking")),
	["Idle"] = Animator:LoadAnimation(AnimationsFolder.Walking:WaitForChild("Idle"))
}

local SprintingAnimations = { -- SprintingAnimations
	["Transition"] = Animator:LoadAnimation(AnimationsFolder.Sprinting:WaitForChild("Transition")),
	["Walking"] = Animator:LoadAnimation(AnimationsFolder.Sprinting:WaitForChild("Walking")),
	["Idle"] = Animator:LoadAnimation(AnimationsFolder.Sprinting:WaitForChild("Idle"))
}

-- Objects --
local Camera = game.Workspace:WaitForChild("Camera")
local Gui = script.Parent

-- Misc --
local Debounce = false 
local Sprinting = false -- True if the player is sprinting 
local Crawling = false -- True if the player is Crawling 
local Transition = false -- True if the Player is in a transition animation

-- Settings --
local NormalJumpPower = 50
local MaxStammina = 100
local TickSpeed = 0.1
local PlayerStates = {
	["Crawling"] = {WalkSpeed = 10, JumpPowerMulti = .6, StamminaCost = -0.2, Animations = CrowchingAnimations, CameraOffset = Vector3.new(0,-1.5,0), FieldOfView = 70},
	["Walking"] = {WalkSpeed = 16, JumpPowerMulti = 1, StamminaCost = -0.1, Animations = WalkingAnimations, CameraOffset = Vector3.new(0,0,0), FieldOfView = 70},
	["Sprinting"] = {WalkSpeed = 22, JumpPowerMulti = .9, StamminaCost = .2, Animations = SprintingAnimations, CameraOffset = Vector3.new(0,0,0), FieldOfView = 80}
}

-- Setup --
local Stamina = MaxStammina -- Sets Stamina to Whaever MaxStamina is set to
local CurrentState = PlayerStates["Walking"] -- Makes the Player Start out Walking

-- Update Gui --
local function UpdateGui()
	Gui.TextLabel.Text = math.round(Stamina)
end

-- Check if Player can Sprint --
local function CanRun()
	return Stamina >= 0 and not Crawling and not Sprinting
end

-- Adjust Stammina --
local function AdjustStammina(Adjustment)

	-- Make Sure Stammina is Within the Range of 0-100
	if (Stamina - Adjustment) >= 1 and (Stamina - Adjustment) <= MaxStammina then
		return (Stamina - Adjustment)

		-- If Stamina would be greater than MaxStammina then set Stamina to MaxStammina --
	elseif (Stamina - Adjustment)	>= MaxStammina  then
		return MaxStammina

		-- If Stammina would be less than 0 then Set Stamina to 1 --
	elseif (Stamina - Adjustment) <= 1 then
		Sprinting = false
		return 1
	end

end

-- Transiton Animation --
local function TransitionAnimation(TransitionAnim)
	TransitionAnim:Play()
	task.wait(TransitionAnim.Length)
end

-- Play Animations --
local function PlayAnimation(Animations)
	if Humanoid.MoveDirection.Magnitude > 0 and not Transition then
		if not Animations.Walking.IsPlaying then Animations.Walking:Play() end
	else
		Animations.Walking:Stop()
	end	
end

-- Update Player Stats --
local function UpdatePlayer()

	-- Check Which State Player is in --
	if Sprinting then 
		CurrentState = PlayerStates["Sprinting"]
	elseif Crawling then 
		CurrentState = PlayerStates["Crawling"]
	else
		CurrentState = PlayerStates["Walking"]
	end

	-- Update Values --
	Humanoid.WalkSpeed = CurrentState.WalkSpeed
	Humanoid.JumpPower = (NormalJumpPower * CurrentState.JumpPowerMulti)
	Humanoid.UseJumpPower = true
	Stamina = AdjustStammina(CurrentState.StamminaCost)
	
	-- Upate Camera --
	TweenService:Create(Humanoid, TweenInfo.new(0.25,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut),{CameraOffset = CurrentState.CameraOffset}):Play()
	TweenService:Create(Camera, TweenInfo.new(0.25,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut),{FieldOfView = CurrentState.FieldOfView}):Play()
	
	-- Update Animations --
	if not Transition then PlayAnimation(CurrentState.Animations) end
	
	-- Update GUI --
	UpdateGui()
end

-- Main Function --
local function PlayerState(EventName, InputState, _InputObject)

	-- Check if the Event Fired was Called "ToggleSprint"
	if EventName == ToggleSprint and InputState == Enum.UserInputState.Begin then

		-- Make Sure Player Can Run --
		if CanRun() then
			Transition = true
			CurrentState.Animations.Walking:Stop()
			CurrentState.Animations.Idle:Stop()
			TransitionAnimation(CurrentState.Animations.TransitionC)
			Sprinting = true
			task.wait(0)
			CurrentState.Animations.Idle:Play()
			Transition = false
			
			-- Make Sure the Player can Walk --
		else if Sprinting or Crawling then
				if Crawling then
					Transition = true
					CurrentState.Animations.Walking:Stop()
					CurrentState.Animations.Idle:Stop()
					TransitionAnimation(CurrentState.Animations.TransitionC)
					Crawling = false
					task.wait(0)
					CurrentState.Animations.Idle:Play()
					Transition = false
				else
					Transition = true
					CurrentState.Animations.Walking:Stop()
					CurrentState.Animations.Idle:Stop()
					TransitionAnimation(CurrentState.Animations.Transition)
					Sprinting = false
					task.wait(0)
					CurrentState.Animations.Idle:Play()
					Transition = false
				end
			end
		end
	end

	-- Crawling Event --
	if EventName == ToggleCrawl and InputState == Enum.UserInputState.Begin then
		Sprinting = false
		if not Crawling then
			Transition = true
			CurrentState.Animations.Walking:Stop()
			CurrentState.Animations.Idle:Stop()
			TransitionAnimation(CurrentState.Animations.TransitionC)
			Crawling = true
			task.wait(0)
			CurrentState.Animations.Idle:Play()
			Transition = false
		else
			Transition = true
			CurrentState.Animations.Walking:Stop()
			CurrentState.Animations.Idle:Stop()
			TransitionAnimation(CurrentState.Animations.Transition)
			Crawling = false
			task.wait(0)
			CurrentState.Animations.Idle:Play()
			Transition = false
		end
	end
end

-- Events --
ContactActionService:BindAction(ToggleSprint, PlayerState, true, Enum.KeyCode.LeftShift)
ContactActionService:BindAction(ToggleCrawl, PlayerState, true, Enum.KeyCode.LeftControl)
RunService.Heartbeat:Connect(UpdatePlayer)

You should always be thinking whether you should optimize your script instead.

That being said, there are some obvious pickings here.

	-- Upate Camera --
	TweenService:Create(Humanoid, TweenInfo.new(0.25,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut),{CameraOffset = CurrentState.CameraOffset}):Play()
	TweenService:Create(Camera, TweenInfo.new(0.25,Enum.EasingStyle.Linear,Enum.EasingDirection.InOut),{FieldOfView = CurrentState.FieldOfView}):Play()

You are creating a tween every Heartbeat and they never get to finish before they are overwritten by another tween.
These tweens seem to be equivalent to lerping CameraOffset and FieldOfView every tick:

	-- Upate Camera --
	local alpha = 1 - 0.25^dt -- Change the function signature to UpdatePlayer(dt). Not sure about the math here, be sure to get someone to test with a fps unlocker and see if the feel doesn't change, also compare with just alpha=dt
	Humanoid.CameraOffset = Humanoid.CameraOffset:Lerp(CurrentState.CameraOffset, alpha)
	Camera.FieldOfView = Camera.FieldOfView:Lerp(CurrentState.FieldOfView, alpha)

The point of a Tween is to run hands-free after your code finishes, not this.

This is incredibly minor, but you don’t have to update Humanoid.UseJumpPower every tick.

In general, I think you ought to figure out the specific points when the state transitions and then change WalkSpeed, JumpPower, CurrentState etc. (i.e. perform a state transition) then, instead of checking the state name every tick.

If I remember correct you can do this, which returns as a boolean

Sprinting = not ((Stamina - Adjustment) <= 1)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.