Requirements and the correct folder
A Bedrock function is a plain text file containing commands, one command per line. It uses the .mcfunction extension and lives in the Behavior Pack functions folder at the same level as manifest.json. The current Microsoft pack contents reference uses the plural folder name functions.
You need a valid Behavior Pack and a test world with the pack active. Running commands manually also requires the appropriate permissions and cheats in the world. Use a code editor that preserves plain UTF-8 text. A file named setup.mcfunction.txt will not load, so enable file extensions on Windows.
Functions group commands; they do not add JavaScript variables or asynchronous control flow. Use scoreboards, tags, entities, and command conditions for command-driven state. Use the Script API when the logic needs event subscriptions, data structures, or programmatic behavior that becomes awkward in commands.
Create and run your first function
Create functions/icedfox/setup.mcfunction. Commands inside the file do not start with a slash. Blank lines are fine, and comments begin with a hash character.
# Initial setup for the pack
scoreboard objectives add ifx_state dummy
scoreboard players set global ifx_state 1
say Iced Fox function loadedActivate the Behavior Pack, enter the world, and run /function icedfox/setup. The path is relative to the functions folder and omits the extension. If Minecraft reports an unknown function, verify pack activation, folder spelling, file extension, path case, and the Content Log.
Keep the first test simple. A say command proves discovery, but it does not prove later selectors or coordinates are correct. Add commands incrementally and run the same function after each change.
Organize nested functions as the pack grows
Subfolders prevent one directory from becoming a list of unrelated files. A practical structure might include setup, player, combat, world, and internal. Prefix everything with your project namespace folder to reduce collisions with another pack.
functions/
icedfox/
setup.mcfunction
player/
join.mcfunction
reset.mcfunction
combat/
reward.mcfunction
tick/
main.mcfunction
one_second.mcfunction
tick.jsonA function can call another with the function command. Keep the call graph shallow and avoid cycles. Name functions by action: player/reset is clearer than stuff2. A dedicated internal folder signals that other packs or map makers should not call those files as a public interface.
Document scoreboards and tags in a project README. Names have practical limits and may share global world state with other content, so use a short unique prefix such as ifx_.
Understand who and where executes a function
Commands inside a function inherit execution context from the command that called it. A function run in chat by a player can have a different executor and position from one called by a scheduled system or another execute chain. Never assume @s means a player unless you control the caller.
execute as @a[tag=ifx_active] at @s run function icedfox/player/updateInside player/update.mcfunction, @s is now each selected player and relative coordinates are based at that player because the call used both as and at. Without at @s, the executor changes but the execution position may not.
Use selectors that are as narrow as possible. A command over all entities every tick is expensive and can affect content from other packs. Tags, type filters, distance, family, and score ranges reduce work and clarify intent.
Use tick.json without creating a permanent performance problem
A tick.json file can register functions that run repeatedly. This is powerful and easy to misuse. Keep the registered function tiny: update a counter or dispatch to less frequent work. Do not scan the whole world or run hundreds of commands for every player on every tick.
{
"values": [
"icedfox/tick/main"
]
}scoreboard players add timer ifx_state 1
execute if score timer ifx_state matches 20.. run function icedfox/tick/one_second
execute if score timer ifx_state matches 20.. run scoreboard players set timer ifx_state 0The example dispatches roughly once per second under normal tick rate. It is not a real-time clock when the game lags, but it prevents the heavier function from running every tick. For longer schedules, scoreboards or Script API scheduling can be easier to maintain.
Microsoft documents a command limit for a single function call. Treat that as an upper guardrail, not a target. Large bursts can freeze a device long before reaching a formal maximum, especially when nested functions multiply selectors.
Reusable patterns for reliable functions
One-time initialization
Use a sentinel score or tag before adding objectives and world state repeatedly. Keep setup idempotent where commands allow it, and separate migration logic when a new pack version changes stored state.
Dispatch by state
Use execute if score to call small functions for a state instead of putting every branch in one file. This makes each path testable and keeps selector context obvious.
Clean temporary state
Tags and scoreboard values used during one operation should be reset. Temporary entities need a clear lifetime. Forgotten state causes behavior that appears random after long play sessions.
Use functions as interfaces
Expose a few stable entry functions such as setup, start, stop, and reset. Internal layout can then change without breaking command blocks or other content that calls the pack.
Debug a function that does not run
- Run a simple known function and verify the Behavior Pack is active.
- Confirm the file is plain text with the real
.mcfunctionextension. - Check the plural
functionsfolder and exact nested path. - Put a temporary
sayline before the suspected command. - Run the failing command manually with the same executor and position.
- Read the Content Log for syntax or unknown-command messages.
- Reduce selectors and call one nested function at a time.
If the first line runs and a later line does not, the function was discovered; debug syntax or context. If no line runs, focus on pack, path, extension, and registration. If a tick function fails, call it manually before debugging tick.json.
Performance and release checklist
- Keep every-tick work small and dispatch slower tasks.
- Filter selectors and avoid repeated full-world scans.
- Prevent recursive or circular function calls.
- Prefix objectives and tags to avoid collisions.
- Test with multiple players, many entities, and lower-end devices.
- Remove debug chat messages before release.
- Document entry functions and stored state.
- Test a clean imported pack, not only development folders.
Functions are excellent for readable command systems when their execution context and frequency remain explicit. When the design needs complex events or data, move that part to Script API instead of turning one tick function into an application.
Official sources checked
Primary references used to verify this tutorial:
- Microsoft Learn - Introduction to Functions
- Microsoft Learn - /function Command
- Microsoft Learn - Introduction to Commands
- Microsoft Learn - Comprehensive List of Pack Contents