Почему после столкновения космических кораблей с боковым коллайдером они не поворачивают назад?

#c# #unity3d

#c# #unity3d

Вопрос:

Я хочу, чтобы при наличии коллайдера возвращался космический корабль / ы. Но они продолжают двигаться вперед и выходят из боксового коллайдера и местности.

Сценарий, который заставляет клоны отправлять корабли, которые я хочу повернуть назад, когда они сталкиваются:

 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 amp;amp; SphereCount == _sphereCount amp;amp; 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, установленным на on (проверено). А также добавлено к нему жесткое тело и используется гравитация.

Комментарии:

1. Я думаю, вам следует отправить свой вопрос на gamedev.stackexchange.com

2. потому что они уже получают тяжелые повреждения, мешающие нормальной работе системы.

3. other переменная — космический корабль?

4. @Programmer да, это так. По крайней мере, я так думаю. У меня нет другого объекта, движущегося дальше кораблей, и только корабли, помеченные как «Сфера», так что да, другое — космический корабль / корабли

5. Замените other.transform.eulerAngles = Vector3.Lerp (other.transform.eulerAngles, targetAngles, smooth * Time.deltaTime); на other.transform.Rotate(new Vector3(0f,180f,0f)); и дайте мне знать, если он поворачивается сейчас.

Ответ №1:

Это потому, что ваш метод Lerp вызывается только один раз в OnTriggerExit . Lerp обычно используется со временем, например, в обновлении или сопрограмме. Вот как это сделать в сопрограмме:

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