Reputation: 1653
How do I determine that the collider.bounds.center is local or global positioned in unity?
The Problem
I have a vehicle that can update its size and needs its colliders to encapsulate the new size. The vehicle collider is a simple box collider, but I want the colliders to accurately update instead of just encapsulating the object.transform.position
When the gameobjects are rendered. The position of the child object will be (1153.11621, 32.2968063, 3530.69141)
However the collider.bounds.center
returns a different value of (0.0157470703, 0.019865036, -0.00903320312)
.
This same GameObject when placed dynamically by the player will return collider.transform.position (1300.94421, 31.6532516, 3568.89038) and collider.bounds.center (1300.94458, 31.6570377, 3568.88867)
This is the reason why I think the collider.bounds value is not valid or updating correctly.
In theory the vehicle could do the following. Initialize the bounds to the first item's center and size. Encapsulate all items. Then center the float collider based on those bounds.
The problem is the center is not always where it should be relative to the world position of the vehicle. On initial render it is near the 0,0,0 "world" center, but when dynamically adding or removing pieces, the bounds using the world position near the ship.
This means that on the initial render the vehicle would have to set it's bounds at 0, but then subsequent bounds calculations would have to calculate at vehicleObj.transform.position
coordinates.
This bounds.center is used to transform the floating collider, onboard collider and blocking colliders of the vehicle so they are all centered within X and Z axis and set a different Y values based on their type of collider.
The vehicle require local bounds due to
Other requirements
The current approach is to iterate through the piece that is added to this parent gameobject and encapsulate it using the local bounds.
collider.bounds.center
is a local position or a global position.Using gameObject.transform.InverseTransformPoint
to get the localPosition of the element in relation to the vehicle for global positioned center.
However, if the center point is not global it will return a invalid value that is very high, meaning the applied to the vehicle it will cause its collider to be 100-1000x larger than the vehicle size.
I'm trying to find a good way to test if the bounds.center
is nearby the vehicleInstance's world position of near 0,0,0 instead which would cause the vehicle to create a massive collider (and break the vehicle).
Partial Solution using just position and center to get the offset without TransformPoint and InverseTransformPoint.
public static Bounds TransformColliderGlobalBoundsToLocal(Collider collider)
{
var colliderCenterMagnitude = collider.bounds.center.magnitude;
var worldPositionMagnitude = collider.transform.position.magnitude;
Vector3 center;
/*
* <summary>confirms that the magnitude is near zero when subtracting a guaranteed world-position coordinate with a bounds.center coordinate that could be local or global.</summary>
*
* - if magnitude is above 5f (or probably even 1f) it is very likely a local position subtracted against a global position.
*
* - Limitations: Near world center 0,0,0 this calc likely will not be accurate, but won't really matter
*/
var isLocalPosition = Mathf.Abs(colliderCenterMagnitude - worldPositionMagnitude) > 5f;
if (isLocalPosition)
{
var globalCenterFromRoot =
collider.transform.root.transform.TransformPoint(collider.bounds.center);
center = collider.transform.root.transform.InverseTransformPoint(globalCenterFromRoot);
}
else
{
center = collider.transform.root.transform.InverseTransformPoint(collider.bounds.center);
}
return new Bounds(center, collider.bounds.size);
}
Upvotes: 1
Views: 763
Reputation: 1653
My problem was with Physics not syncing. Needed to call Physics.SyncTransforms() before parsing bounds on initial load of the Vehicle.
The reason it needed to be called was due to all the logic being called before the FixedUpdate fired on first render.
Since it was not fired, transforming the position from local to global actually worked, because the boat's local position was also 0,0,0.
Found this information linked in a unity forum psa-collider-bounds-incorrect-until-phyiscs-update.
Upvotes: 0