Unity3D: 弹跳/反射 Raycast

6

大家好,感谢您的帮助。

我想做的事情相当简单,我想显示一个线渲染器,跟随我的弹跳/反射光线投射。

以下是我目前的进展。

 private LineRenderer lr;

public int maxReflectionCount = 3;
public float maxStepDistance = 200f;


void Start()
{
    lr = GetComponent<LineRenderer>();
}


void Update()
{
    RaycastHit hit;

    if (Physics.Raycast(transform.position, transform.forward, out hit))
    {
        if (hit.collider)
        {
            lr.SetPosition(1, new Vector3(0, 0, hit.distance));

            Reflect(this.transform.position + this.transform.forward * 0.75f, this.transform.forward, maxReflectionCount);


        }
    }
    else
    {
        lr.SetPosition(1, new Vector3(0, 0, 2000));

    }

}


private void Reflect(Vector3 position, Vector3 direction, int reflectionsRemaining)
{

    if (reflectionsRemaining == 0)
    {
        return;
    }


    Vector3 startingPosition = position;


    Ray ray = new Ray(position, direction);
    RaycastHit hit2;
    if (Physics.Raycast(ray, out hit2, maxStepDistance))
    {
        direction = Vector3.Reflect(direction, hit2.normal);
        position = hit2.point;
    }
    else
    {
        position += direction * maxStepDistance;
    }



    Debug.DrawRay(startingPosition, position, Color.green);


    Reflect(position, direction, reflectionsRemaining - 1);


}

似乎Vector3.Reflect是关键,但我无法完全弄清如何正确使用它。
我已经用Gizmos使其部分工作。

Line Bounce w Gizmos

但是我无法在实际项目中使用Gizmos,并且我在使用LineRenderer时遇到了问题。我甚至尝试使用Debug.DrawRay,但没有成功。

我只想用它来展示物体会以什么角度弹回。您有任何想法如何让它工作吗?

非常感谢您的帮助!

编辑1:所以我已经删除了所有的Line Renderer内容,因为我可以稍后再处理,现在我正在按照Hacky的建议进行操作。我仍然无法使其正常工作,但这是目前的情况。

//private LineRenderer lr;

public int maxReflectionCount = 3;
public float maxStepDistance = 200f;

Vector3 reflDirection;
Vector3 hitPosition;


void Start()
{
    //lr = GetComponent<LineRenderer>();
}


void Update()
{
    RaycastHit hit;

    if (Physics.Raycast(transform.position, transform.forward, out hit))
    {
        if (hit.collider)
        {
            //lr.SetPosition(1, new Vector3(0, 0, hit.distance));

            Reflect(this.transform.position + this.transform.forward * 0.75f, this.transform.forward, maxReflectionCount);
        }
    }
    else
    {
        //lr.SetPosition(1, new Vector3(0, 0, 2000));
    }

}


private void Reflect(Vector3 position, Vector3 direction, int reflectionsRemaining)
{

    if (reflectionsRemaining == 0)
    {
        return;
    }


    Vector3 startingPosition = position;


    Ray ray = new Ray(position, direction);
    RaycastHit hit2;
    if (Physics.Raycast(ray, out hit2, maxStepDistance))
    {
        reflDirection = Vector3.Reflect(direction, hit2.normal);
        hitPosition = hit2.point;
    }
    else
    {
        position += reflDirection * maxStepDistance;
    }

    Debug.DrawRay(startingPosition, reflDirection, Color.green, 1);

    //Debug.DrawLine(startingPosition, position, Color.blue);


    Reflect(position, direction, reflectionsRemaining - 1);

}

编辑2(重大进展!): 好的,我已经让射线投射反射起作用了......它很辉煌。

这就是它的样子:

 public int maxReflectionCount = 5;
public float maxStepDistance = 200f;



void Start()
{


}


void Update()
{

    Laser();
}


void Laser()
{
    DrawReflectionPattern(this.transform.position + this.transform.forward * 0.75f, this.transform.forward, maxReflectionCount);
}

private void DrawReflectionPattern(Vector3 position, Vector3 direction, int reflectionsRemaining)
{
    if (reflectionsRemaining == 0)
    {
        return;
    }

    Vector3 startingPosition = position;

    Ray ray = new Ray(position, direction);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, maxStepDistance))
    {
        direction = Vector3.Reflect(direction, hit.normal);
        position = hit.point;
    }
    else
    {
        position += direction * maxStepDistance;
    }

    //Gizmos.color = Color.yellow;
    //Gizmos.DrawLine(startingPosition, position);

    Debug.DrawLine(startingPosition, position, Color.blue);

    DrawReflectionPattern(position, direction, reflectionsRemaining - 1);


}

现在我只需要想办法将线渲染器连接到它上面,我们就可以开始了!
2个回答

0

我看到了两个问题:

  1. 我不知道如何使用vector3.reflect ("Vector3.Reflect似乎是关键,但我无法完全弄清楚如何正确使用它。")
  2. 我不知道如何使用linerenrderer ("我无法让它与LineRenderer一起工作。")

我会在这里尝试回答这些问题: 你使用Vector3.Reflect的方法是正确的。请参考Unity文档中的示例:https://docs.unity3d.com/ScriptReference/RaycastHit-normal.html

首先,用Debug.DrawRay(start,dir,color,duration)或Debug.drawline可视化方程式的结果。使用持续时间为1,以便它在场景中保持可见,并且不会立即消失。 在您的Debug.DrawRay中存在一个错误:Debug.DrawRay的第二个参数是位置的方向,您也没有保存光线的起始位置。所以应该是:

Ray ray = new Ray(position, direction);
RaycastHit hit2;
if (Physics.Raycast(ray, out hit2, maxStepDistance))
{
    reflDirection = Vector3.Reflect(direction, hit2.normal);
    hitPosition = hit2.point;
}
else
{
    position += reflDirection * maxStepDistance;
}

Debug.DrawRay(hitPosition, reflDirection, Color.green);

当这个工作正常时,使用线渲染器在游戏视图中显示它。它只期望位置,不需要方向。请注意不要混淆方向和位置。(将方向添加到位置以获取目标)


谢谢你的帮助!所以我需要另外两个Vector3吗?这就是为什么你添加了reflDirection和hitPosition而不是使用position和direction吗?抱歉,我的编程知识很基础,只是想学习。 - NeatMaddness
哎呀,我甚至都无法让你发布的内容正常工作...好吧,我已经删除了所有的Line Renderer代码,你说得对,我可以稍后再考虑它。我已经输入了你的代码并添加了新的Vector3,但我仍然无法使其正常工作。我会编辑我的帖子向你展示我正在处理的内容。 - NeatMaddness
你有一个不错的递归函数。源代码很好。你只需要在函数开始时保存光线位置和方向的值,以便最后可以使用它。很高兴你做到了。至于linerenderer:它包含一系列位置。为了使其工作,你需要在laser()中清除linerenderer的位置,并在每个DrawReflectionPattern()中添加一个位置。就这些。确保linerenderer对象的变换也完全重置。 - Hacky

0

我想为此添加一些内容,以帮助其他遇到类似问题的人。此外,我想友好地提醒OP接受Hacky的回答作为答案,毕竟它确实回答了问题。

对于我的输入,我只想指出应尽可能避免使用递归函数,因为每次调用函数都会复制传递给它作为参数的所有值类型,并且它可能会保留所有先前调用的变量,直到最后一个函数可以终止。不要引用我说的最后一部分。我建议使用循环来完成这个任务,它可以轻松地完成你最终所做的事情,同时节省了调用函数的任何开销和每次需要复制的值。这是我对你的“DrawReflectionPattern”函数的看法:

private void TraceReflection(Vector3 startPosition, Vector3 direction, int reflectionsRemaining) {
    for (Vector3 endPosition; (reflectionsRemaining>0); reflectionsRemaining--, startPosition = endPosition) {  
        if (Physics.Raycast(startPosition, direction, out RaycastHit hit, maxStepDistance)) {
            direction = Vector3.Reflect(direction, hit.normal);
            endPosition = hit.point;
        } else {
            endPosition = startPosition + (direction * maxStepDistance);
        }
        Debug.DrawLine(startPosition, endPosition, Color.blue);
    }
}

你还可以做很多事情使它更好,比如在 for 循环之前定义 hit 变量,但我认为这仍然说明了如何使用循环而不是递归函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接