SkillAgentSearch skills...

RRCG

C# to CV2 Graph Compiler

Install / Use

/learn @notrabs/RRCG
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

RRCG - Rec Room Circuit Generator

What if you never had to move a wire by hand? RRCG brings text-based scripting support to Rec Room's visual scripting language CV2.

example-circuit

| :warning: WARNING | | --- | | Consider upvoting this feature request: https://recroom.featureupvote.com/suggestions/482338/circuits-api <br /> This package only contains the compiler frontend to validate the graph generation. Wihout a proper Circuits API the conversion into actual graphs is to unstable to release. |

<!-- toc -->
  1. Install
  2. Using the Compiler
  3. Writing Code
  4. Troubleshooting
  5. Feature Matrix

Install

RRCG comes as a Unity package to be installed in your Rec Room Studio project.

Using the Package Manager install a package from this Git URL: https://github.com/notrabs/RRCG.git

<details> <summary> How to Update </summary>

Occasionally an update might include breaking changes, most likely if chips get changed or the compiler internals are changed. This can invalidate RRCG's generated files. To safely update, please follow these steps:

  1. Make sure Unity is open before you update
  2. Update using the Package Manager (or git)
  3. If you get errors in generated files => Use "Clean All" in the window menu
  4. If you get errors in source files => Resolve them manually (e.g. adjust to chip changes)
  5. Hit "Recompile All" to make sure your files are compiled with the latest compiler
</details> <details> <summary> For development </summary>

Clone the repository into the "Packages" folder of your Studio project.

e.g. as a submodule: git submodule add https://github.com/notrabs/RRCG.git Packages/RRCG

</details>

Using the Compiler

  1. Create a prefab from the RRCG window menu. Place it in a location with enough space. The chip area will grow as indicated by the arrows.
  2. Open the Inspector for the RRCG prefab
  3. Select a CircuitDescriptor (or use the example)
  4. Click Build Circuit (placeholder for now. Until we have a Circuits API you can only create the debug DOT Graph)
<details> <summary> RRCG script files </summary>

RRCG compiles every file in your project with a .rrcg.cs extension. Any CircuitDescriptor class that was successfully compiled by RRCG will be available to select in the RRCG inspector. See the next chapter for how to write valid code.

You can get started with this example file that is configured by default when you spawn the prefab.

</details> <details> <summary> Standalone Projects </summary>

RRCG offers an advanced standalone compiler to speed up your iteration cycles. It bypasses Unity's dreadingly slow Assembly Reload, without sacrificing any major benefits that come from being integrated into Unity. The main difference in development is where the script files are located. Instead of in the Assets folder, your circuit scripts are placed inside an RRCG folder in the project root. The syntax and your access to Unity data stays the same.

Technically this is achieved by dynamically compiling and loading each iteration of your code. This works for RRCG (and not regular Unity Editor code), because RRCG code contains no side-effects beyond the compilation process.

The main limitation for now is that there is no mechanism for dependencies between standalone projects yet, but you can still reference any assembly compiled within your regular Assets. So the compromise for now is that shared RRCG code needs to stay within the slow Unity compiler.

To get started using standalone projects:

  1. Open the Inspector for your RRCG prefab
  2. Select the "Standalone Project" option
  3. Create a new project (or select an existing one)
  4. Wait for the initial compilation
  5. Select a Descriptor from the project (the project generates with a standard one)
  6. Open the RRCG_Project.sln in the RRCG folder of your Project root

After that, you can build circuits like with the integrated workflow, just without waiting. Subsequent builds within a session should also see additional speed ups thanks to caching mechanisms.

</details> <details> <summary> Watch Mode </summary>

With watch mode on all .rrcg.cs files in your project are compiled automatically when Unity imports them. This also happens every time you make a change to a script file. There's no downside to leaving it watch mode on, but the option to disable it is there if you want to disable automatic compilation during development.

In case you want to manually recompile a file you can use Unity's reimport functionality or use the "Recompile all" feature from the RRCG window menu. This should only be needed after you downloaded a new compiler version or during compiler development.

</details> <details> <summary> DOT Graph </summary>

DOT is a standard graph format that can be visualized online. You can copy a DOT graph for a compiled circuit by pressing the button in the inspector.

</details>

Writing Code

The goal of this language is to be an intuitive, direct mapping of C# to Circuits. With the C# execution flow being mapped to exec lines and data flow being mapped to data lines. C# Language features should do what you expect.

The Circuit Descriptor

The Circuit Descriptor is your entry point. Your chips start building from the CircuitGraph() method, but beyond that you can organize your code however you like. Place it inside a .rrcg.cs file anywhere in your project.

using RRCGSource;

public class ExampleRoom : CircuitDescriptor
{
    public override void CircuitGraph()
    {
        // Your circuits go here
    }
}
<details> <summary> Circuit Libraries </summary>

If you want to create reusable logic without an entry point, extend the CircuitLibrary class instead. This will also hide the class in the Circuit Selection menu. Place it inside a .rrcg.cs file anywhere in your project.

using RRCGSource;

public class ExampleLibrary : CircuitLibrary
{
    // Your circuits go here.
    // You can use it as a normal class or with static methods.
}
</details> <details> <summary> Additional Entry Points </summary>

A room is usually made up of multiple graphs. You can create separate graphs within a function by using exec chips with no exec inputs, or the StartNewGraph() method. But for code organization it is often nicer to have them as separate methods. Use the [CircuitGraph] attribute to mark functions in your CircuitDescriptor as additional entry points. Note that they must be parameterless functions to work.

public class ExampleRoom : CircuitDescriptor
{
    public override void CircuitGraph()
    {
        // Your 1st graph goes here

        EventReceiver(); // implicitly creates a new graph, because receivers have no exec input.

        // Your 2nd graph goes here

        StartNewGraph(); // explicitly creates a new graph.

        // Your 3rd graph goes here
    }

    [CircuitGraph]
    void Foo()
    {
        // Your 4th graph goes here
    }
}

Sometimes you need an exec chip, without connecting it to your exisiting execution flow. You could place it in a separate graph and reference to it with variables, but that quickly gets very verbose. Instead use the InlineGraph() helper to create new graphs without destryoing your current context.

public class ExampleRoom : CircuitDescriptor
{
    EventDefinition<string> onInput = new EventDefinition<string>();

    public override void CircuitGraph()
    {
        ChipLib.Log("Start");

        // Placing a receiver would normally create a new graph. This only extracts its data.
        var input = InlineGraph(() => onInput.Receiver());

        // This log chip will be connected to the previous log chip, but get the data from the event receiver.
        ChipLib.Log(input);
    }
}
</details>

Placing Chips

Chips are available as static functions in the Chips class. For convenience you can access them through the extended CircuitDescriptor class.

public void ExampleCircuit()
{
    Chips.RandomInt(1,10);
    // or
    RandomInt(1,10);
}

In addition to placing chips explicitly, you can also use the shorthands provided in the classes of RR types.

public void ExampleCircuit()
{
    SetPosition(GetLocalPlayer(), new Vector3(1,2,3));
    // or
    GetLocalPlayer().Position = new Vector3(1,2,3);
}

Data flow

Ports are data. Data is Ports. Don't worry what the type system might say. Write code as you usually would. RRCG will create and connect chips when necessary to execute operations.

public void ExampleCircuit()
{
    int rand1 = RandomInt(0, 10);
    var rand2 = RandomInt(0, rand1);

    if (rand1 + rand2 > 10) LogString("Today's your lucky day");
    else LogString("Try again next time");
}

If a chip has multiple outputs, a tuple will be returned

public void ExampleCircuit()
{
    // The underscore is handy to discard unwanted values
    var (parsed, _) = ParseFloat("1.0");

    // You can also access the named fields of the tuple to quickly get single values
    var value = ParseFloat("1.0").Parsed;
}

Exec flow

Functions are invisible. By default the execution flow follows the first pin. If a Chip has no exec input, it automatically starts a new graph.

public void ExampleCircuit()
{
    // starts a new graph
    RoomEvent.Hz30();

    // connects the random chip inside the function directly to the event receiver
    var rand1 = MyFunction();
    LogString(ToString(rand1));

    // starts a new graph
    RoomEvent.Hz30();
    LogString("1");
}

public void MyFunction()
{
    retu

Related Skills

View on GitHub
GitHub Stars12
CategoryDevelopment
Updated7d ago
Forks2

Languages

C#

Security Score

95/100

Audited on Mar 31, 2026

No findings