Limitations in Luna Playable

The Luna engine has been built in-house by the Luna team, with the goal of allowing you to create your playable ads in Unity, and having the same output and experience in the browser.

There are a number of hard limitations that comes with this, as well as some APIs which we currently do not support.



DLLs are currently unsupported in Luna.

What can you do?

Replace the DLL with the plug-in C# source code. C++ plugins are not supported.

Ads and Analytics SDKs

Ads and Analytics SDKs are not supported in Playable ads, and therefore Luna does not support them.

What can you do?

You have a few options:

  • Use Automatic Stubbing to remove the SDKs from your project.
  • Wrap calls to these SDKs using #if !UNITY_LUNA.
  • Remove references to the SDKs entirely from your code.

What can you do?

  • Disable fog in lighting settings, or you can create a custom implementation for fog.

Avatar Animations

Avatar-based animations (both generic and humanoid) are not supported.

What can you do?

  • A work around is to re-bake the animations to target skinned mesh directly.


NavMesh is currently unsupported by Luna - whilst it is on the roadmap, it can be computationally expensive and so an alternative may be preferred for a playable experience.

What can you do?

  • The A* C# plugin from the asset store is a great alternative, and has been tested by Luna.
  • Implement you logic manually in C#.
  • Implement node-based Movement.


SRPs (Scriptable Rendering Pipelines) like LWRP and HDRP, are not currently unsupported, with no short term plans to add support.

What can you do?

  • Most customers are able switch and use Unity's built-in Default rendering pipeline.


Shadows are currently unsupported.

What can you do?

Create fake shadow (blob shadows).

Use lightmaps with static shadows.

WebGL / Shader targets

Additive Shaders

While we do support them, problems can arise due to the limitations of using WebGL1: WebGL1 can't handle values greater than 1, or less than 0. So the output will be clamped between these values.

E.g. Overlit = White (1,1,1,1) + Red (1,0,0,1). Rather than getting the expected value of (2,1,1,2) it will be clamped to (1,1,1,1)

Please be aware this could lead to unexpected outcomes when performing this type of operation, and the colour seen may not be what you intended.

Precompiled Shaders

Shaders marked with Compiled code: none (Precompiled shaders) are not currently supported. Using such shaders can produce Type error: Cannot read property val of null. (on line offsetUnits.val)

Shader Targets

Luna always initialises WebGL 1.0 context for compatibility reasons (even when WebGL 2.0 is available). This leads to limited support of newer shader features (the exact set varies from device to device due to different vendor-specific extensions available). To make sure Luna is able to utilize all your shader code, please try running the game targeting OpenGL ES 2 API.

Bridge Limitations

Luna transpiles C# code to JS with the Bridge.NET library, however Bridge only supports up to C# 7.0. This means features added in later releases (7.1, 7.2 etc.) will likely not be supported in Luna.

Examples of such features, with workarounds for each:

Default without specified type

Example of unsupported behaviour:

public bool IsToolOwned(string id) => GetToolByID(id) != default;

One workaround for this would be to specify the type:

public bool IsToolOwned(string id) => GetToolByID(id) != default(HJTool);

Extension methods with reference

Example of unsupported behaviour:

public static float RandomIn(this ref Vector2 v)

One workaround for this would be to create a static utility class and move the functionality into there. (You can also make use of our scripting defines based on whether the build is Luna or not).

Destructor (~TypeName method)

Example of unsupported behaviour:

class myClass {
~myClass() {}

One workaround for this would be to instead use OnDestroy().

GOTO statement

Example of unsupported behaviour:

switch (n)
case 1:
cost += 25;
case 2:
cost += 25;
goto case 1;
case 3:
cost += 50;
goto case 1;
Console.WriteLine("Invalid selection.");

One workaround for this is to use functions in place of looping back:

private static void costUp(int n){
cost += n * 25;
if (n != null){

In other cases it might be better to use recursion in place of goto logic.

In argument

Example of this unsupported behaviour:

public static Vector3 Clamp(this Vector3 v, in Vector3 a, in Vector3 b)

One workaround for this is to use the 'ref' keyword instead, just make sure to not change the value as 'in' would previously protect any changes from happening:

public static Vector3 Clamp(this Vector3 v, in Vector3 a, in Vector3 b)

Argument discard (Discards)

Example of unsupported behaviour:

if (DateTime.TryParse(dateString, out _))

One workaround for this is to create and use a regular variable instead:

DateTime tempVariable;
if (DateTime.TryParse(dateString, out tempVariable))

Circular inheritance with interfaces

Example of unsupported behaviour:

interface A extends B {}
interface B extends A {}

To workaround this you will need to break such inheritance and rewrite the code without it.


While lighting is supported, there are limitations surrounding the number of lights that have high intensity settings.

For example, if you have a light component and set its intensity to 1 and have additional lights in the scene as well, with intensities set to 1 or higher as these lights are summed in Luna causing over lit scenes in your Luna build.

This is a limitation of WebGL 1.0.

Unity GUI

Luna does not support the old Unity GUI system.


We don't support Unity DOTs or ECS.