# Shared rules library

> Share rule logic between your client and your CloudBehaviour by putting it in a shared assembly.

> **Important:**
>
> This page describes an experimental feature that might change significantly before release. It's not recommended to use or rely on experimental features in production environments due to potential instability.

When the [sync-metadata approach](/cloud-code/cloudbehaviours/sharing-game-rules/sync-metadata-approach.md) stops scaling, share your rule logic directly instead of re-implementing it on both sides. Put the shared logic in its own assembly, and reference that assembly from both your client assembly and your CloudBehaviour's cloud assembly. On deploy, the build bundles the shared assembly into your Cloud Code module automatically, so you write the rule once.

Unlike a model type that crosses the client boundary through the generated bindings, which only ever carries data, a type in a shared assembly keeps its full behavior on both sides, because the client references the real assembly directly instead of a generated stub.

## Set up a shared rules library

To set up a shared rules library:

1. Create a new assembly definition for your shared code, separate from your cloud and client assemblies.
2. Set `noEngineReferences` to `true` on the shared assembly. This setting is required. The cloud assembly can't reference `UnityEngine` types, so the shared assembly can't either. If a type from an assembly that references the Unity engine or Editor crosses the client boundary, the build fails with `CCSG130`.
3. Add the shared assembly to the **references** list of both your cloud assembly and your client assembly.
4. Put your shared rule logic and data types in the shared assembly, using plain C#.

After you add the shared assembly to both references lists, your cloud and client code can reference the same types directly. The following example shows a shared assembly definition and a shared type:

```json title="Shared assembly definition"
{
    "name": "MyGameShared",
    "noEngineReferences": true
}
```

The following shared type carries a real method, not just data, because both your cloud and client assemblies reference it directly:

```csharp title="Shared/MoveResult.cs"
namespace MyGame.Shared
{
    public class MoveResult
    {
        public bool WasLegal;
        public int Column;

        public string Describe() => WasLegal ? $"Placed at column {Column}" : "Move rejected";
    }
}
```

Both your cloud class and your client code can now call `Describe()`, and they run the same source code instead of two separate implementations. Results are identical as long as the code doesn't depend on the runtime it runs in, such as culture settings or floating-point behavior.

## Known limitations

This pattern has been tested in the Unity Editor only. Test your player builds before you rely on it in a shipping game.

When you deploy, your shared assembly and everything it references are bundled into your module, the same way as your cloud assembly's own references. To bundle a precompiled DLL, enable **Override References** on the shared assembly and add the DLL to its **Assembly References** list. DLLs that Unity references automatically aren't bundled.

## Additional resources

* [Sharing game rules](/cloud-code/cloudbehaviours/sharing-game-rules.md)
* [Sync-metadata approach](/cloud-code/cloudbehaviours/sharing-game-rules/sync-metadata-approach.md)
