如何将立方体的旋转与四边形相匹配,以便在我移动它时它保持平整?

How do I match the rotation of a cube to a quad so it stays flat on it as I move it?

为简单起见,我只是尝试沿着成一定角度的四边形绘制箭头预制件。无论它处于什么位置,我都需要它平放在它上面(稍微凸起)。

我现在正在做的是为箭身准备一个立方体,为头部准备一个“三角形”预制件。我在屏幕上单击以获取“开始位置”(使用光线投射命中点以确保我在下面的旋转四边形上方),然后当我在它周围拖动鼠标时更新“结束位置”向量 3。我只需计算两点之间的距离,看看“localScale.y”将其扩展多少,这对箭头长度非常有效。对于头部,我只是将它附加到“终点”,所以它只是跟随鼠标。

我遇到的问题是它没有在四边形 上保持“平坦”,四边形在 X 处旋转了 70 度(在检查器中)。因此,当我移动并旋转鼠标时,它会围绕长度轴旋转。

这是我的代码:

 if (Physics.Raycast(mouseRay, out hit))
        {
            arrowEndPoint = hit.point;

            // Get rotation of Quad
            quadRotation = rotatedQuad.transform.rotation.eulerAngles.x;
            var arrowBodyRotation = simpleArrowBody.transform.rotation.eulerAngles;
            var arrowHeadRotation = simpleArrowHead.transform.rotation.eulerAngles;

            arrowBodyRotation.x = quadRotation;     // Doesn't seem to be affecting it
            arrowHeadRotation.x = quadRotation;

            // Follow arrow head to mouse
            simpleArrowHead.transform.position = arrowEndPoint;

            // Get distance between Start and End point
            arrowLength = Vector3.Distance(arrowStartPoint, arrowEndPoint);

            // Direction based on the start and end points
            var direction = (arrowEndPoint - arrowStartPoint).normalized;

            // Adjust scale and rotation of Body
            simpleArrowBody.transform.localScale = new Vector3(simpleArrowBody.transform.localScale.x, arrowLength, simpleArrowBody.transform.localScale.z);
            simpleArrowBody.transform.up = direction; 

            // Adjust rotation of Head
            simpleArrowHead.transform.up = direction;
            simpleArrowHead.transform.up = -rotatedQuad.transform.forward; // Didn't work
        }
  quadRotation = rotatedQuad.transform.rotation.eulerAngles.x;
  var arrowBodyRotation = simpleArrowBody.transform.rotation.eulerAngles;
  var arrowHeadRotation = simpleArrowHead.transform.rotation.eulerAngles;

  arrowBodyRotation.x = quadRotation;     // Doesn't seem to be affecting it
  arrowHeadRotation.x = quadRotation;

当然这个一点作用都没有!

您只是将其分配给局部变量 Vector3(这是一个 struct,因此是一个 复制值 )。

如果你想实际应用它,你会例如使用

quadRotation = rotatedQuad.transform.rotation.eulerAngles.x;
var arrowBodyRotation = simpleArrowBody.transform.rotation.eulerAngles;
var arrowHeadRotation = simpleArrowHead.transform.rotation.eulerAngles;

arrowBodyRotation.x = quadRotation;
arrowHeadRotation.x = quadRotation;

simpleArrowBody.transform.rotation.eulerAngles = arrowBodyRotation;
simpleArrowHead.transform.rotation.eulerAngles = arrowHeadRotation;

但是 请注意 eulerAngles 对他来说非常不可靠!

直接使用旋转通常很棘手。所以我通常更喜欢使用向量,因为我更了解它们 ;)

我会做的是

  • 而是以一种“正常”定向的方式设计你的箭头。这意味着它指向本地 Z(向前) 方向,面向你的方向是它的本地向上方向。在这种情况下,Unity 提供了辅助方法。

  • 然后您可以简单地将 Quaternion.LookRotation 与您的 direction 一起使用,并将向上矢量传递给 -rotatedQuad.transform.forward

例如

public class Example : MonoBehaviour
{
    public Transform rotatedQuad;
    public Transform simpleArrowHead;
    public Transform simpleArrowBody;

    private Vector3? arrowStartPoint;

    private void Update()
    {
        var mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Input.GetMouseButtonDown(0) && Physics.Raycast(mouseRay, out var hit))
        {
            arrowStartPoint = hit.point;
        }
        else if (arrowStartPoint.HasValue && Input.GetMouseButton(0) && Physics.Raycast(mouseRay, out hit))
        {
            var arrowEndPoint = hit.point;

            // Get distance between Start and End point
            var delta = arrowEndPoint - arrowStartPoint.Value;
            var arrowLength = delta.magnitude;

            // Direction based on the start and end points
            var direction = delta.normalized;

            // Adjust position, scale and rotation of Body
            var scale = simpleArrowBody.localScale;
            scale.z = arrowLength;
            simpleArrowBody.localScale = scale;
            // make the forward point into the direction while maintaining the 
            // up vector aligned with the quad surface
            simpleArrowBody.rotation = Quaternion.LookRotation(direction, -rotatedQuad.forward);
            // place at center between start and end
            simpleArrowBody.position = arrowStartPoint.Value + delta / 2f;

            // Follow arrow head to mouse and adjust rotation of Head
            simpleArrowHead.position = arrowEndPoint;
            // make the forward point into the direction while maintaining the 
            // up vector aligned with the quad surface
            simpleArrowHead.rotation = Quaternion.LookRotation(direction, -rotatedQuad.forward);
        }
    }
}