What would be a way to ignore the parent
and move a LocalTransform
to a raycast hit.Position
based on it’s LocalToWorld
I’m assuming you have a world-space position change that you want to apply to your LocalTransform. You need to convert the world-space offset to the local space. Grab the parent’s LocalToWorld
matrix, math.inverse
it, and multiply it with your offset. For the mul
to work, you will need to pad your float3
with a 0
to form a float4
.
In my scenario, I have a parent with a few child objects. I have a raycast in order to bring those objects to the ground. This works when LocalTransform
is targeting the world and not the parent.
I’m not sure how to apply your example in order to bypass the parent.
var parentLTW = SystemAPI.GetComponent<LocalToWorld>(parent.Value);
float4x4 parentmatrix = parentLTW.Value;
parentmatrix = math.inverse(parentmatrix);
float4 padding = new float4(transform.ValueRO.Position.x, transform.ValueRO.Position.y, transform.ValueRO.Position.z, 0);
float4 offset = math.mul(parentmatrix, padding);
transform.ValueRW.Position.y = hit.Position.y - offset.y;
Looks like you’re transforming the full local space position of the object. Extracting the offset.y
value afterwards won’t give you the right numbers.
You need to obtain the world space offset first. In your case that’s the equivalent of (0, -transform.position.y, 0)
. Since your object is in local space, the LocalTransform
gives you the equivalent of transform.localPosition
instead. To get the world space position, AFAIK these are your options:
- Extract it from the
LocalToWorld
component, but since the LTW only gets updated later in the frame, you’d be working with values from the previous frame. Depending on the use case, this might be fine? - Use the
TransformHelpers.ComputeWorldTransformMatrix
to calculate the up-to-dateLocalToWorld
based on the current hierarchy state. This is slower.
This method is intended for the relatively uncommon cases where an entity’s accurate world-space transformation matrix is needed immediately. For example:
- When performing a raycast from an entity which may be part of an entity hierarchy, such as the wheel of a car object. The ray origin must be in world-space, but the entity’s LocalTransform may be relative to its parent.
- When one entity’s transform needs to “track” another in world-space, and the targeting entity and/or the targeted entity are in a transform hierarchy.
- When an entity’s transform is modified in the LateSimulationSystemGroup (after the TransformSystemGroup has updated, but before the PresentationSystemGroup runs), this method can be used to compute a new LocalToWorld value for the affected entity.
For an entity that is not part of an entity hierarchy, the LocalTransform component already stores the world-space transform (since the two spaces are identical). In his case, reading LocalTransform directly is more efficient than calling this method.
The LocalToWorld component also contains a world-space transformation matrix. However, this value may be out of date or invalid; it is only updated when the TransformSystemGroup runs). It may also contain additional offsets applied for graphical smoothing purposes. Therefore, while the LocalToWorld component may be useful as a fast approximation when its latency is acceptable, it should not be relied one when an accurate, up-to-date world transform is needed for simulation purposes.
Once you have the world space offset, you can transform it like this:
offset = math.mul(math.inverse(parentmatrix), new float4(offset, 0)).xyz;
If you’re making some sort of a ground snapping mechanism, you can also try overwriting the entity’s LocalToWorld
after the transform systems are updated. This lets you work in world space, and on current frame values, but your changes will be overwritten in next frame.
Did you mean this?
var offset = new float3(0, -transform.ValueRO.Position.y, 0);
offset = math.mul(math.inverse(parentLTW.Value), new float4(offset, 0)).xyz;
transform.ValueRW.Position.y = hit.Position.y + offset.y;
It appears to not offset correctly.
What would be a way to ignore the parent
and move a LocalTransform
to a raycast hit.Position
based on it’s LocalToWorld
?