【问题标题】:How can I make the transform rotating smooth facing each waypoint?如何使变换旋转平滑面对每个航路点?
【发布时间】:2021-04-08 05:36:59
【问题描述】:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class MoveOnCurvedLines : MonoBehaviour
{
    public LineRenderer lineRenderer;
    public float speed;
    public bool go = false;
    public bool moveToFirstPositionOnStart = false;
    public float rotSpeed;
    public bool random = false;
    public int currentCurvedLinePointIndex;

    private Vector3[] positions;
    private Vector3[] pos;
    private int index = 0;
    private bool goForward = true;
    private List<GameObject> curvedLinePoints = new List<GameObject>();
    private int numofposbetweenpoints;
    private bool getPositions = false;
    int randomIndex;
    int curvedPointsIndex;

    // Start is called before the first frame update
    void Start()
    {
        curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();

        if (curvedLinePoints != null && curvedLinePoints.Count > 0)
        {
            transform.rotation = curvedLinePoints[1].transform.rotation;
        }

        if (random)
            GetNewRandomIndex();
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        positions = new Vector3[lineRenderer.positionCount];
        //Get the positions which are shown in the inspector 
        lineRenderer.GetPositions(positions);


        //the points returned are in world space
        return positions;
    }

    // Update is called once per frame
    void Update()
    {
        if (lineRenderer.positionCount > 0 && getPositions == false)
        {
            pos = GetLinePointsInWorldSpace();
            numofposbetweenpoints = pos.Length / curvedLinePoints.Count;

            if (moveToFirstPositionOnStart == true)
            {
                transform.position = pos[index];
            }

            getPositions = true;
        }

        if (go == true && lineRenderer.positionCount > 0)
        {
            Move();

            transform.localRotation = Quaternion.RotateTowards(transform.localRotation, curvedLinePoints[c].transform.localRotation, Time.deltaTime * rotSpeed);
        }

        var dist = Vector3.Distance(transform.position, curvedLinePoints[curvedPointsIndex].transform.position);
        if (dist < 0.1f)
        {
            if (curvedPointsIndex < curvedLinePoints.Count - 1)
                curvedPointsIndex++;

            currentCurvedLinePointIndex = curvedPointsIndex;
        }
    }

    int counter = 0;
    int c = 1;
    void Move()
    {
        Vector3 newPos = transform.position;
        float distanceToTravel = speed * Time.deltaTime;

        bool stillTraveling = true;
        while (stillTraveling)
        {
            Vector3 oldPos = newPos;

            newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);

            distanceToTravel -= Vector3.Distance(newPos, oldPos);
            if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
            {
                // when you hit a waypoint:
                if (goForward)
                {
                    bool atLastOne = index >= pos.Length - 1;
                    if (!atLastOne)
                    {
                        index++;
                        counter++;
                        if (counter == numofposbetweenpoints)
                        {
                            c++;
                            
                            counter = 0;
                        }
                        if (c == curvedLinePoints.Count - 1)
                        {
                            c = 0;
                        }
                    }
                    else { index--; goForward = false; }
                }
                else
                { // going backwards:
                    bool atFirstOne = index <= 0;
                    if (!atFirstOne)
                    {
                        index--;

                        counter++;
                        if (counter == numofposbetweenpoints)
                        {
                            c++;
                            
                            counter = 0;
                        }
                        if (c == curvedLinePoints.Count - 1)
                        {
                            c = 0;
                        }
                    }
                    else { index++; goForward = true; }
                }
            }
            else
            {
                stillTraveling = false;
            }
        }

        transform.position = newPos;
    }
}

在更新这一行中旋转变换:

transform.localRotation = Quaternion.RotateTowards(transform.localRotation, curvedLinePoints[c].transform.localRotation, Time.deltaTime * rotSpeed);

但首先它不应该与 'c' int 变量一起使用,因为计算错误,List curveLinePoints 中有 30 个立方体。但是当使用 numofposbetweenpoints 变量进行计算时,numofposbetweenpoints 中只有 20 个,然后当增加“c”变量时,它只会增加 20 而不是 30,但也许我在这部分错了。

第二个它根本不旋转。

在屏幕截图中,平台是移动的对象。创建楼梯的Cubes是curvedLinePoints List。

平台正在沿着立方体之间的 LineRenderer 位置移动,但我希望平台将面向弯曲线点列表中的立方体而不是 LineRenderer 位置旋转!

在数组 pos 上有 610 个位置,但我希望变换面向每个弯曲线点旋转。

在我看来,我认为当平台到达最后一个位置然后开始向下移动时,平台应该旋转绿色轴应该面朝下,因为平台现在正在向下移动,所以它应该看着曲线点正在向下的方向,但平台一直向前看,从不旋转到它正在移动的方向。

当平台到达/通过最后一个弯曲线点时,我认为这就是逻辑上应该是这样的。

【问题讨论】:

  • 很高兴看到my answer 仍在帮助人们。游戏应该如何知道沿着移动轨迹的每个位置使用哪个旋转航路点?您需要某种方式告诉代码在每个航路点之间转弯的速度。我猜假设平台具有恒定的旋转速度是不正确的。最简单的方法是只拥有与位置航点相同数量的方向航点,并在它们之间进行插值。

标签: c# unity3d


【解决方案1】:

如果您有与位置航路点相同数量的旋转航路点,您可以确定每个位置航路点的旋转,然后在它们之间进行插值。只是,跟踪前进方向,最后使用LookRotation 转换为旋转:

void Move()
{
    Vector3 newPos = transform.position;
    Vector3 newDir = transform.forward;

    float distanceToTravel = speed * Time.deltaTime;

    bool stillTraveling = true;
    while (stillTraveling)
    {
        Vector3 oldPos = newPos;
        Vector3 oldDir = newDir;

        float distanceToNext = Vector3.Distance(oldPos, pos[index]);

        newPos = Vector3.MoveTowards(oldPos, pos[index], distanceToTravel);

        newDir = curvedLinePoints[index] - pos[index];
        newDir.z = 0; // look directly ahead

        if ( distanceToNext >= distanceToTravel)
        {  
            // How far from oldPos tonewPos 
            float t = Mathf.InverseLerp(0, distanceToNext, distanceToTravel); 
            newDir = Vector3.Slerp(oldDir, newDir, t);
        }

        distanceToTravel -= Vector3.Distance(oldPos, newPos);
        if (newPos == pos[index]) // Vector3 comparison is approximate so this is ok
        {
            // when you hit a waypoint:
            if (goForward)
            {
                bool atLastOne = index >= pos.Length - 1;
                if (!atLastOne)
                {
                    index++;
                    counter++;
                    if (counter == numofposbetweenpoints)
                    {
                        c++;
                        
                        counter = 0;
                    }
                    if (c == curvedLinePoints.Count - 1)
                    {
                        c = 0;
                    }
                }
                else { index--; goForward = false; }
            }
            else
            { // going backwards:
                bool atFirstOne = index <= 0;
                if (!atFirstOne)
                {
                    index--;

                    counter++;
                    if (counter == numofposbetweenpoints)
                    {
                        c++;
                        
                        counter = 0;
                    }
                    if (c == curvedLinePoints.Count - 1)
                    {
                        c = 0;
                    }
                }
                else { index++; goForward = true; }
            }
        }
        else
        {
            stillTraveling = false;
        }
    }
    transform.position = newPos;
    transform.rotation = Quaternion.LookRotation(newDir);
}

【讨论】:

  • 我在此行的编辑器中遇到异常:newDir = curveLinePoints[index].transform.position - pos[index];超出范围。有 30 个曲线点和 601 个 pos 平台应该变换并在 pos 数组 601 位置之间移动,但应该只面向曲线点旋转,索引根据 pos 号 601 增加
  • @user1196715 答案说您需要拥有与方向航点相同数量的位置航点。每个位置航路点都应该有一个方向航路点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多