为什么在宇宙飞船与盒对撞机相撞后它们不回头? [英] Why after the spaceships collide with the box collider they are not turning back?

查看:93
本文介绍了为什么在宇宙飞船与盒对撞机相撞后它们不回头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望当有对撞机时,将飞船转回原处.但是它们一直在前进,并脱离了对撞机和地形.

I want that when there is a collider turn the spaceship/s back. But they keep moving forward and out of the box collider and terrain.

构成克隆的脚本会在它们发生碰撞时向后退回:

The script that make the clones ships that i want to turn back when they collide:

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冲突的脚本:

And the script of the colliding with the function 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);

但是他们从不回头.

创建克隆飞船的脚本被附加到GameObject名称为Spheres并标记为MySphere.

The script that create the cloned ships is attached to a GameObject name Spheres and tagged as MySphere.

第二个脚本附加到一个名为Invisible Walls的GameObject上,我在其中添加了一个框碰撞器,将Is Trigger设置为on(选中).并添加了一个刚体并选中了使用重力".

The second script is attached to a GameObject called Invisible Walls and that i added to it a box collider with the Is Trigger set to on(checked). And also added to it a Rigidbody and Use Gravity is checked on.

推荐答案

这是因为您的Lerp方法在OnTriggerExit中仅被调用一次.通常会随着时间的推移使用Lerp,例如在Update或协程中.这是在协程中执行此操作的方法:

It's because your Lerp method is only called once in OnTriggerExit. Lerp is usually used over time e.g. in Update or a coroutine. Here's how to do it in a coroutine:

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;
    }
}

这篇关于为什么在宇宙飞船与盒对撞机相撞后它们不回头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆