14

I found 11 questions like this on gamingSE already, but none of them have proper and up-to-date answers. So I'm creating this Q&A:

How do you either activate a command x ticks/seconds/minutes/hours/… in the future or every x ticks/seconds/minutes/… in a loop?

Repeating command blocks and ticking functions execute 20 times per second, redstone is not a good solution in many situations and most of the extremely fancy solutions, like falling blocks in cobwebs, have broken over time or are needlessly complicated.

3
  • 1
    Why is redstone not a good solution in many situations?
    – John
    Commented Feb 6, 2020 at 20:36
  • @John Good question. I've added a link to the answer to my post. Commented Feb 7, 2020 at 11:05
  • Actually, it does a somewhat bad job of stating why it's evil in the first place. I'll add an answer there one day. For now, in short: Lag, slower, might be tampered with, unsafe (water etc.), chunk loading, bugs, less features (like execution context), … All of those are issues you get with redstone. Commented Feb 7, 2020 at 11:09

2 Answers 2

12

For functions there is a built-in way to do this:

/schedule function <function_name> <time>

So if you for example want to execute the function named "test" in the namespace "abc" in 1 hour, which equals 3 in-game days, you can use any of these commands:

/schedule function abc:test 3d
/schedule function abc:test 3600s
/schedule function abc:test 72000t
/schedule function abc:test 72000
/schedule function abc:test 3d replace
…

Unit postfixes for minutes, hours etc. do not exist. The in-game days unit is not affected by sleeping or /time.

If you have changed your mind, you can abort a scheduled function execution like this:

/schedule clear abc:test

If you want to schedule multiple executions, you can use append instead of replace. If you want to replace all existing schedules of this function with the current one, you can use replace or just provide no mode at all, replace is the default.

To loop execution, you can simply use the /schedule command at the end of your function. Usually you'll want to do this under some condition, so that it doesn't keep looping forever.


If you cannot or do not want to use functions or /schedule, you can still use the old scoreboard timer method. This needs a little bit more resources, because it actively does something every tick, but it shouldn't cause noticeable lag.

As a preparation, you need a scoreboard:

/scoreboard objectives add timer dummy

The "dummy" type is one that is not affected by anything except commands.

In a repeating command block or ticked function, execute this command:

scoreboard players add $timer timer 1

The name "$timer" cannot possibly be a real player name, so it is a good choice for a dummy player name. If you do not want it to show up in a scoreboard sidebar display, start the name with a # character.

Now you can do something once the timer reaches your desired number of ticks like this:

execute if score $timer timer matches 100 run say 5 seconds are over!

If you want to do something repeatedly after 5 seconds, simply replace 100 with 100... If you want a variable starting time, compared to someone else's score, you can for example use >= @p points instead of matches 100.

If you want to repeat something every x seconds/minutes/…, you can just reset the timer after you have done whatever you want to do with it. So at the end of your command block chain or ticked function, you put this:

execute if score $timer timer matches 100 run scoreboard players set $timer timer 0

This concept can also be used to do something every x times something happens. To do this, simply increase the timer only conditionally instead of every tick, for example like this:

execute if block ~ ~1 ~ stone run scoreboard players add $timer timer 1

But make sure to change whatever the command is checking for directly afterwards, otherwise it keeps ticking up by 1 every tick as long as the condition is matched.

3
  • 1
    If you want to make your delay longer than 4294967296 ticks (almost 7 years) for some reason, you either need to make a more complex command setup, like ticking up a second timer every time the first one resets, or, for the most extreme case, use a universe death clock. SethBling also has some fun compact timers that last a REALLY long time here and here. Commented Feb 4, 2020 at 10:29
  • 1
    You could make a mini-game out of this - set a timer to limit the length of your world. Once you reach that timer, you are killed indefinitely, making the game unplayable.
    – Ben
    Commented Feb 5, 2020 at 0:17
  • You can do literally everything with this that requires timers or delays. Commented Feb 5, 2020 at 23:12
2

Area Effect Cloud method

If you are unwilling to set up a scoreboard because you think excess scoreboards are a waste of space, a better method would be the Area Effect Cloud method.

Note that this does not work for functions. Functions should use /schedule to schedule another function.

Area effect clouds (AECs) have a Duration tag and an Age tag. Their Age will increase at a rate of 1 per tick. When its Age gets to its Duration, the AEC will disappear.

The following command will summon an AEC that disappears in 100 ticks (5 seconds), because an unspecified Duration defaults to 0:

summon minecraft:area_effect_cloud ~ ~ ~ {Age:-100,Particle:"take",Tags:["delay"]} 

So now that we can make an AEC that hangs around, how can we make it execute something after the delay is over?

The best way to do this is to detect when the AEC is about to expire, and make it activate a command block. We can choose to summon the AEC inside the command block we want it to activate, and then when it is about to expire, flick its auto tag to 1b, setting it to Always Active, and then flick it back to 0b. The following commands will do just that:

tag @e[type=area_effect_cloud,tag=delay,nbt={Age:0}] add delayActivating
execute at @e[type=area_effect_cloud,tag=delayActivating] run data merge block ~ ~ ~ {auto:1b}
execute at @e[type=area_effect_cloud,tag=delayActivating] run data merge block ~ ~ ~ {auto:0b}

That's the implementation of the system that makes it work. Then, to initiate a delay, use this command:

summon area_effect_cloud _________ {Age:-_____,Particle:"take",Tags:["delay"]}

Along with the other commands, this command will work to start a delay. This basically will activate the command block at the position you set, after a delay of however many ticks you set.

2
  • The first "tag=delayActivating" should be a =!, right? Anyway, the only possible advantage of this seems to be to have one less scoreboard in autocomplete, but at the cost of another entity in the world. Commented Mar 18, 2021 at 14:01
  • Oh yeah, that makes the system reusable, in contrast to what I originally thought you were trying to do. Commented Mar 18, 2021 at 21:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.