0
votes

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

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

It does get to the two lines:

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

But they never turn back.

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

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.

1
I think you should send you question to gamedev.stackexchange.compix
because they already receive heavy damage, affecting it's system to function normally.DarkMakukudo
other variable is the space ship?Programmer
@Programmer yes it is. At least that is what i guess. I have no other object moving then the ships and only the ships tagged as "Sphere" so yes other is the space ship/sTheLost Lostit
Replace other.transform.eulerAngles = Vector3.Lerp (other.transform.eulerAngles, targetAngles, smooth * Time.deltaTime); with other.transform.Rotate(new Vector3(0f,180f,0f)); and let me know if it turns now.Programmer

1 Answers

1
votes

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