Rule Editor

Rule editor is a custom function graph allowing you to determine what happens to sand each frame after movement has been calculated. To learn how you can create sand materials with the rule editor, checkout the Tutorial

basic rule

Above, you can see the rule for basic sand. It only takes the sand input, and passes it as an output. If you removed this connection, sand would always become empty.

Every time you modify the rule, it gets updated and should be visible in your sand behavior.

A more complex rule could do something like this:

  1. Read input sand (fire)
  2. With probability 0.1 (per this frame), turn sand to empty (using If node)
  3. With probability 0.1 (per this frame), turn sand to fire. When fire turns to fire, its velocity resets to 0.0, so some fire sand will live longer, some will die, some will turn to fire, but velocity reset.
  4. Pass new sand as output

This would look like:

fire initial

It takes a while to get used to the graph like programming, but with some practice it allows you to do pretty cool things like below. It's mostly a lot of trial and error.

slime mold

You are simply modifying sand's id, color and velocity. Most of the logic will be based on neighboring sand, physics, probabilities and time. These simple building blocks will allow you to create quite complex behavior.


Use function search to find what functions are available. You can right-click the background of the rule editor to open the search and click one to add a function node.

function search


You can move inside the editor with middle mouse and multi select nodes by drawing with left mouse. Ctrl + C/V works as well.

Copy Paste

You can import functions from other people by copying and pasting nodes. For example, pasting this following piece of text to your editor will add basic sand input node.

The copied nodes should take zoom into account and center to the graph area.

    node_data: {
            idx: 2,
            version: 1,
        ): ((
            id: (
                idx: 2,
                version: 1,
            label: "Input: Get Sand",
            inputs: [],
            outputs: [
                ("sand_out", (
                    idx: 1,
                    version: 1,
            user_data: (
                template: InputGetSand,
        ), (
            x: 0.0,
            y: 0.0,
        ), None),
    connections: [],
    zoom: 1.0,

Was this page helpful?