Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by greenshadow · Aug 17, 2013 at 04:34 AM · gameobjectmeshpositionscalepermanent

How do I permanently resize a model with children?

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.

Comment
Add comment · Show 9
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Sajidfarooq · Aug 17, 2013 at 06:07 AM 0
Share

It would help if you could reference the original question where RobertBu helped you re-size the mesh permanently. It would provide some context.

avatar image whydoidoit · Aug 17, 2013 at 06:58 AM 0
Share

Just wondering why you can't just resize the scale of the parent when you've worked out the entire size of the children. I can't quite figure out why you need to go through and move and resize the children.

avatar image greenshadow · Aug 17, 2013 at 07:19 AM 0
Share

@Sajidfarooq I agree, the context may provide some help. I have edited the original post and provided a link.

avatar image greenshadow · Aug 17, 2013 at 07:29 AM 0
Share

@whydoidoit You are correct, I can resize the scale of the parent rather than changing and moving each of children. However the effect will only apply to each instance, and not permanently change the model unless the meshes of the children themselves are scaled and recalculated.

The reason I want to permanently change the scale of the model is so that I can avoid the problems with animations that arise from scaling an object after the animation is created, and to reduce additional overhead which may be needed to calculate objects which aren't at 1.0 scale.

If I can create a tool to permanently change the model correctly, the artists can import the models, use the tool to size them to exact scale, and then create $$anonymous$$ecanim animations to be used. If the animations are done first, and then the object instance is scaled, my understanding is they can produce undesired results.

avatar image whydoidoit · Aug 17, 2013 at 07:57 AM 0
Share

Right but you could just create a prefab or just alter the model scale as @fattie says (which could be done automatically using your script as part of the asset import process).

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Fattie · Aug 17, 2013 at 07:23 AM

LATER ...

dude, I think you're looking for the famous encapsulate function

you use it constantly with bounds ....... it makes things so easy

http://answers.unity3d.com/questions/360459/encapsulate-bounds-problem.html

Does that help!?


EARLIER ...

Shouldn't you just be changing the scale of the actual model on the importer ?

Comment
Add comment · Show 12 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image greenshadow · Aug 17, 2013 at 07:38 AM 0
Share

@Fattie this is a great question, but that would require the exact bounds of model to be known in advance so that an exact calculation of scale can be applied on the importer to make the object no wider, taller, or longer than 1 Unity unit. One of the purposes of the script is to be able to arrive at that calculation.

Ideally, artists would create the models at 1.0 Unity units in scale before importing, however, art is not my forte, and the artists I am working with are having fits over trying to create the models in the right size.

avatar image Fattie · Aug 17, 2013 at 07:42 AM 0
Share

Green -- just one point.

"artists I am working with are having fits..."

it is a classic in the video game industry, that, modellers $$anonymous$$UST make models at correct size. it's like "point one" in the business.

(You can see 1000s questions on here about it.)

they simply have to utterly change their ways. Fact. if they are beginners you should just tell them this directly - see the 1000s questions on here - for their benefit

avatar image Fattie · Aug 17, 2013 at 07:44 AM 0
Share

I don't really follow you here. Have an editor script called "Size Fixer"

it has I guess two lines of code. (1) look at the bounds to find the longest dimension. (2) change the scale so that it is 5 meters (or whatever your goal is)

this is a commonplace calculation ... here's an example where some GREAT AD$$anonymous$$IN explain it nicely! ;-) ..

http://answers.unity3d.com/questions/432009/resizing-a-gameobject-based-on-mouse-position.html

So, just run "Size Fixer" when you want, or automatically when a mesh is added

I apologize if I'm "missing something" about your question

avatar image greenshadow · Aug 17, 2013 at 08:01 AM 0
Share

@Fattie I readily admit that these artists are indeed beginners with Unity. They have much to learn. However, no need to apologize my friend, perhaps it is not you, but me who is "missing something": won't animations be affected by scaling down (or up) an object after the animation has been created in $$anonymous$$ecanim?

Also, "Size Fixer" looks great for objects with no children, but let's say we have a model which is comprised of child meshes. Let's also say that the object must be no bigger than 1.0 Unity units on any axis. Now we can't simply use this line anymore:

lengthNow = ourSprite.renderer.bounds.size.x;

Ins$$anonymous$$d, we've got to calculate the farthest x, y, and z bounds that renderers of children reach to arrive at an equivalent to "lengthNow", and then we can resize the objects, similar to this portion of code from the method in the original post:

             //establish overall bounds
             finalX = maxX - $$anonymous$$X;
             finalY = maxY - $$anonymous$$Y;
             finalZ = maxZ - $$anonymous$$Z;
             
             //deter$$anonymous$$e largest dimension
             size = finalX;
             if (size < finalY)
             {
                 size = finalY;
             }
             if (size < finalZ)
             {
                 size = finalZ;
             }
             
             //**omitted for clarity**
             
             //calculate scale
             float scale = 1.0f / size;
avatar image Fattie · Aug 17, 2013 at 08:21 AM 0
Share

regarding the important question scaling of an animation in $$anonymous$$ecanim ... I'm almost certain there is no problem with that or the whole game engine would fall apart ... but I'm not a Top Expert in $$anonymous$$ecanim. perhaps @whydoidoit can confirm that? cheers all

Show more comments
avatar image
1

Answer by greenshadow · Aug 18, 2013 at 07:24 AM

I thought I would provide a solution to this issue here, so that those who took the time to help me can see what I came up with, and so that others can possibly learn from it. I ended up utilizing the direction provided by @Fattie and @whydoidoit, combining the elegant use of the encapsulate function, and looking hard at the capabilities of the the AssetPostProcessor class to create a script which will scale an object to a maximum of 1 Unity unit on any axis upon importing.

On Preprocessing the import, the script first sets the FBX globalscale to 1. Then, in Postprocessing, the script calculates the ratio necessary to resize the model into Unity units, and the model is then scaled down in size, before being written to the disk. The benefit here is that the change is "semi-permanent", in that any instances of this model will contain the same scale. The script works great, and will scale models to exact size, without sacrificing the quality of animations which are added afterwards. Thanks again @Fattie and @whydoidoit:

 using UnityEngine;
 using System.Collections;
 using UnityEditor;
      
 class MeshPostprocessor : AssetPostprocessor {
     
     float desiredSizeInUnits = 1.0f;
     
     void OnPreprocessModel ()
     {
         ModelImporter importer = (ModelImporter)assetImporter;
         importer.globalScale = 1f;
     }
     
     void OnPostprocessModel (GameObject g)
     {
         Bounds combinedBounds = new Bounds(g.transform.position, new Vector3(0, 0, 0));
         Renderer[] renderers = g.GetComponentsInChildren<Renderer>();
         
         foreach (Renderer r in renderers)
         {
             combinedBounds.Encapsulate(r.bounds);
         }
         
         float size = combinedBounds.size.x;
         if (size < combinedBounds.size.y)
         {
             size = combinedBounds.size.y;
         }
         if (size < combinedBounds.size.z)
         {
             size = combinedBounds.size.z;
         }
          
         if (Mathf.Abs(desiredSizeInUnits - size) < 0.01f)
         {
             return;
         }
          
         float scale = desiredSizeInUnits / size;
         g.transform.localScale *= scale;
     }
 }
 
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Aug 18, 2013 at 08:12 AM 0
Share

Thanks for posting that - very helpful to others browsing later.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

postion scale and rotation greyed out and not working 1 Answer

Calculating mesh over GameObject scale 1 Answer

I tried to make a box to select units like you do in windows 1 Answer

Positioning gameobjects by a corner, not by center 0 Answers

Why the guismo of the GameObject is at the center but its "mesh" is not at all in the center? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges