Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么反过来不起作用?如何添加旋转部分?_C#_Unity3d - Fatal编程技术网

C# 为什么反过来不起作用?如何添加旋转部分?

C# 为什么反过来不起作用?如何添加旋转部分?,c#,unity3d,C#,Unity3d,文章有点长,但两个脚本都是相互连接的。我试图减少代码量 Waypoints脚本附加到空游戏对象上,我在其中添加了一个旋转部分: [Header("Rotation")] public Quaternion rotationTothinkWhatToDoHere; 但我不知道如何在Waypoints脚本和Waypoints Follower脚本中使用它 using System.Collections; using System.Collections.Generic; us

文章有点长,但两个脚本都是相互连接的。我试图减少代码量

Waypoints脚本附加到空游戏对象上,我在其中添加了一个旋转部分:

[Header("Rotation")]
public Quaternion rotationTothinkWhatToDoHere;
但我不知道如何在Waypoints脚本和Waypoints Follower脚本中使用它

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Cinemachine;

public class Waypoints : MonoBehaviour
{
    [Header("Objects To Move")]
    public Transform objectToMovePrefab;
    public int numberOfObjectsToMove = 1;
    public bool moveInReverse = false;

    [Header("Speed")]
    public float speed;
    public bool randomSpeed = false;
    public float minRandomSpeed = 1;
    public float maxRandomSpeed = 100;
    private bool changeSpeedOnce = false;

    [Header("Rotation")]
    public Quaternion rotationTothinkWhatToDoHere;

    [Header("Waypoints")]
    [SerializeField] private List<Transform> waypoints;
    public bool moveOnWaypoints = false;

    [Header("Delay")]
    public bool useDelay = false;
    public float delay = 3;
    public bool randomDelay = false;
    public float minRandomDelay = 0.3f;
    public float maxRandomDelay = 5;

    [Header("LineRenderer")]
    public LineRenderer lineRenderer;
    public bool moveOnLineRenderer = false;
    public List<Vector3> lineRendererPositions = new List<Vector3>();

    [Header("Cinemachine Cameras")]
    public CinemachineVirtualCamera virtualCamera;

    private List<WaypointsFollower> waypointsFollowers = new List<WaypointsFollower>();

    private void Start()
    {
        for (int i = 0; i < numberOfObjectsToMove; i++)
        {
            var parent = GameObject.Find("Moving Object Parent");
            var objectToMove = Instantiate(objectToMovePrefab, parent.transform);
            objectToMove.name = "Platfrom";

            waypointsFollowers.Add(objectToMove.GetComponent<WaypointsFollower>());
        }

        virtualCamera.Follow = waypointsFollowers[0].gameObject.transform;
        virtualCamera.LookAt = waypointsFollowers[0].gameObject.transform;

        foreach (WaypointsFollower wpf in waypointsFollowers)
        {
            wpf.goForward = moveInReverse;
        }

        WaypointsMovementStates();

        SpeedUpdater();

        if (useDelay)
            StartCoroutine(SendObjectstomoveWithDelay());
    }

    private void Update()
    {
        lineRendererPositions.Clear();
        lineRendererPositions.AddRange(GetLinePointsInWorldSpace());

        SpeedUpdater();
    }

    IEnumerator SendObjectstomoveWithDelay()
    {
        {
            foreach (WaypointsFollower follower in waypointsFollowers)
            {
                if (randomDelay)
                {
                    delay = Random.Range(minRandomDelay, maxRandomDelay);
                }

                yield return new WaitForSeconds(delay);

                follower.go = true;
            }
        }
    }

    private void SpeedUpdater()
    {
        if (changeSpeedOnce == false)
        {
            foreach (WaypointsFollower follower in waypointsFollowers)
            {
                if (randomSpeed)
                {
                    follower.speed = Random.Range(minRandomSpeed, maxRandomSpeed);
                }
                else
                {
                    follower.speed = speed;
                }
            }

            changeSpeedOnce = true;
        }
    }

    Vector3[] GetLinePointsInWorldSpace()
    {
        var 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;
    }

    private void WaypointsMovementStates()
    {
        // If moving on both linerenderer positions and waypoints objects
        if (moveOnLineRenderer && moveOnWaypoints && waypoints.Count > 0)
        {
            if (useDelay == false)
            {
                foreach (WaypointsFollower wpf in waypointsFollowers)
                {
                    wpf.go = true;
                }
            }
        }


        // If moving on linerenderer positions only without moving on waypoints objects
        if (moveOnLineRenderer && moveOnWaypoints == false)
        {
            if (waypoints.Count > 0)
                waypoints.Clear();

            if (useDelay == false)
            {
                foreach (WaypointsFollower wpf in waypointsFollowers)
                {
                    wpf.go = true;
                }
            }
        }


        // If only to move on waypoints objects without moving on linerenderer positions
        if (moveOnWaypoints && waypoints.Count > 0 && moveOnLineRenderer == false)
        {
            lineRendererPositions.Clear();

            foreach (Transform wp in waypoints)
            {
                lineRendererPositions.Add(wp.position);
            }

            if (useDelay == false)
            {
                foreach (WaypointsFollower wpf in waypointsFollowers)
                {
                    wpf.go = true;
                }
            }
        }

        if(moveInReverse)
        {
            foreach (WaypointsFollower wpf in waypointsFollowers)
            {
                wpf.go = true;
            }
        }
    }
}
当goForward为false时,将对象从最后一个航路点移动到第一个航路点,然后在到达第一个航路点时,将goForward切换为true,并从第一个航路点移动到最后一个航路点

当goForward第一次为真时,它工作,然后从第一个航路点移动到最后一个航路点,然后从最后一个航路点移动到第一个航路点,但当goForward第一次为假时,它不工作

我不明白为什么是-1

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

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

    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 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;
        }
        else
        {
            index = waypoints.lineRendererPositions.Count - 1;
        }
    }

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

            getonce = true;
        }

        if (go == true && waypoints.lineRendererPositions.Count > 0)
        {
            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;
    }
}
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
使用UnityEngine;
公共类航路点如下:单行为
{
公众浮标速度;
公共航路点航路点;
公共图书馆;
公共事业发展;
私有整数指数=0;
专用整数计数器=0;
私有int c=0;
私有列表curvedLinePoints=新列表();
公共int-numofpos点与点之间;
私人布尔盖特恩斯;
私有void Start()
{
waypoints=GameObject.Find(“waypoints”).GetComponent();
curvedLinePoints=GameObject.FindGameObjectsWithTag(“曲线点”).ToList();
if(waypoints.moveInReverse==假)
{
goForward=true;
}
其他的
{
goForward=false;
}
如果(前进)
{
指数=0;
}
其他的
{
索引=航路点.LineRenderPositions.Count-1;
}
}
私有void更新()
{
if(getonce==false)
{
numofposbetweenpoints=曲线线点。计数;
getonce=true;
}
if(go==true&&waypoints.linerenderpositions.Count>0)
{
Move();
}
}
私人空位移动()
{
Vector3 newPos=变换位置;
浮动距离到行程=速度*时间.deltaTime;
bool=true;
当(仍在旅行)
{
向量3 oldPos=newPos;
//错误异常超出第55行的界限,请检查!!!!!
newPos=Vector3.向(oldPos、航路点、linerenderpositions[索引]、distanceToTravel)移动;
distanceToTravel-=矢量3.距离(新位置、旧位置);
如果(newPos==waypoints.lineRenderPositions[index])///Vector3比较是近似值,那么这是确定的
{
//当您到达一个航路点时:
如果(前进)
{
布尔atLastOne=索引>=航路点.LineRenderPositions.Count-1;
如果(!atLastOne)
{
索引++;
计数器++;
if(计数器==numoffosbetweenpoints)
{
C++;
计数器=0;
}
if(c==curvedLinePoints.Count-1)
{
c=0;
}
}
else{index--;goForward=false;}
}
其他的
{//倒退:

bool atFirstOne=index在删除之前,我看到了你的前一篇文章,因此,以下是我对你的原始问题的答案:通过旋转和移动在航路点之间移动,并选择在运动结束时发生什么。如果回答你上次删除的问题仍然没有解决你的iss问题,我可以回答你当前的问题ue

// new enum - outside of your class
public enum WaypointMovementType
{
    REPEAT_START,       // will repeat to the start waypoint when end is reached
    REPEAT_REVERSE,     // will reverse the waypoint list when end is reached
    STOP                // will terminate when end is reached
};

// new variables - this is inside your class

// keep a reference of our coroutine to not run duplicates
Coroutine movingWayPoints = null;

// time it takes to rotate to our goal waypoint
private float rotateTime = 0.5f;

// time it takes to move to our goal waypoint
private float movementTime = 1.5f;

// Start is called before the first frame update
void Start()
{
    parent = GameObject.Find("Waypoints");

    // generate the waypoints
    GenerateWaypoints();

    // run our process 
    if (movingWayPoints == null)
        movingWayPoints = StartCoroutine(MoveBetweenWaypoints(tmpList, WaypointMovementType.STOP));
}

private IEnumerator MoveBetweenWaypoints(List<Vector3> waypoints, WaypointMovementType movementType)
{
    int currentWaypointIdx = 0;

    // continue our loop until we have reached our end goal waypoint 
    while (currentWaypointIdx < waypoints.Count)
    {
        // rotate towards out goal point
        yield return StartCoroutine(RotateTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // move towards our goal point
        yield return StartCoroutine(MoveTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // increment our index count or wait for further time if you would like a delay between rotation / movement
        ++currentWaypointIdx;
    }

    // coroutine is done, so set the motion to null
    movingWayPoints = null;

    // now that we have reached the end, determine what we want to do
    if (movementType != WaypointMovementType.STOP)
    {
        // if we want to reverse, then reverse our list
        if (movementType == WaypointMovementType.REPEAT_REVERSE)
            waypoints.Reverse();

        // now call the coroutine again
        movingWayPoints = StartCoroutine(MoveBetweenWaypoints(waypoints, movementType));
    }
}

private IEnumerator RotateTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // store our current rotation
    Quaternion initialRotation = transform.rotation;

    // find our direction to the goal
    Vector3 dir = goalWaypoint - transform.position;

    // calculate the final / goal rotation
    Quaternion finalRotation = Quaternion.LookRotation(dir);

    // store our current time
    float currentTime = 0.0f;

    // rotate until we reach our goal
    while (currentTime <= rotateTime)
    {
        currentTime += Time.deltaTime;
        transform.rotation = Quaternion.Lerp(initialRotation, finalRotation, currentTime / rotateTime);
        yield return null;
    }

    // set our rotation in case there are floating point precision errors
    transform.rotation = finalRotation;
}

private IEnumerator MoveTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // store our current position
    Vector3 initialPostion = transform.position;

    // store our current time
    float currentTime = 0.0f;

    while (currentTime <= movementTime)
    {
        currentTime += Time.deltaTime;
        transform.position = Vector3.Lerp(initialPostion, goalWaypoint, currentTime / movementTime);
        yield return null;
    }

    // set our position in case there are floating point precision errors
    transform.position = goalWaypoint;
}
与其使用
Update
功能来处理列表中一系列航路点之间的旋转和移动,我建议使用。如果您不熟悉,请将其视为一个处理少量加班增量的过程,并将跳回到停止的位置。它应简化旋转和移动问题将其转换为更小的逻辑片段,以便更轻松地理解您的问题

// new enum - outside of your class
public enum WaypointMovementType
{
    REPEAT_START,       // will repeat to the start waypoint when end is reached
    REPEAT_REVERSE,     // will reverse the waypoint list when end is reached
    STOP                // will terminate when end is reached
};

// new variables - this is inside your class

// keep a reference of our coroutine to not run duplicates
Coroutine movingWayPoints = null;

// time it takes to rotate to our goal waypoint
private float rotateTime = 0.5f;

// time it takes to move to our goal waypoint
private float movementTime = 1.5f;

// Start is called before the first frame update
void Start()
{
    parent = GameObject.Find("Waypoints");

    // generate the waypoints
    GenerateWaypoints();

    // run our process 
    if (movingWayPoints == null)
        movingWayPoints = StartCoroutine(MoveBetweenWaypoints(tmpList, WaypointMovementType.STOP));
}

private IEnumerator MoveBetweenWaypoints(List<Vector3> waypoints, WaypointMovementType movementType)
{
    int currentWaypointIdx = 0;

    // continue our loop until we have reached our end goal waypoint 
    while (currentWaypointIdx < waypoints.Count)
    {
        // rotate towards out goal point
        yield return StartCoroutine(RotateTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // move towards our goal point
        yield return StartCoroutine(MoveTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // increment our index count or wait for further time if you would like a delay between rotation / movement
        ++currentWaypointIdx;
    }

    // coroutine is done, so set the motion to null
    movingWayPoints = null;

    // now that we have reached the end, determine what we want to do
    if (movementType != WaypointMovementType.STOP)
    {
        // if we want to reverse, then reverse our list
        if (movementType == WaypointMovementType.REPEAT_REVERSE)
            waypoints.Reverse();

        // now call the coroutine again
        movingWayPoints = StartCoroutine(MoveBetweenWaypoints(waypoints, movementType));
    }
}

private IEnumerator RotateTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // store our current rotation
    Quaternion initialRotation = transform.rotation;

    // find our direction to the goal
    Vector3 dir = goalWaypoint - transform.position;

    // calculate the final / goal rotation
    Quaternion finalRotation = Quaternion.LookRotation(dir);

    // store our current time
    float currentTime = 0.0f;

    // rotate until we reach our goal
    while (currentTime <= rotateTime)
    {
        currentTime += Time.deltaTime;
        transform.rotation = Quaternion.Lerp(initialRotation, finalRotation, currentTime / rotateTime);
        yield return null;
    }

    // set our rotation in case there are floating point precision errors
    transform.rotation = finalRotation;
}

private IEnumerator MoveTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // store our current position
    Vector3 initialPostion = transform.position;

    // store our current time
    float currentTime = 0.0f;

    while (currentTime <= movementTime)
    {
        currentTime += Time.deltaTime;
        transform.position = Vector3.Lerp(initialPostion, goalWaypoint, currentTime / movementTime);
        yield return null;
    }

    // set our position in case there are floating point precision errors
    transform.position = goalWaypoint;
}

我宁愿定义移动和旋转速度,并使用
MoveTowards
RotateTowards
,而不是按时间移动。否则,即使两个航路点非常接近,时间也会相同,但移动速度会慢得多etc@derHugo非常正确!为了完整性,我将添加一个额外的代码段,它使用速度而不是时间。绝对同意使用航路点速度会更好。@derHugo添加了一个新的示例片段,现在使用了
MoveTowards
RotateTowards
private IEnumerator MoveBetweenWaypoints(List<Vector3> waypoints, WaypointMovementType movementType)
{
    int currentWaypointIdx = 0;

    // continue our loop until we have reached our end goal waypoint 
    while (currentWaypointIdx < waypoints.Count)
    {
        // rotate towards out goal point
        yield return StartCoroutine(RotateTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // move towards our goal point
        yield return StartCoroutine(MoveTowardsGoalWaypoint(waypoints[currentWaypointIdx]));

        // increment our index count or wait for further time if you would like a delay between rotation / movement
        ++currentWaypointIdx;
    }

    // coroutine is done, so set the motion to null
    movingWayPoints = null;

    // now that we have reached the end, determine what we want to do
    if (movementType != WaypointMovementType.STOP)
    {
        // if we want to reverse, then reverse our list
        if (movementType == WaypointMovementType.REPEAT_REVERSE)
            waypoints.Reverse();

        // now call the coroutine again
        movingWayPoints = StartCoroutine(MoveBetweenWaypoints(waypoints, movementType));
    }
}

private IEnumerator RotateTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // find our direction to the goal
    Vector3 dir = goalWaypoint - transform.position;

    // calculate the final / goal rotation
    Quaternion finalRotation = Quaternion.LookRotation(dir);

    // continue until our angles match
    while(Vector3.Angle(transform.forward, dir) > ROTATION_CHECK_EPSILON)
    {
        transform.rotation = Quaternion.RotateTowards(transform.rotation, finalRotation, Time.deltaTime * rotateSpeed);
        yield return null;
    }

    // set our rotation in case there are floating point precision errors
    transform.rotation = finalRotation;
}

private IEnumerator MoveTowardsGoalWaypoint(Vector3 goalWaypoint)
{
    // continue until our distance is close to our goal
    while(Vector3.Distance(transform.position, goalWaypoint) > DISTANCE_CHECK_EPSILON)
    {
        transform.position = Vector3.MoveTowards(transform.position, goalWaypoint, Time.deltaTime * movementSpeed);
        yield return null;
    }

    // set our position in case there are floating point precision errors
    transform.position = goalWaypoint;
}