【问题标题】:How can I rotate the capsule to look at the next position while reaching the current position?如何在到达当前位置时旋转胶囊以查看下一个位置?
【发布时间】:2021-05-21 07:43:38
【问题描述】:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class WaypointsFollower : MonoBehaviour
{
    public float speed;
    public Waypoints waypoints;
    public Transform capsule;
    public bool go;
    public bool goForward;
    public float rotationSpeed;

    private int index = 0;
    private int counter = 0;
    private int c = 0;
    private List<GameObject> curvedLinePoints = new List<GameObject>();

    public int numofposbetweenpoints;

    private bool getonce;
    private bool getBackwardIndexOnce = true;

    private void Start()
    {
        waypoints = GameObject.Find("Waypoints").GetComponent<Waypoints>();

        curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();

        if(waypoints.moveInReverse == false)
        {
            goForward = true;
        }
        else
        {
            goForward = false;
        }

        if(goForward)
        {
            index = 0;
        }
    }

    private void Update()
    {
        if (getonce == false)
        {
            numofposbetweenpoints = curvedLinePoints.Count;

            getonce = true;
        }

        if (go == true && waypoints.lineRendererPositions.Count > 0)
        {
            if(goForward == false && getBackwardIndexOnce)
            {
                index = waypoints.lineRendererPositions.Count - 1;

                getBackwardIndexOnce = false;
            }

            Move();
        }
    }

    private void Move()
    {
        Vector3 newPos = transform.position;
        float distanceToTravel = speed * Time.deltaTime;

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

            // error exception out of bound on line 55 to check !!!!!
            newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);

            distanceToTravel -= Vector3.Distance(newPos, oldPos);

            if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
            {
                // when you hit a waypoint:
                if (goForward)
                {
                    bool atLastOne = index >= waypoints.lineRendererPositions.Count - 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;
    }

    private void RotateTo()
    {
        // Determine which direction to rotate towards
        Vector3 targetDirection = -capsule.position;

        // The step size is equal to speed times frame time.
        float singleStep = rotationSpeed * Time.deltaTime;

        // Rotate the forward vector towards the target direction by one step
        Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

        // Draw a ray pointing at our target in
        Debug.DrawRay(capsule.position, newDirection, Color.red);

        // Calculate a rotation a step closer to the target and applies rotation to this object
        capsule.rotation = Quaternion.LookRotation(newDirection);
    }
}

变换沿航点移动,但我希望胶囊面向每个 numofposbetweenpoints 旋转。

有很多路点或多或少超过 4000 个,但点之间只有 10 个 numofpos。 此屏幕截图将清除它。 waypoints 是 linerenderer 的位置,numofposbetweenpoints 是连接线渲染器线的每条线的立方体。

Clear image

在屏幕截图中,大立方体是脚本中的变换,该变换沿着作为 linerenderer 位置的 ping 线移动。背景中的小方块是linerenderer线的连接点。

我希望胶囊在每次变换移动时平滑地旋转观察 numofposbetweenpoints(小立方体),胶囊应该平滑地旋转观察下一个 numofposbetweenpoints。 numofposbetweenpoints 只有 10 个。

这是底部的旋转部分:

private void RotateTo()
        {
            // Determine which direction to rotate towards
            Vector3 targetDirection = -capsule.position;
    
            // The step size is equal to speed times frame time.
            float singleStep = rotationSpeed * Time.deltaTime;
    
            // Rotate the forward vector towards the target direction by one step
            Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
    
            // Draw a ray pointing at our target in
            Debug.DrawRay(capsule.position, newDirection, Color.red);
    
            // Calculate a rotation a step closer to the target and applies rotation to this object
            capsule.rotation = Quaternion.LookRotation(newDirection);
        }

在这一行,它每次都缺少下一个小立方体:

Vector3 targetDirection = -capsule.position;

我有小立方体 numofposbetweenpoints 的数量,但我如何获得对每个小立方体的引用并使 numofposbetweenpoints 索引每次都增加?

我在第 50 行:

numofposbetweenpoints = curvedLinePoints.Count;

curvedLinePoints 是一个列表,但我不确定如何对列表中的游戏对象进行旋转。

这是我到目前为止所做的,我认为轮换正在起作用,但不是我想要的:

在顶部我添加了:

private int rotationIndex = 0;

然后在 RotateTo 我将其更改为:

private void RotateTo()
    {
        var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
        if(distance < 0.1f)
        {
            rotationIndex++;
        }

        // Determine which direction to rotate towards
        Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;

        // The step size is equal to speed times frame time.
        float singleStep = rotationSpeed * Time.deltaTime;

        // Rotate the forward vector towards the target direction by one step
        Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

        // Draw a ray pointing at our target in
        Debug.DrawRay(capsule.position, newDirection, Color.red);

        // Calculate a rotation a step closer to the target and applies rotation to this object
        capsule.rotation = Quaternion.LookRotation(newDirection);
    }

两个问题:

  1. 即使我将旋转速度设置为 30,它的旋转速度仍然有点慢。为什么 30 这么慢?

  2. 旋转是在这个屏幕截图中的所有轴上,但我希望它只在 Y 轴上旋转,但是因为要使胶囊站立,我必须在 Y 轴上旋转时将 X 设置为 -90,它会改变胶囊 -喜欢缩放它。我希望胶囊能像自己一样旋转。

Rotation

这是在游戏开始旋转之前运行游戏时胶囊在原版中的样子:

Rotation at start

【问题讨论】:

  • 为了清楚起见,您想以相同的速度沿当前对象的方向旋转对象吗?或者想立即旋转到列表中的下一个对象curvedLinePoints,同时向它移动?
  • @TEEBQNE 朝着它前进。但请注意,变换正在朝着,但我希望胶囊旋转。变换是移动胶囊旋转到列表曲线线点中的下一个对象的变换。你明白了。
  • @TEEBQNE 更新了我的问题,包括我做了什么、结果是什么以及我希望它是什么样的。我有两个问题。
  • 刚刚回来并能够回答您更新的问题。如果您需要更多信息/详细信息,或者第二个 sn-p 不起作用,请告诉我。

标签: c# unity3d


【解决方案1】:

回答您新增的两个问题:

  1. 即使我将旋转速度设置为 30,它的旋转速度仍然有点慢。为什么 30 这么慢?

您当前的时间步长设置为rotationSpeed * Time.deltaTime。正如您所提到的,rotationSpeed 现在是 30,但Time.deltaTime 是什么? Time.deltaTime 是帧之间的秒数,表示它是 1 / framesPerSecond。通常帧率约为 60,因此对于示例,我们将其命名为 1/600.016666667。当乘以30 的常数时,我们得到30/600.5

您在RotateTowards 中使用的参数是maxRadiansDelta。来自wiki,这个参数是:

此旋转允许的最大弧度角。

至于为什么你的旋转可以被定义为慢,你的移动速度大约是0.5 弧度/秒。如果将此值从 30 增加到 60 之类的值,那么您将移动到每秒 1.0 弧度,依此类推。

  1. 旋转是在这个屏幕截图中的所有轴上,但我希望它只在 Y 轴上旋转,但是因为要使胶囊站立,我必须在 Y 轴上旋转时将 X 设置为 -90,它正在改变胶囊 -喜欢缩放它。我希望胶囊能够像自己一样旋转。

这里的问题是RotateTowards 会将您的对象定向到所有轴上,以直接向前移动并将其指向您的目标变换。我相信这样的事情会奏效吗?

Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);

newDirection.z = 0f;

capsule.rotation = Quaternion.LookRotation(newDirection, capsule.Up);

我相信上面的 sn-p 应该只围绕 Y 轴旋转对象。告诉我进展如何。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-21
    • 2016-06-07
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多