Setup sprite Custom Physics Shape during asset import from script?

After importing a sprite, I can open the sprite editor manually and select “Custom Physics Shape” in the dropdown. Then I can select the “Generate” button to create a first-pass outline.

Can I automate this process during asset import? I’d like to simply run this Generate command with a specific outline tolerance value on all sprites that follow a specific naming scheme, but I haven’t found any API for it yet.

I’ve seen Sprite.OverridePhysicsShape but that would require me to implement all of the outline generation myself. Instead, I’d like to talk advantage of the existing outline detection provided by Unity.

Had the same issue, decided to simply use reflection to get what I need. Below the code that generates the Custom Physics Shape, the only downside is that you need to have the editor focused in order for it to work.

The code is far from pretty but it gets the job done, maybe someday I will wrap this into a Unity Plugin.

var windowType = typeof(UnityEditor.U2D.Sprites.SpriteEditorModuleBase).Assembly.GetType("UnityEditor.U2D.Sprites.SpriteEditorWindow");

var window= EditorWindow.GetWindow(type);
window.Show();
//Need to delay at least 1 frame so that the sprite editor menu appears
SetupPhysicsShape(windowType, window);

window.Close();


private static void SetupPhysicsShape(Type windowType, EditorWindow window)
        {

            var tolerance = 1f;

            var method = windowType.GetMethod("SetupModule", BindingFlags.Instance | BindingFlags.NonPublic);
            method.Invoke(window, new Object[] { 2 });

            var module = windowType.GetField("m_CurrentModule", BindingFlags.Instance | BindingFlags.NonPublic);

            var moduleInstance = module.GetValue(window);

            var moduleType = moduleInstance.GetType();

            var outlineInstance = moduleType.GetField("m_Outline", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(moduleInstance);

            var outlineType = outlineInstance.GetType();

            var list = outlineType.GetField("m_SpriteOutlineList", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(outlineInstance) as IList;

            var spriteOutline = list[0];

            var spriteOutlineType = spriteOutline.GetType();

            var tess = spriteOutlineType.GetField("m_TessellationDetail", BindingFlags.Instance | BindingFlags.NonPublic);

            tess.SetValue(spriteOutline, tolerance);



            moduleType = moduleType.BaseType;
            var mets = moduleType.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            var recordUndo = mets.First(m => m.Name == "RecordUndo");

            recordUndo.Invoke(moduleInstance, null);


            var shapeOutlineList =
                moduleType.GetProperty("selectedShapeOutline", BindingFlags.Instance | BindingFlags.NonPublic)
                    .GetValue(moduleInstance) as IList;

            shapeOutlineList.Clear();



            var selectedProp = moduleType.GetField("m_Selected", BindingFlags.Instance | BindingFlags.NonPublic)
                .GetValue(moduleInstance);


            moduleType.GetMethod("SetupShapeEditorOutline", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(moduleInstance, new[] { selectedProp });


            moduleType.GetProperty("shapeEditorDirty", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(moduleInstance, true);

            windowType.GetMethod("DoApply", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(window, null);
        }

@ImaginationOverflowPT , Nice finding, do you possibly have one for rendering outline generation as well?

Also for multi type sprites what do I need to change to make it work?

WYSIWYG xD, only done what I needed at the time, you can definitely extend that to your needs by using any C# inspector and see how unity handles it on their windows, at least it was what I did at the time.

@ImaginationOverflowPT Any chance you’re willing to help me implement this as something I can use in my project?

You can reach out to me at contact@imaginationoverflow.com, but I will only be able to do contract work at the beginning of next year.