sr4dev / Unity-SpriteAssist

Unity Sprite mesh extension
https://github.com/sr4dev/Unity-SpriteAssist
227 stars 29 forks source link

How to make a Polygon Collider 2D using the generated mesh? #45

Closed CharlieHess closed 2 years ago

CharlieHess commented 2 years ago

In a 2D isometric setup, I have a sprite that defines the walkable areas of a level exactly, like this:

image

When I attach a Polygon Collider 2D to it, I get a collider that looks like this:

image

Clearly not usable for the actual collision.

SpriteAssist helps me generate a sprite mesh that matches the bounds of the sprite almost exactly:

image

But now I'm unsure how to make a collider from that. If I attach a Polygon Collider, I get the same result as before. And I can't use a Mesh Collider as I'm in a 2D URP setup. Any ideas?

sr4dev commented 2 years ago

I want to support Polygon Collider. Unfortunately SpriteAssist dosen't support Polygon Collider. If you really want it, it's possible to simply add it(but there's a problem). Add this code to OpaqueMeshCreator class.

baseSprite.OverridePhysicsShape(new List<Vector2[]>(){ vertices });

   public class OpaqueMeshCreator : MeshCreatorBase
    {
        public override void OverrideGeometry(Sprite baseSprite, Sprite dummySprite, TextureInfo textureInfo, SpriteConfigData data)
        {
            dummySprite.GetVertexAndTriangle2D(data, out var vertices, out var triangles, MeshRenderType.Opaque);
            vertices = MeshUtil.GetScaledVertices(vertices, textureInfo, isClamped: true);
            baseSprite.OverrideGeometry(vertices, triangles);

            //HERE! ★
            baseSprite.OverridePhysicsShape(new List<Vector2[]>(){ vertices });
        }

        public override GameObject CreateExternalObject(Sprite sprite, TextureInfo textureInfo, SpriteConfigData data, string oldPrefabPath = null)
        {
            return PrefabUtil.CreateMeshPrefab(textureInfo, false);
        }

        public override void UpdateExternalObject(GameObject externalObject, Sprite baseSprite, Sprite dummySprite, TextureInfo textureInfo, SpriteConfigData data)
        {
            PrefabUtil.UpdateMeshPrefab(textureInfo, false, externalObject);

            dummySprite.GetVertexAndTriangle3D(data, out var vertices, out var triangles, MeshRenderType.Opaque);
            PrefabUtil.AddComponentsAssets(baseSprite, externalObject, vertices, triangles, textureInfo, RENDER_TYPE_OPAQUE, data.opaqueShaderName, data);
        }

        public override void UpdateMeshInMeshPrefab(GameObject externalObject, Sprite baseSprite, Sprite dummySprite, TextureInfo textureInfo, SpriteConfigData data)
        {
            dummySprite.GetVertexAndTriangle3D(data, out var vertices, out var triangles, MeshRenderType.Opaque);
            PrefabUtil.UpdateMeshFiltersMesh(externalObject, vertices, triangles, textureInfo, data.isCorrectNormal);
        }

        public override List<SpritePreviewWireframe> GetMeshWireframes()
        {
            return new List<SpritePreviewWireframe>()
            {
                new SpritePreviewWireframe(SpritePreviewWireframe.opaqueColor, MeshRenderType.Opaque)
            };
        }
    }

And reimport a Sprite asset. Now you can create a Polygon Collider 2D with SpriteAssist. But it's not perfectly... I need time to fix this issue... image

CharlieHess commented 2 years ago

OK for future searchers it turns out this is built into Unity already:

https://answers.unity.com/questions/1905020/generate-polygon-collider-from-sprite-exact-matchc.html

Open up the Sprite editor and select Custom Physics Shape, then move the tolerance up and hit generate. 0 is vague but very non-intensive collision (What it defaults to), while 1 is extremely accurate to sprite shape but requires a lot of polygons for the collision mesh. Then just apply a polygon Collider to the sprite