在再次销毁和创建新对象时,如何更新目标数组?

时间:2017-05-26 22:42:15

标签: c# unity3d

问题出在这个脚本中:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class PatrolData
{
    public Transform target = null;
    public float minDistance = 5f;
    public float lingerDuration = 5f;

    public float desiredHeight = 10f;

    public float flightSmoothTime = 10f;
    public float maxFlightspeed = 10f;
    public float flightAcceleration = 1f;

    public float levelingSmoothTime = 0.5f;
    public float maxLevelingSpeed = 10000f;
    public float levelingAcceleration = 2f;
}

public class PatrolOverTerrain : MonoBehaviour
{
    public FlyToOverTerrain flyOverTerrain;
    public LookAtCamera lookAtCamera;
    public enum PatrolMode { Clamp, Wrap, PingPong };
    public PatrolData[] patrolPoints;
    public PatrolMode mode = PatrolMode.Wrap;

    private int iterator = 0;
    private int index = 0;
    private float lingerDuration = 0f;
    private int oldLength = 0;

    public List<GameObject> TeleportationBooths = new List<GameObject>();
    public Vector3 distanceFromTarget;

    private void Start()
    {
        GameObject[] tempObj = GameObject.FindGameObjectsWithTag("Teleportation Booth");

        for (int i = 0; i < tempObj.Length; i++)
        {
            //Add to list only if it does not exist
            if (!TeleportationBooths.Contains(tempObj[i]))
            {
                TeleportationBooths.Add(tempObj[i]);
            }
        }

        //Get the current Size
        if (tempObj != null)
        {
            oldLength = tempObj.Length;
        }

        GeneratePatrolPoints();
    }

    private void OnEnable()
    {
        if (patrolPoints.Length > 0)
        {
            lingerDuration = patrolPoints[index].lingerDuration;
        }
    }



    private void Update()
    {
        //Check if oldLength has changed
        if (oldLength != TeleportationBooths.Count)
        {
            //Update oldLength
            oldLength = TeleportationBooths.Count;

            //Call your the function
            GeneratePatrolPoints();
        }

        int length = patrolPoints.Length;
        if (!flyOverTerrain) return;
        if (patrolPoints.Length < 1) return;
        if (index < 0) return;

        // Getting exception out of index on line 89.
        // Need to make a list also for the Cubes(buildings).

        var patrol = patrolPoints[index];
        if (lingerDuration <= 0)
        {
            iterator++;
            switch (mode)
            {
                case PatrolMode.Clamp:
                    index = (iterator >= length) ? -1 : iterator;
                    break;
                case PatrolMode.Wrap:
                    iterator = Modulus(iterator, length);
                    index = iterator;
                    break;
                case PatrolMode.PingPong:
                    index = PingPong(iterator, length);
                    break;
            }
            if (index < 0) return;

            patrol = patrolPoints[index];

            flyOverTerrain.target = patrol.target;
            flyOverTerrain.desiredHeight = patrol.desiredHeight;
            flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
            flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
            flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
            flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
            flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
            flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;

            lookAtCamera.target = patrol.target;
            lookAtCamera.RotationSpeed = 3;

            lingerDuration = patrolPoints[index].lingerDuration;
        }


        Vector3 targetOffset = Vector3.zero;
        if ((bool)patrol.target)
        {
            targetOffset = transform.position - patrol.target.position;
        }

        float sqrDistance = patrol.minDistance * patrol.minDistance;
        if (targetOffset.sqrMagnitude <= sqrDistance)
        {
            flyOverTerrain.target = null;
            lookAtCamera.target = null;
            lingerDuration -= Time.deltaTime;
        }
        else
        {
            flyOverTerrain.target = patrol.target;
            lookAtCamera.target = patrol.target;
        }
        distanceFromTarget = transform.position - patrol.target.position;
    }

    private int PingPong(int baseNumber, int limit)
    {
        if (limit < 2) return 0;
        return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
    }

    private int Modulus(int baseNumber, int modulus)
    {
        return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
    }

    public void GeneratePatrolPoints()
    {
        patrolPoints = new PatrolData[TeleportationBooths.Count];
        for (int i = 0; i < patrolPoints.Length; i++)
        {
            patrolPoints[i] = new PatrolData();
            patrolPoints[i].target = TeleportationBooths[i].transform;
            patrolPoints[i].minDistance = 30f;
            patrolPoints[i].lingerDuration = 3f;
            patrolPoints[i].desiredHeight = 20f;
            patrolPoints[i].flightSmoothTime = 10f;
            patrolPoints[i].maxFlightspeed = 10f;
            patrolPoints[i].flightAcceleration = 3f;
            patrolPoints[i].levelingSmoothTime = 0.5f;
            patrolPoints[i].maxLevelingSpeed = 10000f;
            patrolPoints[i].levelingAcceleration = 2f;
        }
    }
}

在更新内部的这部分中,我将列表的旧长度与当前长度进行比较:

//Check if oldLength has changed
        if (oldLength != TeleportationBooths.Count)
        {
            //Update oldLength
            oldLength = TeleportationBooths.Count;

            //Call your the function
            GeneratePatrolPoints();
        }

因此,如果我创建一个新对象而不破坏旧对象,那么它的长度就不一样了,它会调用GeneratePatrolPoints()并使用刚刚添加的新目标更新目标:

patrolPoints[i].target = TeleportationBooths[i].transform;

问题是,当我检查ui切换并首先销毁对象然后再次创建它们时,长度与之前相同,因此它不会调用GeneratePatrolPoints()并且不会更新目标。

所以我失去了对象异常。 我正在更新列表,但我还需要再次更新目标。

在这个脚本中,我决定是否创建新对象并将它们添加到列表中,这样长度就不一样了,一切都是正确的,或者首先销毁当前对象然后创建新对象但是长度将是同样的:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GenerateObjectsButton : MonoBehaviour
{
    [SerializeField]
    private InstantiateObjects[] instantiateobjects;
    private bool toggleOnOf;
    public Toggle toggle;

    private void Start()
    {
        toggle.onValueChanged.AddListener((value) =>
            {
                MyListener(value);
            });
    }

    public void MyListener(bool value)
    {
        if (value)
        {
            //do the stuff when the toggle is on
            toggleOnOf = true;
        }
        else
        {
            //do the stuff when the toggle is off
            toggleOnOf = false;
        }
    }

    public void OnButton()
    {
        for (int i = 0; i < instantiateobjects.Length; i++)
        {
            if (toggleOnOf == false)
            {
                instantiateobjects[i].generateObjectOnTerrain();
            }
            else
            {
                instantiateobjects[i].DestroyObjects();
                instantiateobjects[i].generateObjectOnTerrain();
            }
        }
    }
}

问题在于第一个脚本将长度与列表计数进行比较。

1 个答案:

答案 0 :(得分:0)

解决方案是在GenerateObjectsButton脚本中添加一个新的bool变量:

public bool destroyed = false;

在再次销毁和创建新对象后将其设置为true:

public void OnButton()
    {
        for (int i = 0; i < instantiateobjects.Length; i++)
        {
            if (toggleOnOf == false)
            {
                instantiateobjects[i].generateObjectOnTerrain();
            }
            else
            {
                instantiateobjects[i].DestroyObjects();
                instantiateobjects[i].generateObjectOnTerrain();
                destroyed = true;
            }
        }
    }

现在被毁坏是真的。 返回PatrolOverTerrain脚本。

现在我不仅检查长度是否相同,而且如果销毁的话也是如此:

//Check if oldLength has changed
    if (oldLength != TeleportationBooths.Count)
    {
        //Update oldLength
        oldLength = TeleportationBooths.Count;

        //Call your the function
        GeneratePatrolPoints();
    }

    GameObject go = GameObject.Find("Button");
    var destroyed = go.GetComponent<GenerateObjectsButton>().destroyed;
    if (destroyed)
    {
        GeneratePatrolPoints();
    }

现在我知道什么时候我只创建新对象并通过比较长度或首次销毁对象然后创建新对象来添加它们,所以长度没有改变,但是它自己的列表没有。

无论如何,这是一个有效的解决方案。