Help setting up a advanced input system

Hello, I am creating a fighting game and want to create an input system that can activate any abilities corresponding to the input. I’m trying to think of a good way to make this but I’m at a loss. I tried having a module store what input does what and keeping a move name, tied remotes, etc. But it seems that doesn’t work.

I also tried making a folder that holds modules for the combat but I don’t know how to continue that as well.
image

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local module = {
	
	["BasicCombat"] = {
		
		["Punch"] = {Input = Enum.UserInputType.MouseButton1, ReplicatedStorage:WaitForChild("Events"):WaitForChild("Combat"):WaitForChild("Default"):WaitForChild("Main")} --{Input, Remote}
		
	}
	
}

return module

If there is a better way I can approach this PLEASE let me know. Thanks in advanced

6 Likes

You don’t need to use :WaitForChild on instances that are visible in the Studio Explorer before the game is run! Those are guaranteed to exist before scripts are executed (because they are “static”, i.e. exist from the start of the game and aren’t created through a script).

What does InputHandler look like? I assume that is what you’re struggling with.

5 Likes

It’s empty again atm, but as a basic script for what it might look like. I made this just now because I’m not on studio but this is close of what I have. Keybinds module isn’t made and most of the script isn’t finished or made.

local UserInputService = game:GetService("UserInputService")

--Keybind module used to map what keybinds to what.
--EXAMPLE: MouseButton1 = {'move name', 'move module?'}
local Keybinds = require(module.for.keybinds) 

local InputRemote : RemoteEvent

local InputDetection = coroutine.create(function()
    UserInputService.InputBegan:Connect(function(input, GPE)
        if GPE then return end

       ... --main code

     Keybinds :FireServer(input)
    end)
end)
1 Like

Though mainly I just need help thinking of a way to make a reliable input system that can get inputs and call functions designed for those inputs

1 Like

You don’t need a coroutine for event connections like .InputBegan:Connect. Think of them less like loops and more like functions you’ve declared, they don’t block the rest of the script:

local function MyFunction()
    wait(5)
end

-- "Hi" is printed even though there is a "wait" in the function because we have not
-- called that function before printing "Hi"
print("Hi!")
-- Event connections are a little different though, it's sort of like speaking to someone
-- without caring about whether you're giving them enough time to understand your words between sentences.

You could have a for-loop that checks through the keybinds module for anything that has the same input like so:

-- I will assume that the module whose code you've given in the main post
-- is the one named "BasicCombat"
local Keybinds = require(script.Parent.Combat.BasicCombat)

UserInputService.InputBegan:Connect(function(Input, ShouldIgnore)
    -- Also called "GameProcessedEvent", "ShouldIgnore" will be `true` when the user
    -- is interacting with other things like a textbox, and we of course want to ignore that.
    if ShouldIgnore then
        return
    end
    
    for _, Keybind in Keybinds.BasicCombat do
        if Keybind.Input == Input.KeyCode or Keybind.Input == Input.UserInputType then
            -- The user has pressed a keybind with an associated RemoteEvent, fire it.
            -- You look like you've forgotten to give a name to the RemoteEvent
            -- in the dictionary, but I'll just write this assuming you've assigned it to "Remote".
            Keybind.Remote:FireServer()
        end
    end
end

I wasted a significant amount of time writing up a detailed explanation on dictionaries, only to realize you already knew what they were and had just written a typo. Whoops!

2 Likes

I’ll see what I can make with this, thanks for making this and sorry for wasting some of your time :sob:

1 Like

Would firing the server when specific inputs are activated hurt the server?

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local InputModule = require(ReplicatedStorage:WaitForChild("Libraries"):WaitForChild("Input"))
local Keybinds = require(script:WaitForChild("Keybinds"))

local InputRemote = ReplicatedStorage:WaitForChild("Events"):WaitForChild("Shared"):WaitForChild("Inputs"):WaitForChild("Inputs")

local plr = game:GetService("Players").LocalPlayer

UserInputService.InputBegan:Connect(function(Input : InputObject, GPE : boolean)
	if GPE then return end
	
	--Gives an input
	local PlayerInput = nil do
		--print(Input.UserInputType, Input.KeyCode)
		if Input.KeyCode == Enum.KeyCode.Unknown then
			PlayerInput = Input.UserInputType
			
		elseif Input.UserInputType == Enum.UserInputType.None or Input.UserInputType == Enum.UserInputType.Keyboard then
			PlayerInput = Input.KeyCode
		end
	end
	
	for Keys, _ in pairs(Keybinds) do
		if Keys == PlayerInput then
			print("MATCH")
			--InputRemote:FireServer(PlayerInput.Name, false)
		else continue
		end
	end
	
	local Move = Keybinds[Input]
	InputRemote:FireServer(PlayerInput.Name, true)
end)

UserInputService.InputEnded:Connect(function(Input : InputObject, GPE : boolean)
	if GPE then return end

	--Gives an input
	local PlayerInput = nil do
		--print(Input.UserInputType, Input.KeyCode)
		if Input.KeyCode == Enum.KeyCode.Unknown then
			PlayerInput = Input.UserInputType

		elseif Input.UserInputType == Enum.UserInputType.None or Input.UserInputType == Enum.UserInputType.Keyboard then
			PlayerInput = Input.KeyCode
		end
	end
	
	for Keys, _ in pairs(Keybinds) do
		if Keys == PlayerInput then
			print("END")
			--InputRemote:FireServer(PlayerInput.Name, false)
		else continue
		end
	end
end)
1 Like

If you are able to give more information on what type of Framework you are look for it would allow us to further help you. (Classes, Different Combat Types, Tools, etc.)

Combat framework
this is to get the character limit

Combat like Blox Fruit’s or something of that sort?

1 Like

Not always :flushed: (replicatedFirst)

2 Likes

If you are worried about using up network resources, for this case you shouldn’t be. It’s only when you start firing several remote events many times a second per player.

But personally, I would recommend the keybinds be connected to functions instead of remote events, because those function could handle extra visual effects and reduce “input delay” and then also fire a remote event to tell the server to actually perform the combat action.

1 Like

The inputs basically hold a boolean that the server changes, when true, the player is holding that key, else its false.

local Module = {}
--This is for demonstration:
local isHolding : boolean
Module[plr][Input] = isHolding 

Made a template I can go off that helped me make the rest of the input system, thanks for the help all.

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