简体   繁体   English

仍然不清楚为什么所有的船只在旋转后都没有向它们所面对的方向移动?

[英]Still not clear yet why all the ships are not moving to the direction they are facing after rotation?

private void MoveShips()
    {
        for (int index = 0; index < spheres [0].transform.childCount; index++) {
            Transform oneChild = spheres [0].transform.GetChild (index);
            lastPositions [index] = oneChild.transform.position;
            if (!hasRotated [index]) 
            {
                oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
            } 
            else 
            {
                oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;
            }
        }

        if (updateOn == true) {
            for(int index =0;index < spheres[0].transform.childCount;index++)
            {
                Transform child = spheres[0].transform.GetChild(index);

                distanceTraveled[index] += Vector3.Distance (child.transform.position, lastPositions [index]);
                if (distanceTraveled [index] >= randomNumbers [index] && !hasRotated [index]) 
                {
                    targetAngles = child.transform.eulerAngles + 180f * Vector3.up;
                    StartCoroutine (TurnShip (child.transform, child.transform.eulerAngles, targetAngles, smooth));
                    hasRotated [index] = true;
                }
            }
        }
    }

    IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
    {
        float lerpSpeed = 0;

        while(lerpSpeed < 1)
        {
            ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
            lerpSpeed += Time.deltaTime * smooth;
            yield return null;
        }
    }

For example i have 300 ships.例如,我有 300 艘船。 They are moving forward using Vector3.forward then i want to make that after each child completed the rotation then change it's moving direction to the direction it's facing now.他们正在使用 Vector3.forward 向前移动,然后我想在每个孩子完成旋转之后将其移动方向更改为它现在面向的方向。 So in the case i rotate the ships 180 degrees but the ships move up.所以在我将船只旋转 180 度但船只向上移动的情况下。

This line make them move up:这条线使他们向上移动:

oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;

I tried also to change this line to:我也尝试将此行更改为:

oneChild.transform.position += oneChild.transform.forward * moveSpeed;

This make the ships to disapear.这使船只消失。

I also tried:我也试过:

oneChild.transform.position += oneChild.transform.forward * -1 * moveSpeed;

Or或者

oneChild.transform.position += -oneChild.transform.forward * Time.deltaTime * moveSpeed; --- This line make the ships move up turn and move down. But i want them to move forward not up and down. Move forward to the direction they are facing after the rotation.

Or或者

oneChild.transform.position += oneChild.transform.forward * -1;

I also tried to use only the Vector3 for example:例如,我还尝试仅使用 Vector3:

if (!hasRotated [index]) 
            {
                oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
            } 
            else 
            {
                oneChild.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
            }

But this will move the ships back not to the direction they are facing.但这将使船只返回而不是它们所面对的方向。 If i will rotate the ships only 60 degrees they will move back not to the facing direction.如果我将船只仅旋转 60 度,它们将不会向后移回面向方向。

Another problem i think it's a problem the ships change the moving diection if it's up down before they completed the rotation.另一个问题我认为这是一个问题,如果船在完成旋转之前向上向下,则船会改变移动方向。 I want that first the ship each ship will complete the rotation and while rotating to keep moving to the original direction only when the rotation end then change the movement to the direction it's facing.我希望每艘船首先完成旋转,并在旋转时保持向原始方向移动,只有在旋转结束时才将移动更改为它所面对的方向。

The script剧本

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

public class SphereBuilder : MonoBehaviour
{
    public GameObject SpaceShip;
    GameObject[] spheres;
    public float moveSpeed = 50;

    private float distanceTravelled;
    public bool updateOn = true;
    private Vector3 lastPosition;

    List<bool> hasRotated = new List<bool>();
    List<float> distanceTraveled = new List<float>();
    List<Vector3> lastPositions = new List<Vector3>();
    List<int> randomNumbers = new List<int> ();

    public float smooth = 1f;
    private Vector3 targetAngles;
    private bool isRunning = false;

    // for tracking properties change
    private Vector3 _extents;
    private int _sphereCount;
    private float _sphereSize;

    /// <summary>
    ///     How far to place spheres randomly.
    /// </summary>
    public Vector3 Extents;

    /// <summary>
    ///     How many spheres wanted.
    /// </summary>
    public int SphereCount;
    public float SphereSize;

    private void rndNumbers()
    {
        int Min = 20;
        int Max = 50;
        System.Random rnd = new System.Random ();
        randomNumbers = Enumerable.Range(Min, Max).OrderBy(x => rnd.Next()).Take(spheres[0].transform.childCount).ToList();
    }

    private void Start()
    {
        UpdateSpheres ();
        spheres = GameObject.FindGameObjectsWithTag("MySphere");
        rndNumbers ();
        for(int index = 0; index < spheres[0].transform.childCount;index++)
        {
            Transform child = spheres[0].transform.GetChild(index);
            lastPosition = new Vector3(child.transform.position.x,child.transform.position.y,child.transform.position.z);
            lastPositions.Add (lastPosition);
            hasRotated.Add(false);
            distanceTraveled.Add(0f);
        }
    }

    private void OnValidate()
    {
        // prevent wrong values to be entered
        Extents = new Vector3(Mathf.Max(0.0f, Extents.x), Mathf.Max(0.0f, Extents.y), Mathf.Max(0.0f, Extents.z));
        SphereCount = Mathf.Max(0, SphereCount);
        SphereSize = Mathf.Max(0.0f, SphereSize);
    }

    private void Reset()
    {
        Extents = new Vector3(250.0f, 20.0f, 250.0f);
        SphereCount = 100;
        SphereSize = 20.0f;
    }

    private void Update()
    {
        UpdateSpheres();
        MoveShips ();
    }

    private void MoveShips()
    {
        for (int index = 0; index < spheres [0].transform.childCount; index++) {
            Transform oneChild = spheres [0].transform.GetChild (index);
            lastPositions [index] = oneChild.transform.position;
            if (!hasRotated [index])
            {
                oneChild.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
            }
            else
            {
                oneChild.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
            }
        }

        if (updateOn == true) {
            for(int index =0;index < spheres[0].transform.childCount;index++)
            {
                Transform child = spheres[0].transform.GetChild(index);

                distanceTraveled[index] += Vector3.Distance (child.transform.position, lastPositions [index]);
                if (distanceTraveled [index] >= randomNumbers [index] && !hasRotated [index]) {
                    //child.transform.Rotate (new Vector3 (0f, 180f, 0f));


                    targetAngles = child.transform.eulerAngles + 180f * Vector3.up;
                    //if (!isRunning)
                    //{
                        StartCoroutine (TurnShip (child.transform, child.transform.eulerAngles, targetAngles, smooth));
                    //}
                    hasRotated [index] = true;
                    child.transform.position += Vector3.back * Time.deltaTime * moveSpeed;
                }
            }
        }
    }

    IEnumerator TurnShip(Transform ship, Vector3 startAngle, Vector3 endAngle, float smooth)
    {
        isRunning = true;
        float lerpSpeed = 0;

        while(lerpSpeed < 1)
        {
            ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);
            lerpSpeed += 1 * smooth;
            yield return new WaitForSeconds(0.01f);
        }
        isRunning = false;
    }

    private void UpdateSpheres()
    {
        if (Extents == _extents && SphereCount == _sphereCount && Mathf.Approximately(SphereSize, _sphereSize))
            return;

        // cleanup
        var spheres = GameObject.FindGameObjectsWithTag("Sphere");
        foreach (var t in spheres)
        {
            if (Application.isEditor)
            {
                DestroyImmediate(t);
            }
            else
            {
                Destroy(t);
            }
        }

        var withTag = GameObject.FindWithTag("Terrain");
        if (withTag == null)
            throw new InvalidOperationException("Terrain not found");

        for (var i = 0; i < SphereCount; i++)
        {
            var o = Instantiate(SpaceShip);
            o.tag = "Sphere";
            o.transform.SetParent(gameObject.transform);
            o.transform.localScale = new Vector3(SphereSize, SphereSize, SphereSize);

            // get random position
            var x = Random.Range(-Extents.x, Extents.x);
            var y = Extents.y; // sphere altitude relative to terrain below
            var z = Random.Range(-Extents.z, Extents.z);

            // now send a ray down terrain to adjust Y according terrain below
            var height = 10000.0f; // should be higher than highest terrain altitude
            var origin = new Vector3(x, height, z);
            var ray = new Ray(origin, Vector3.down);
            RaycastHit hit;
            var maxDistance = 20000.0f;
            var nameToLayer = LayerMask.NameToLayer("Terrain");
            var layerMask = 1 << nameToLayer;
            if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
            {
                var distance = hit.distance;
                y = height - distance + y; // adjust
            }
            else
            {
                Debug.LogWarning("Terrain not hit, using default height !");
            }

            // place !
            o.transform.position = new Vector3(x, y, z);
        }

        _extents = Extents;
        _sphereCount = SphereCount;
        _sphereSize = SphereSize;
    }
}

what you are saying makes me think the local forward is simply wrong (your ship model is turned).你说的让我觉得当地前锋完全是错误的(你的船型变了)。 or your forward gets changed because of parenting (wich can be tricky)或者你的前锋因为养育而改变(这可能很棘手)

also

dont use Vector3.forward, if you want to travel on it OWN forward.不要使用 Vector3.forward,如果你想自己向前旅行。

oneChild.transform.position += oneChild.transform.forward * Time.deltaTime * moveSpeed;

is correct.是正确的。

x X

ship.eulerAngles = Vector3.Lerp(startAngle, endAngle, lerpSpeed);

should be a Slerp https://docs.unity3d.com/ScriptReference/Vector3.Slerp.html应该是 Slerp https://docs.unity3d.com/ScriptReference/Vector3.Slerp.html

The difference between this and linear interpolation (aka, "lerp") is that the vectors are treated as directions rather than points in space.这与线性插值(又名“lerp”)之间的区别在于向量被视为方向而不是空间中的点。

or lerp angle: https://docs.unity3d.com/ScriptReference/Mathf.LerpAngle.html或 lerp 角度: https ://docs.unity3d.com/ScriptReference/Mathf.LerpAngle.html

x X

targetAngles = child.transform.eulerAngles + 180f * Vector3.up;

i find this last line a bit abstract, not knowing what angle you are turning on, and ,again, using vector3.up instead of child.transform.up but i guess this line is to flip your ship upside down, or perhaps making it move up&down我觉得这最后一行有点抽象,不知道你打开的角度是什么,而且,再次使用 vector3.up 而不是 child.transform.up 但我猜这条线是把你的船倒过来,或者让它倒过来上下移动

hope it helps.希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM