- Home /
How to measure the height of 3D objects.
3D objects with different shapes are stacked at some point. And I want to measure the maximum height of the point. Each 3D object is a thing, not a simple figure. As objects stacked, their heights also change. How should i measure the height? First, the way I think is: It is a way to use trigger. Move the trigger up and wait for OnTriggerExit() to be called. Is there a better way than this?
Thanks! $$anonymous$$eshRenderer.bounds.max.y: Depending on the object, Y Position seems to have an error range of up to 0.9, but it seems to be usable. I will apply it.
Answer by IsaiahKelly · Sep 10, 2017 at 12:02 AM
Use a bounding box to calculate the height
The quickest and most accurate calculation is with Collider.bounds.size. Here is an example script that will grab the total bounding box size of all child objects under the object it is attached to. Then you simply grab the y value of the bounding box size to get the overall height.
using UnityEngine;
public class BoundsDebug : MonoBehaviour
{
// Visual display of the bounding box for testing.
private void OnDrawGizmos()
{
// Draw each child's bounds as a green box.
Gizmos.color = new Color(0f, 1f, 0f, 0.3f);
foreach (var child in GetComponentsInChildren<Collider>())
{
Gizmos.DrawCube(child.bounds.center, child.bounds.size);
}
// Draw total bounds of all the children as a white box.
Gizmos.color = new Color(1f, 1f, 1f, 0.1f);
var maxBounds = GetMaxBounds(gameObject);
Gizmos.DrawCube(maxBounds.center, maxBounds.size);
Debug.Log("Total height is " + maxBounds.size.y);
}
Bounds GetMaxBounds(GameObject parent)
{
var total = new Bounds(parent.transform.position, Vector3.zero);
foreach (var child in parent.GetComponentsInChildren<Collider>())
{
total.Encapsulate(child.bounds);
}
return total;
}
}
This script will produce the following results in the editor when you place game objects with colliders under a game object with this script attached to it. It works quite well, but you'll notice that the upper left object here has gaps around it. This is because it appears that mesh colliders are automatically converted into box colliders for bounds calculations and this is what produces the gaps you see for non-square objects when rotated.
Use a raycast hit to calculate the height
Alternatively you could use a raycast to get more accurate readings for mesh colliders. However, the problem with this is you would need to figure out where to shoot the ray from to actual get the very top of the object. This would be no easy task, so it's probably a better idea to just check the actual height of the vertices on the meshes instead as suggested by fafase.
$$anonymous$$ost objects have $$anonymous$$esh Collider applied, and the error range seems to same. It is exact if Collider is a figure.
not sure what this error is you're talking about, but why are you using max ins$$anonymous$$d of size?
For example, Find the vertex height that is the highest of the various vertices of a 3D object. If i rotate the object, the position of the vertex will change, and the maximum height will also change(Unless it is a balanced object). And Error Range.. When i rotate an object, there is a difference occurred between bounds.max.y and the actual object max height.
Answer by zzeeshann · Sep 10, 2017 at 01:19 AM
If the object has a renderer,
Vector3 sizeVec = GetComponent<Renderer>().bounds.size;
Next best thing would probably be collider
Vector3 sizeVec = GetComponent<Collider>().bounds.size;
Debug.Log(sizeVec.x);
Debug.Log(sizeVec.y);
Debug.Log(sizeVec.z);
You can also watch this video tutorial https://youtu.be/W-p0LFqJY_0
Answer by fafase · Sep 11, 2017 at 06:52 PM
If you need exact value, you can use the mesh and iterate through the vertices. If you consider the bottom object wont change because it is below it all, you can just store that guy for the rest.
Get highest object
Get lowest object ( you store this one as it may be the first item to be placed)
Iterate vertices from 1 to find highest y value
iterate vertices from 2 to find lowest y value (store that one if not likely to change)
Do 3 - 4 to get the distance
Make sure that for steps 3 and 4 you convert their position to world space (vertex value is local space).
This will give exact distance regardless of the collider shape or the rotation of the objects.
As mentioned in the comment, you can use generation process to find the highest object on top. Iterate the collection of placed items, when one failed to be on top after 3 runs (or 4, or 2) remove it as it will never be on top. This will gradually set your collection to only the top items. Then iterate the y values only if you have a new topper.
This is probably the most accurate, but also the most expensive process because there could easily be hundreds of vertices to check and you'd be repeating the action every time something changes or even every frame!
Indeed it is the most expensive. But dat accuracy tho...
On the other hand, you are only checking the vertices of the two far most objects, and only the y values. So the hit may not be so great. Considering your bottom object may not change, you got that value already from the start. So you are only checking the vertices of the top object. And you can also optimize the search for that one by discarding objects that have failed to be on top for like three searches. So you end up only checking like 4 or 5 items and only one set of y values of the top one.
yes. Here is my code.
Vector3[] verts = meshFilter.mesh.vertices;
for (int i = 0; i < verts.Length; i++)
{
verts[i] = transform.TransformPoint(verts[i]);
}
float maxHeight = verts[0].y;
for (int i = 1; i < verts.Length; i++)
{
if (verts[i].y > maxHeight)
{
maxHeight = verts[i].y;
}
}
Whenever objects are added one by one, vertex calculation is performed on the object, and the maximum height value is updated by comparing with the previously calculated height value. Is it a bit different from what you told me? Something I have not written about is that objects are added sequentially.