用旋转定义相对点

Defining a relative point with rotations

我想得到一个相对点(所以它是当前位置 + 方向向量 3)

这样当我旋转游戏对象时它仍然处于相同的相对点

示例:(假设当旋转为 0 时它在 x 轴上距离游戏对象 1 个单位,当旋转为 -90 时它应该在 z 轴上距离游戏对象 1 个单位)

这是我尝试过的:(中心是相对于游戏对象的距离的 vector3)

boxPos = new Vector3(
    center.x + transform.position.x + (transform.rotation.eulerAngles.y * (1 / 360) * center.x),
    center.y + transform.position.y,
    center.z + transform.position.z + (0.5f - (transform.rotation.eulerAngles.y * (1 / 360) * center.z))
    );

有什么办法吗?

经过多次建议...结果如下:

测试 1:

代码:

private void OnDrawGizmos()
{
    //center is a value I defined... it is the relative point
    //no need to care about extents... that's just box size
    Vector3 objectPosition = transform.position;
    Quaternion rotation = transform.rotation;
    boxPos = (rotation * (center - objectPosition)) + objectPosition;
    Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale);
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(boxPos, new Vector3(extents.x * 2, extents.y * 2, extents.z * 2));
}

结果:

0-0-0 POSITION: it renders as if it was shifted center/-2 units away from the expected point (as expected from the other notices).

ROTATION: makes it behave weirdly

MOVEMENT: doesn't affect it at all

OTHER NOTICES: boxPos is just center/-2 (so if center is 1, -2, 3 boxPos would be -0.5, 1, -1.5)

测试 2:

代码:

private void OnDrawGizmos()
{
    //no need to care about extents... that's just box size
    //first child of the object is just an empty object... shifted by center values... this is always in the intended relative point of the object
    boxPos = transform.TransformPoint(gameObject.transform.GetChild(0).position);
    Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale);
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(boxPos, new Vector3(extents.x * 2, extents.y * 2, extents.z * 2));
}

结果:

0-0-0 POSITION: it rendered perfectly as expected.

ROTATION: makes it shift away (but around) from the object.

MOVEMENT: also makes it shift way in the direction of movement (with a shift of value: position * (center/2) which makes the overall movement *1.5 of the expected movement every 1 unit in any direction)

测试 3:

代码:

private void OnDrawGizmos()
{
    //no need to care about extents... that's just box size
    //first child of the object is just an empty object... shifted by center values... this is always in the intended relative point of the object
    boxPos = transform.TransformPoint(transform.InverseTransformPoint(gameObject.transform.GetChild(0).position));
    Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale);
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(boxPos, new Vector3(extents.x * 2, extents.y * 2, extents.z * 2));
}

结果:

0-0-0 POSITION: it rendered perfectly as expected.

ROTATION: makes it shift away (but around) the object.

MOVEMENT: it works perfectly as expected.

测试 4:

代码:

private void OnDrawGizmos()
{
    //center is a value I defined... it is the relative point
    //no need to care about extents... that's just box size
    Vector3 objectPosition = transform.position;
    Quaternion rotation = transform.rotation;
    point = transform.TransformPoint(transform.InverseTransformPoint(gameObject.transform.GetChild(0).position));
    boxPos = (rotation * (point - objectPosition)) + objectPosition;
    Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale);
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(boxPos, new Vector3(extents.x * 2, extents.y * 2, extents.z * 2));
}

结果:

0-0-0 POSITION: it rendered perfectly as expected.

ROTATION: makes it shift away (but around) the object.

MOVEMENT: it works perfectly as expected.

测试 5:

代码:

private void OnDrawGizmos()
{
    //center is a value I defined... it is the relative point
    //no need to care about extents... that's just box size
    //first child of the object is just an empty object... shifted by center values... this is always in the intended relative point of the object
    boxPos = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale).inverse.MultiplyPoint(transform.GetChild(0).position);
    Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale);
    Gizmos.color = Color.red;
    Gizmos.DrawWireCube(boxPos, new Vector3(extents.x * 2, extents.y * 2, extents.z * 2));
}

结果:

0-0-0 POSITION: it rendered perfectly as expected.

ROTATION: it works perfectly as expected.

MOVEMENT: it works perfectly as expected.

有一个数学方程可以解决这个问题。假设对象旋转有 Quaternion rotation;,游戏对象有 Vector3 objectPosition;,局部点有 Vector3 point; space,等式是 (rotation * (point-objectPosition)) + objectPosition

Vector3 objectPosition = transform.position;
Quaternion rotation = transform.rotation;
Vector3 point = Vector3(1, 0, 0);
Vector3 worldSpacePoint = (rotation * (point-objectPosition)) + objectPosition;
// if rotation is -90 degrees on the Y axis and objectPosition is zero, worldSpacePoint will be Vector3(0, 0, 1)

对于必须取消旋转和缩放而不是 child 位置的特定用例,我会这样做:

Vector3 boxPos = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.localScale)
        .inverse.MultiplyPoint(transform.GetChild(0).position);

通常情况下,我会说你已经在使用转换,所以只需使用 InverseTransformPoint 来计算 object 的本地位置,如果你想转换回世界位置,你可以使用 TransformPoint:

Transform target;
Vector3 relativePos;

// ...

Vector3 relativePos = transform.InverseTransformPoint(target.position);

// ...

Vector3 worldPos = transform.TransformPoint(relativePos);