为什么宇宙飞船与盒子对撞机相撞后不回头

本文关键字:回头 对撞机 宇宙飞船 盒子 为什么 | 更新日期: 2023-09-27 18:12:03

我希望当有对撞机时让飞船返回。但它们一直向前移动,走出对撞机和地形的框框。

当它们碰撞时我想要返回的克隆船的脚本:

using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections;
using System.Collections.Generic;
public class SphereBuilder : MonoBehaviour
{
    public GameObject SpaceShip;
    GameObject[] spheres;
    public float moveSpeed = 50;
    // 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 Start()
    {
        spheres = GameObject.FindGameObjectsWithTag("MySphere");
    }
    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 ();
        //lastPosition = child.position;
    }
    private void MoveShips()
    {
        foreach (Transform child in spheres[0].transform)
        {
            child.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;       
        }
    }
    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;
    }
}

与OnTriggerExit函数碰撞的脚本:

using UnityEngine;
using System.Collections;
public class InvisibleWalls : MonoBehaviour {
    public float smooth = 1f;
    private Vector3 targetAngles;
    // Use this for initialization
    void Start () {
    }
    // Update is called once per frame
    void Update () {
    }
    void OnTriggerExit(Collider other)
    {
        if (other.tag == "Sphere") 
        {
            targetAngles = other.transform.eulerAngles + 180f * Vector3.up;
            other.transform.eulerAngles = Vector3.Lerp (other.transform.eulerAngles, targetAngles, smooth * Time.deltaTime);
        }
    }
}

它确实到达了这两行:

targetAngles = other.transform.eulerAngles + 180f * Vector3.up;
other.transform.eulerAngles = Vector3.Lerp (other.transform.eulerAngles, targetAngles, smooth * Time.deltaTime);

但他们从不回头。

创建克隆船的脚本附加到一个名为Spheres的游戏对象上,并标记为MySphere。

第二个脚本附加到一个名为Invisible Walls的游戏对象上,我添加了一个盒子碰撞器,并将is Trigger设置为on(勾选)。还添加了刚体,并勾选了重力

为什么宇宙飞船与盒子对撞机相撞后不回头

这是因为你的Lerp方法只在OnTriggerExit中调用一次。Lerp通常随时间使用,例如在Update或协程中。下面是如何在协程中完成它:

void OnTriggerExit(Collider other)
{
    if (other.tag == "Sphere") 
    {
        targetAngles = other.transform.eulerAngles + 180f * Vector3.up;
        StartCoroutine(TurnShip(other.transform, other.transform.eulerAngles, targetAngles, smooth))
    }
}
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;
    }
}