Creating a Mesh Inset by a Specified Distance

Alright, this is probably something fairly simple for those well-versed in mesh manipulation within Unity but I’m having trouble wrapping my head around a solution and haven’t found anything else close enough to my problem to get me started in the right direction.

I have an existing mesh plane, which could be either a rectangle, or any convex/concave polygon in the end. What I need to do is create an identical mesh, and then effectively scale that mesh down to create a border of ‘d’ unit distance between the edges of the original and duplicate mesh. Does anyone have a best practice for doing this?

Thus far I have duplicated the original mesh, but I haven’t worked with manipulating vertices/etc enough to just dive in without a little further direction. Normally, I would simply scale an object down by hand until it “looked right”, but in this instance it needs to be inset dynamically at runtime by an input value, and be technically correct. Thanks for any help in advance!

Here is a script that will take in a mesh, then scale it depending on the value given. I have not included scaling of the collider though this would be easy to add.

#pragma strict

public var theObject : Transform;
private var theMesh : Mesh;
private var originalVerts : Vector3[];
private var scaledVerts : Vector3[];
public var scaleFactor : float = 1.0;

function Start() 
{
	if (!theObject)
    {
       theObject = this.transform;
    }

    theMesh = theObject.GetComponent(MeshFilter).mesh as Mesh;

    originalVerts = new Vector3[ theMesh.vertices.length ];
    originalVerts = theMesh.vertices;

    scaledVerts = new Vector3[ originalVerts.length ];

    ScaleMesh();
}

function Update() 
{
	if (Input.GetMouseButtonUp(0))
    {
       ScaleMesh();
    }
}

function ScaleMesh() 
{
    for (var vert : int = 0; vert < originalVerts.length; vert ++)
    {
       scaledVerts[vert] = originalVerts[vert] * scaleFactor;
    }
	
	theMesh.vertices = scaledVerts;
}

If you wanted to save the meshes to use in setting up rather than having them scaled at runtime, you could export the mesh from a ‘helper scene’ with something like AssetDatabase.CreateAsset( newObjectFilter.mesh, “Assets/Generated/My” + objectToSave.name + “_mesh.asset” );

I think this method may be slightly better, with my limited knowledge you won’t be able to batch drawcalls on anything that has been scaled through the inspector or localScale.

SNS, are you aware you can very simply and easily scale any object in Unity, just using localScale?

You can do this at runtime and it will be technically correct.

It would be very difficult (ie months of work) to write code to re-make mesh on a smaller scale - and in the end it would just do what localScale does! Hope it helps


If you mean simply the problem of how to calculate what fraction you want, you use division to find a fraction. So you use division, with the new and old lengths.

desiredLength = your desired length in meters
var lengthNow:float;
lengthNow = ourSprite.renderer.bounds.size.x;
lengthNow will be the length now in meters

transform.localScale.x = ( desiredLength / lengthNow );

OK ?

As I already said, almost certainly you are going to want to make the scale “about 0.9”

You will have to TRY THAT (takes maybe 10 seconds), and you will see if 0.9 is correct.

If it is not correct, try other values. For example, you could try 0.91.

For anyone else who comes across this question, I have since revised my method for creating a mesh inset by a specific distance. Unfortunately, I can’t reasonably show the whole of the code here but I can give the general idea behind how I solved the problem. The primary issue is that the other answers were inaccurate for measuring from an edge. You could scale a vertex by x distance, but I needed offsets from the edge.

Some of the more common tools used were a “PointInPolygon” check and Line classes with intersection and other methods; for the most part these are pretty simple to find via google and aren’t too hard to codify for whatever circumstance you may need. For my checks, only 2D checks were necessary which further simplified things.

The process involved taking the vertices of a mesh and then creating an exterior of Lines using those vertices. Doing a PIP check against the original mesh using the normal of each Line determined direction to offset (specified distance / unit of measurement used) regardless of winding direction, and the Line was moved away from its origin by that offset. This continues until all Lines have been iterated through. The new vertices are found by doing intersection checks against the Lines in order.

That pretty much sums it up! Feel free to post with any questions.