使用多个位置使LineRenderer绘制动画

3

我有一个 LineRenderer,其中包含许多位置,我正在尝试从点a -> b,b ->c等位置对该线进行动画处理...

首先,我保存了线的所有位置,然后重置了 positionCount,这样在开始时它就不可见。但是当我在循环中绘制 lineRenderer,每次迭代增加 positionCount,并且在绘制下一条线时,之前的线会微微晃动并瞬间改变宽度。

以下是代码:

public float LineDrawSpeed;

void Start()
{
  lineRenderer = GetComponent<LineRenderer>();
  int lineCountInLineRenderer = lineRenderer.positionCount - 1;
  var startPositions = new Vector3[lineRenderer.positionCount];
  lineRenderer.GetPositions(startPositions);
  lineRenderer.positionCount = 1;
  StartCoroutine(LineDrawCoroutine(startPositions));
}

这里是协程:

IEnumerator LineDrawCoroutine(Vector3[] positions)
{
  for (int i = 0; i < positions.Length - 1; i++)
  {
    if (lineRenderer.positionCount <= i + 1)
    lineRenderer.positionCount++;

    lineRenderer.SetPosition(i, positions[i]);
    float timePass = 0f;
    while (timePass < LineDrawSpeed)
    {
      var factor = timePass / LineDrawSpeed;
      factor = Mathf.SmoothStep(0, 1, factor);

      lineRenderer.SetPosition(i + 1, Vector3.Lerp(positions[i], positions[i + 1], factor));

      timePass += Mathf.Min(Time.deltaTime, LineDrawSpeed - timePass);
      yield return null;
    }
  }
}

机制运作良好,但动画方面出现了一些问题。

1
@whathm 是的,确切地说。如何在不出现奇怪的线条视觉变化的情况下,对许多位置进行LR动画处理。 - Fletchet
你是想画曲线还是直线? - Jee
1
@whathm,直线。 - Fletchet
1
明白了。我在下面添加了一个解决方案。如果这个解决方案对你有用,请告诉我! - Jee
1
如果我理解你的意思正确的话,那就是我的代码基本上就是这样做的,所以我认为你应该没问题。我在开始时设置了positionCount,然后只是设置其中的向量,而不是增加实际的positionCount值。 - Jee
显示剩余2条评论
2个回答

2
我发现这个宽度变化的主题相当有趣。据我查证,需要考虑两个重要点。
1. LineRenderer 渲染广告牌线条。

https://docs.huihoo.com/unity/5.3/Documentation/en/Manual/class-LineRenderer.html

广告牌是嵌入在3D世界中的2D元素,其方向会自动计算,使其始终面向相机。这解释了随着相机移动而产生的宽度变化。
如果相机没有移动,请注意以下内容:根据文档定义,宽度属性定义为:“一个宽度值和一个曲线值,用于控制沿其长度的路径宽度。曲线在每个顶点处采样,因此其准确性受路径中顶点数量的限制。路径的整体宽度由宽度值控制。”

https://docs.unity3d.com/Manual/class-LineRenderer.html

“因此,当您动态更改线的顶点时,您的路径的整体宽度可能会发生变化。”
“因此,我认为您的算法运行良好,并且宽度变化是与线渲染器组件一起出现的。”

1
谢谢您的解释。也许可以在不改变位置计数的情况下绘制LineRenderer。我会朝这个方向去看。我不想在每条A-B线上创建单独的LR。我希望能够在一个LR中完成我的画线动画。 - Fletchet
我没有想到那个。您可以使用一个脚本处理多个LR并循环遍历它们。如果它们都具有相同的宽度,则可以解决或最小化宽度问题... - rustyBucketBay
你的意思是在每一行简单的代码上都创建一个单独的LR吗? - Fletchet
是的,我的意思是为每个部分创建一个带有LR的游戏对象,然后创建一个全局控制器对象,并引用每个对象,以便您可以根据动画逻辑循环遍历它们,并检查是否存在宽度变化问题...不过这是你的想法 ;) - rustyBucketBay

1
我相信你的问题在于你一遍又一遍地增加了位置计数。虽然不是100%确定。
无论如何,以下是逐步增加线条长度的工作代码。它只是一个IEnumerator,但您可以在StartCoroutine中调用它,它应该可以工作。
这将适用于直线,但对于曲线需要进行一些调整(但如果您愿意,则可以使其工作)。
为了更好地解释这一点,我没有增加positionCount并添加向量,而是将positionCount设置为所需的向量数量,然后逐步填充每个向量的所需位置。当一开始就设置它们时,它们默认为0,0,0,因此请确保这不会给您带来任何问题。
以下是我使用的代码:
//  Using IEnumerator to ensure that the line is drawn over a specific amount of time
private IEnumerator DrawLine()
{
    float renderTime = 2f;                                      // total time for full line render
    int renderSteps = 75;                                       // desired resolution of render (higher amt of steps creates smoother render)
    float timeBetweenSteps = renderTime / renderSteps;          // time between each render step

    //  Grab the LineRenderer component that is attached to the gameObject and defined in Inspector
    LineRenderer lineRenderer = yourGameObject.GetComponent<LineRenderer>();

    //  Declare the endpoint
    Vector3 endPoint = new Vector3(0, 5, 0);

    //  Take the end point and break into the amount of steps we need in order to create 
    //  fully rendered line
    //  Create an additiveVector for the forLoop that will step through the renderSteps
    //  >>  Start at zero becuase zero is the localOrigin
    Vector3 stepVector = endPoint / renderSteps;
    Vector3 additiveVector = Vector3.zero;

    //  Setting the line's position element count to the render resolution because we will
    //  have to step through 
    lineRenderer.positionCount = renderSteps;

    //  For Loop that steps through each position element in the Line
    for (int i = 0; i != lineRenderer.positionCount; i++)
    {
        lineRenderer.SetPosition(i, additiveVector);            // set the position element to the additiveVEctor
        additiveVector += stepVector;                           // add one step to the additiveVector
        yield return new WaitForSeconds(timeBetweenSteps);      // Wait the appropriate step time before repeating the loop
    }
}

如果您有任何问题,请告诉我。希望这能帮到您!


它不能正常工作。因为我已经在检查器中设置了positionCount,而这会将其设置为renderSteps。顺便说一句,它只绘制一条线并为其设置75个位置:D 嗯,线宽的问题仍然存在。 - Fletchet
@Fletchet 把 renderSteps 方法移出来,放到你的主方法里。然后像你在原始示例中那样将其传递给 Enumerator。是的,我知道它会这样做。这是为了预设线条应该按照什么增量进行动画处理。至于宽度,如果我的代码仍然导致宽度问题,那么很可能是你在检查器中设置的 LineRenderer 的问题,因为我可以将此代码复制并粘贴到新项目中而没有任何问题... 如果你仍然有问题,请告诉我。 - Jee
我使用内部循环,其中我将每个下一个点除以75并设置其位置。将所有点归零不起作用,因为屏幕上可见点0,0,0,但当我开始协程时,我会在开始时执行SetPosition(0, myPos[0]),然后在循环中当我执行SetPosition(i, nextPos)时,就会出现与零点相关的奇怪伪影。 - Fletchet

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