How to run the same function that is already running?

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

  1. What do you want to achieve? Run the same function that’s already running.

  2. What is the issue? I’ve tested it many times, but it just waits for the current running function before running the same function.

  3. What solutions have you tried so far? I’ve looked all around dev forums and YT videos, but my answer cannot be solved.

Here’s an example:

When pressing “A” on your keyboard, it runs a function. When clicking “B” it runs the same function as function “A”. I want to press “A” and “B” at the same time like a function for each without writing down 2 functions. Is this possible?

1 Like

Not completely sure what you mean by this, but from what you said I think what you are looking for is information on recursive functions. Here is a link to a good explaination on them.

1 Like

This is partially what I mean, but what if there was a wait inside the function that delays?

Try creating a variable and set the variable at the start and end, and when calling the function, use a conditional statement based on that variable.

I’m confused, can you show an example?

In your example, it wouldn’t matter since keybindings in Roblox use event:Connect and similar methods of registering to handlers, which means that it already can run the function asynchronously. However, if you want to do this with your own functions, you have spawn, delay, and coroutines.

spawn and delay are effectively the same.
spawn(thisfunction) will run thisfunction at effectively the same time as what comes after the spawn function.
Delay does the same
delay(thisfunction, 10) except that it runs thisfunction ten seconds later.

Coroutines are a little more complicated (though you have better control and they are more reliable) and the simplest way is like this.
coroutine.wrap(thisfunction)()

1 Like

The problem is that it takes up a lot of code. Is there any simple solution?

It might not be the best solution, but it’s the easiest one.

local allow_foo = true
local function foo()
	if allow_foo then
		allow_foo = false
		-- do this
		allow_foo = true
	end
end

Oh, I misunderstood.

This is accomplished best with arguments, but not everything can be simplified.

local speed = 100
local function doStuff(ab)
    if ab == "a" then speed += 10
    elseif ab == "b" then speed -= 10
    end
    updateSpeed()
end

So in this case, you are reusing updateSpeed, though this is such a simple function that it can’t really get shorter.

1 Like

I’m confused, it didn’t work out really but I understand if you don’t get it. Here’s a line of code that I revamped from @ThatToothyDear.

local allow_foo = true
local function foo()
	if allow_foo then
		allow_foo = false
		wait(10)
		print("Foo")
		allow_foo = true
	end
end

foo()
foo()

It doesn’t print both “Foo”'s instantly.

That’s better, but the wait doesn’t need to last for 10 seconds, best between 0.1 to 0.5.

I don’t think you get it. We need the 10 there. It is a necessity of the function, but we can’t run the same function simultaneously.

I understand, but I think it should be at least shorter because if the function is used for a common behavior in the game, the player might get annoyed that they have to wait for 10 seconds before they can use it again.

1 Like

Maybe try corountines? You can have waits that last as long as you want, and they won’t yield the script. They will run on their own.

coroutine.wrap() could help, as it is a function that happens when called without yielding the script. This would allow you to run the function twice AND still wait the 10 seconds.

1 Like

I tried that, but what if I kept on calling that coroutine? How would I able to make it so it doesn’t die?

Im not too experienced with coroutines, and I still don’t know how to stop them from dying… :confused:

But, you could do something like this, which just makes a new coroutine each time.

function onInput()
   coroutine.wrap(function()
          -- run the code here
   end)
end

If you are relying on player input or something…

function inputBegan(input)
       if input.KeyCode == Enum.KeyCode.key -- key would be whatever the input is.
             coroutine.wrap(function()
                     -- do something here
                     wait(10) -- or whatever wait you wanted
                     -- do something after the wait()
             end)
      end
end
2 Likes

@Cu_rrency & @synical4, while I am not experienced in coroutines, the official guide on Lua features a chapter to coroutines. You can read it online here: Programming in Lua : 9. There’s also a Wikipedia article on coroutines in general.

1 Like

Also, as stated earlier, you could also have the function written somewhere else in the script.
If you do write the function elsewhere, you could simply do:

function doSomething()
   print("Hello!")
   -- do something else
end

function onInput(input)
   if input == whatever then
      coroutine.wrap(doSomething)
   end
end
1 Like

I believe you are looking for this: Threading Code spawn() allows a function to fire on a different thread, without yielding the current one, meaning two of the same function can run at once. It’s usually used for while loops, but I believe it will help you in this case. Here’s an example:

function Example()
print("Hello!")
wait(10)
print("Hello Again!")

end

spawn(Example) --Both
spawn(Example) --Should Fire
2 Likes

There shouldn’t need to be a wait in here if you use events instead. Here is some quick code I whipped up that should solve your problem (sorry in advance if I made any mistakes):

local contextActionService = game:GetService("ContextActionService")
local aButton, bButton= "A", "B"
local aButtonPressed, bButtonPressed= false, false

local function doYourKeyCombination()
	--This will run only when "AB" is pressed!
	aButtonPressed = false -->These two are needed to reset the combination
	bButtonPressed = false
end

local function orMaybeThisIsWhatYouMean()
	--This will run if "A", "B" or "AB" is pressed!
end

local function InputBegan(actionName, inputState, inputObject)
	if actionName == "A" then
		if inputState == Enum.UserInputState.Begin then
			if bButtonPressed then
				local co = coroutine.wrap(function()
					doYourKeyCombination()
					orMaybeThisIsWhatYouMean()
				end)
				co()
			else
				aButtonPressed = true
				orMaybeThisIsWhatYouMean()
			end
		else
			aButtonPressed = false
		end
	elseif actionName == "B" then
		if inputState == Enum.UserInputState.Begin then
			if aButtonPressed then
				local co = coroutine.wrap(function()
					doYourKeyCombination()
					orMaybeThisIsWhatYouMean()
				end)
				co()
			else
				bButtonPressed = true
				orMaybeThisIsWhatYouMean()
			end
		else
			bButtonPressed = false
		end
	end
end

contextActionService:BindAction(aButton, InputBegan, false, Enum.KeyCode.A)
contextActionService:BindAction(bButton, InputBegan, false, Enum.KeyCode.B)

I wasn’t fully sure exactly what you wanted, so I just threw in the different combinations as a bonus :stuck_out_tongue:.

2 Likes