Looking for script optimization and help

I’m trying to make a puzzle game where the keys in your keyboard are switched out for other keys, so I had written some code for the switching keys part.
robloxapp-20230905-2130053.wmv (1.2 MB)

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer

function switchKeyStartW(key)
	UserInputService.InputBegan:Connect(function(input, gameProcessed)
		if input.KeyCode == key then
			if input.UserInputType == Enum.UserInputType.Keyboard then
				print("A key is being pushed down! Key:", input.KeyCode)
			RunService:BindToRenderStep("move", Enum.RenderPriority.Character.Value + 1, function()
				if player.Character then
					local humanoid = player.Character:FindFirstChild("Humanoid")
					if humanoid then
						humanoid:Move(Vector3.new(0, 0, -1), true)
					end
				end
			end)
			end
		end
	end)
end

function switchKeyStartD(key)
	UserInputService.InputBegan:Connect(function(input, gameProcessed)
		if input.KeyCode == key then
			if input.UserInputType == Enum.UserInputType.Keyboard then
				print("A key is being pushed down! Key:", input.KeyCode)
				RunService:BindToRenderStep("move", Enum.RenderPriority.Character.Value + 1, function()
					if player.Character then
						local humanoid = player.Character:FindFirstChild("Humanoid")
						if humanoid then
							humanoid:Move(Vector3.new(1, 0, 0), true)
						end
					end
				end)
			end
		end
	end)
end

function switchKeyEnd(key)
	UserInputService.InputEnded:Connect(function(input, gameProcessed)
		if input.KeyCode == key then
			if input.UserInputType == Enum.UserInputType.Keyboard then
				print("A key is being pushed down! Key:", input.KeyCode)
				RunService:BindToRenderStep("move", Enum.RenderPriority.Character.Value + 1, function()
					if player.Character then
						local humanoid = player.Character:FindFirstChild("Humanoid")
						if humanoid then
							humanoid:Move(Vector3.new(0, 0, 0), true)
						end
					end
				end)
			end
		end
	end)
end

UserInputService.InputBegan:Connect(switchKeyStartW(Enum.KeyCode.E))
UserInputService.InputEnded:Connect(switchKeyEnd(Enum.KeyCode.E))
UserInputService.InputBegan:Connect(switchKeyStartD(Enum.KeyCode.Q))
UserInputService.InputEnded:Connect(switchKeyEnd(Enum.KeyCode.Q))

[I did only E-W and D-Q]
However, the script happens to be quite long and it doesn’t even seem to work properly. I can’t move diagonally and my character often stops when i press the keys in quick succession. Any help regarding this would be much appreciated. (i will probably respond late)

I have 3 main optimisations for you, which will surely cut down the size of that script. If you don’t understand anything, don’t hesitate to ask. It also fixes the issues you had with your old script.

First, you could start by removing the multiple connections by only making one or two which is affected by a variable, or in this case a dictionary. For example:

local keybinds = {
	["Up"] = Enum.KeyCode.W,
	["Left"] = Enum.KeyCode.A,
	["Down"] = Enum.KeyCode.S,
	["Right"] = Enum.KeyCode.D
}

Next, you could cut down on the humanoid move calls by making 3 variables now, and using them in a loop later. This also will tie in with the last optimisation, which is to reduce the amount of functions used.

local movementX, movementZ = 0, 0

You can disregard the movementY variable because you can’t move upwards (unless you want to, which it won’t work)

If you apply all of this to your script, you will end up with something like this:

local keybinds = {
	["Up"] = Enum.KeyCode.W,
	["Left"] = Enum.KeyCode.A,
	["Down"] = Enum.KeyCode.S,
	["Right"] = Enum.KeyCode.D
}

local movementX, movementZ = 0, 0

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer

function handleAddKeys(inp, gpe)
	if inp.KeyCode == keybinds.Up then
		movementZ = -1
	elseif inp.KeyCode == keybinds.Down then
		movementZ = 1
	elseif inp.KeyCode == keybinds.Left then
		movementX = -1
	elseif inp.KeyCode == keybinds.Right then
		movementX = 1
	end
end

function handleDelKeys(inp, gpe)
	if inp.KeyCode == keybinds.Up then
		movementZ = 0
	elseif inp.KeyCode == keybinds.Down then
		movementZ = 0
	elseif inp.KeyCode == keybinds.Left then
		movementX = 0
	elseif inp.KeyCode == keybinds.Right then
		movementX = 0
	end
end

UserInputService.InputBegan:Connect(handleAddKeys)
UserInputService.InputEnded:Connect(handleDelKeys)

RunService:BindToRenderStep("move", Enum.RenderPriority.Character.Value + 1, function()
	if player.Character then
		local humanoid = player.Character:FindFirstChild("Humanoid")
		if humanoid then
			humanoid:Move(Vector3.new(movementX, 0, movementZ), true)
		end
	end
end)

this is 14 lines shorter than your script.
(This code should theoretically fix your diagonal movement, as it is changing its own variable which is being applied to the character.)

Please let me know if this helped, and remember you need to disable movement (and not with walk speed) for this to properly work. (which I’m assuming you’re already done)

edit - fixed formatting

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer

-- Keep track of which keys are currently being pressed
local keysPressed = {}

-- Handle key presses
UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if input.UserInputType == Enum.UserInputType.Keyboard then
        -- Map the pressed key to the corresponding movement key
        local movementKey
        if input.KeyCode == Enum.KeyCode.E then
            movementKey = Enum.KeyCode.W
        elseif input.KeyCode == Enum.KeyCode.Q then
            movementKey = Enum.KeyCode.D
        else
            movementKey = input.KeyCode
        end

        -- Mark the movement key as being pressed
        keysPressed[movementKey] = true
    end
end)

-- Handle key releases
UserInputService.InputEnded:Connect(function(input, gameProcessed)
    if input.UserInputType == Enum.UserInputType.Keyboard then
        -- Map the released key to the corresponding movement key
        local movementKey
        if input.KeyCode == Enum.KeyCode.E then
            movementKey = Enum.KeyCode.W
        elseif input.KeyCode == Enum.KeyCode.Q then
            movementKey = Enum.KeyCode.D
        else
            movementKey = input.KeyCode
        end

        -- Mark the movement key as being released
        keysPressed[movementKey] = false
    end
end)

-- Handle character movement
RunService:BindToRenderStep("move", Enum.RenderPriority.Character.Value + 1, function()
    if player.Character then
        local humanoid = player.Character:FindFirstChild("Humanoid")
        if humanoid then
            -- Calculate the movement direction based on which keys are currently being pressed
            local moveDirection = Vector3.new(0, 0, 0)
            if keysPressed[Enum.KeyCode.W] then moveDirection = moveDirection + Vector3.new(0, 0, -1) end
            if keysPressed[Enum.KeyCode.A] then moveDirection = moveDirection + Vector3.new(-1, 0, 0) end
            if keysPressed[Enum.KeyCode.S] then moveDirection = moveDirection + Vector3.new(0, 0, 1) end
            if keysPressed[Enum.KeyCode.D] then moveDirection = moveDirection + Vector3.new(1, 0, 0) end

            -- Move the character in the calculated direction
            humanoid:Move(moveDirection, true)
        end
    end
end)

I couldn’t thank you more for this. It works perfectly fine!

1 Like

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