How to access useful Unity Editor/Engine internal methods?

I was trying to figure out how to manipulate a sprite image, so I looked at the code for the Sprite Editor. I noticed that it accessed some internal Unity Editor methods, including the one I really wanted: UnityEditor.SpriteUtility.CreateTemporaryDuplicate.

The Unity 2D methods seem to have no problem accessing these internal methods through an InternalBridge class. But when I copy over the code, including the assembly def’s and assembly info’s, I still get errors saying unable to access due to protection level.

Unity packages can do it, why can’t I?

Okay, I figured out how Unity does it. If you look at the Visual Studio Assembly Browser for UnityEditor.CoreModule, you see that there are a number of [assembly: InternalsVisibleTo ()] directives. This includes Unity.InternalAPIEditorBridge001 up to Unity.InternalAPIEditorBridge024. (There are also Unity.InternalAPIEngineBridge001 up to (I think–it’s harder to tell) Unity.InternalAPIEngineBridge024 for engine internals. )

The internal bridge class for plug-in com.unity.2d.common is in the DLL Unity.InternalAPIEditorBridge.001 according to its asmdef. So that’s how Unity can access its internals from its plugins!

So, to access the Unity Internals (if you’re desperate for them), you create an asmdef for an unused editor bridge DLL, and–presto!–you have the same access.

The problem would be in release code to figure out which internal bridges are already taken. Since I’m not making release code (only a plug-in for the editor that would be used in specific, controlled circumstances), that’s not my concern.

Decompile unity and recompile it with looser access modifiers?


Sounds like a bad idea? Yeah thats why they are internal. They arent meant to be used by you.

Uhm, you could always use reflection to access internal or private classes / methods / fields. There are only very few things you could not access through reflection. Of course you would create an unwanted dependency which may break in any future update since it’s only meant for internal use.

Though the specific method you’re talking about only uses public available APIs as far as I can tell. Note that the method goes through some detours to create a duplicate of the texture. If the texture is marked readable you should be able to simply instantiate the texture. You only would need to go though this convoluted process if the source texture is not readable. So it actually creates a temporary render texture, uses blit to copy the texture content on the GPU and then does a readback from the render texture into a new texture.

So then, the safest thing to do is to not write your own InternalAPIBridge, but rather “borrow” the one from the 2D Commons package.

Create an Assembly Definition Reference inside a folder called InternalBridge (or anything really, but do it inside a specific folder for safety). Now, reference the InternalBridgeDef under Packages > 2D Common > Runtime / Editor > InternalBridge,

Add a script called AssemblyInfo containing the following:

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("My.Cool.Assembly")]

And a script called InternalEngineBridge in which you safely expose the internals you require. NOTE: you HAVE to put it under a namespace to avoid naming conflicts! You could also use a different name but that could break if Unity adds scripts themselves, so using a namespace is safest.

using UnityEngine;

namespace UnityClock
{
    internal static class InternalEngineBridge
    {
        // Note how NumericFieldDraggerUtility is an internal Unity class.
        public static float NiceDelta(Vector2 deviceDelta, float acceleration) => 
            NumericFieldDraggerUtility.NiceDelta(deviceDelta, acceleration);
    }
}

Now all that’s left is to reference the InternalBridgeDef from the 2D Commons package inside the assembly where you want to use it.

And presto!

public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, TimeSpan startValue)
{
    InternalEngineBridge.NiceDelta(delta, 0f);
}

This is completely safe, since you can just keep adding Assembly Definition References! You also make sure that you expose to the things that need it, and nothing else. As the magicians say, “you finish clean”. The only thing you need is to have the 2D Commons package installed - dumb, but I’ll take it!

Although you can access internal APIs in various ways, before doing so, I highly recommend that you try to achieve what you are aiming for using public APIs. We have strict rules when it comes to developing, maintaining and deprecating public APIs, however, these rules are more lax when it comes to internal APIs. Internal APIs can be deprecated from one version to the next, and usually have less safety checks, since they tend to be developed with a certain domain knowledge in mind.

If you want to work with Sprite data, do have a look at this documentation page, maybe these public APIs can help you achieve what you are going for: Sprite Editor Data Provider | 2D Sprite | 1.0.0

However, if you really need to use internal APIs, @CaseyHofland approach is the safest of them all. But do let us know why you need internal API access, so that we might be able to open up these areas for you in the future.