I am in the process of building some tools for level creation and asset management. We have a need to be able to permanently resize models to 1.0 unity units max, x, y, or z. Working from a solution provided by @robertbu, I have devised a script which works great for objects which have no children. However, I am having an issue with resizing objects which do have children. I have a function right now which will cycle through the bounds of the children to determine the total bounds of the object, and then resize their meshes and translate their positions relative to the parent, using a calculated scale.
The problem is that the meshes stay permanently resized as they should, but the new positions only apply to the instance, resulting in models whose children resize smaller and smaller every time they are placed because the new positions never permanently applied. How can I permanently change the child mesh positions relative to the parent?
Here is the function I am currently working with:
void ResizeMeshToUnit(GameObject g) {
int count = g.transform.GetChildCount();
float minX, minY, minZ, maxX, maxY, maxZ, finalX, finalY, finalZ, size;
//initialize variables.
finalX = finalY = finalZ = size = 0f;
minX = maxX = g.transform.position.x;
minY = maxY = g.transform.position.y;
minZ = maxZ = g.transform.position.z;
if (count < 1)
{
return;
}
//cycle through children bounds to get minimums and maximums for model
for (int i = 0; i < count; i++) {
Transform t = g.transform.GetChild(i);
var renderer = t.GetComponent<Renderer>();
if (renderer != null)
{
Bounds bounds = renderer.bounds;
if (bounds.min.x < minX)
{
minX = bounds.min.x;
}
if (bounds.min.y < minY)
{
minY = bounds.min.y;
}
if (bounds.min.z < minZ)
{
minZ = bounds.min.z;
}
if (bounds.max.x > maxX)
{
maxX = bounds.max.x;
}
if (bounds.max.y > maxY)
{
maxY = bounds.max.y;
}
if (bounds.max.z > maxZ)
{
maxZ = bounds.max.z;
}
}
}
//establish overall bounds
finalX = maxX - minX;
finalY = maxY - minY;
finalZ = maxZ - minZ;
//determine largest dimension
size = finalX;
if (size < finalY)
{
size = finalY;
}
if (size < finalZ)
{
size = finalZ;
}
//return if already correct scale
if (Mathf.Abs(1.0f - size) < 0.01f)
{
Debug.Log ("Already unit size");
return;
}
//calculate scale
float scale = 1.0f / size;
//use scale to resize child meshes and alter positions
for (int i = 0; i < count; i++)
{
Transform t = g.transform.GetChild(i);
MeshFilter mf = t.GetComponent<MeshFilter>();
if (mf != null)
{
Mesh mesh = mf.sharedMesh;
t.localPosition *= scale;
Vector3[] verts = mesh.vertices;
for (int j = 0; j < verts.Length; j++)
{
verts[j] = verts[j] * scale;
}
mesh.vertices = verts;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}
}
How can I get the positions to permanently stick in the model?
EDIT:
The original question, which @robertbu provided a working approach for can be found here:
http://answers.unity3d.com/questions/495977/how-do-i-scale-an-object-or-prefab-to-a-size-in-un.html
EDIT 2: Solution has been worked out and is contained in an an answer below.