使用对象来回旋转 raycast2D

Posted

技术标签:

【中文标题】使用对象来回旋转 raycast2D【英文标题】:Rotating raycast2D back and forth with object 【发布时间】:2022-01-09 20:54:53 【问题描述】:

我做了一个圆圈,并在上面附加了一个激光盒。

激光将向其上 y 轴(垂直向上)发射光线投射。我还添加了一个线渲染器来查看它。

我希望光线投射来回旋转 90 度。有点像它扫描顶部的所有内容。我的问题是它不能正常工作。它确实来回旋转,但如果我移动激光物体的 x 位置,光线投射将以一个奇怪的角度旋转。

激光物体的脚本

public LineRenderer lineRenderer;
public LayerMask layerMask;
public float laserSpeed;

Vector3 pointA;
Vector3 pointB;
Vector3 castPosition;
RaycastHit2D rayCast;

float time;

void Start()

    pointA = transform.eulerAngles + new Vector3(0f, 0f, 90f);

    pointB = transform.eulerAngles + new Vector3(0f, 0f, -90f);


void Update()

    time = Mathf.PingPong(Time.time * laserSpeed, 1);
    transform.eulerAngles = Vector3.Lerp(pointA, pointB, time);
    castPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z);
    rayCast = Physics2D.Raycast(castPosition, transform.TransformDirection(Vector2.up), 10f, layerMask);

    lineRenderer.SetPosition(0, castPosition);
    lineRenderer.SetPosition(1, transform.TransformDirection(Vector2.up) * 10f);
        

【问题讨论】:

@derHugo 好吧,我刚开始统一,所以我把一小段代码混合在一起。你能展示一下正确的做法吗? 【参考方案1】:

eulerAngles 用于连续动画非常“危险”。 Unity 将旋转存储为Quaternion,并且有多种方法可以在欧拉空间中表示它们!

当您阅读.eulerAngles 属性时,Unity 会将Quaternion 的内部旋转表示转换为欧拉角。因为,使用欧拉角表示任何给定旋转的方法不止一种,因此您读出的值可能与您分配的值完全不同。如果您尝试逐渐增加值以生成动画,这可能会导致混淆。

为避免此类问题,推荐使用旋转的方法是在阅读.eulerAngles 时避免依赖一致的结果,尤其是在尝试逐渐增加旋转以产生动画时。有关实现此目的的更好方法,请参阅Quaternion * operator

所以你应该去Quaternion 并做例如

然后您使用transform.TransformDirection(Vector2.up),这是一个方向,并将其作为位置传递给您的线渲染器。

你想要的,其实是组合的位置

transform.position + transform.up

所以应该是在一起吧

public LineRenderer lineRenderer;
public LayerMask layerMask;
public float laserSpeed;

private Quaternion originalRotation;
private Quaternion minRotation;
private Quaternion maxRotation;

void Start()

    originalRotation = transform.rotation;

    minRotation = originalRotation * Quaternion.Euler(0, 0, -90);
    maxRotation = originalRotation * Quaternion.Euler(0, 0, 90);


void Update()

    // Note that Vector3 is a "struct" -> there is no need to manually use "new Vector3(transform.position.x, ...)"
    var startPosition = transform.position;

    lineRenderer.SetPosition(0, startPosition);
    
    var factor = Mathf.PingPong(Time.time * laserSpeed, 1);

    // instead of the eulers rather use Quaternion
    transform.rotation = Quaternion.Lerp(minRotation, maxRotation, factor);

    // "transform.up" basically equals using "transform.TransformDirection(Vector3.up)"
    var rayCast = Physics2D.Raycast(startPosition, transform.up, 10f, layerMask);

    if(rayCast.collider)
    
        // when you hit something actually use this hit position as the end point for the line
        lineRenderer.SetPosition(1, rayCast.point);
    
    else
    
        // otherwise from the start position go 10 units in the up direction of your rotated object
        lineRenderer.SetPosition(1, startPosition + transform.up * 10f);
      

【讨论】:

感谢您的详尽解释。效果很好! @stalwart1014 如果有帮助,别忘了accept这个答案!

以上是关于使用对象来回旋转 raycast2D的主要内容,如果未能解决你的问题,请参考以下文章

Axure RP 8来回旋转

OpenGL学习——变换——绕x轴来回旋转的木板

使用加速度计计算旋转矩阵

在动画中使用 Step 函数来变换旋转元素

在点之间来回移动 3d 对象

在 Flex 中,如何在 MXML 应用程序文件和 MXML 组件文件之间来回传递 var 对象