代码之家  ›  专栏  ›  技术社区  ›  Daniel Lip

为什么在设置脚本执行顺序时,仍有一个脚本首先执行?

  •  1
  • Daniel Lip  · 技术社区  · 7 年前

    我有两个脚本附加到同一个emptygameobject。 第一个脚本是:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    
    public class SpawnObjects : MonoBehaviour
    {
        public int numberOfObjects;
        public GameObject objectToPlace;
        public Vector3 newObjectsSize = new Vector3(5, 5, 5);
        public float spawnSpeed = 0.1f;
    
        private int wallsLengthX;
        private int wallsLengthZ;
        private int wallsPosX;
        private int wallsPosZ;
        private int currentObjects;
        private List<GameObject> objects = new List<GameObject>();
    
        void Start()
        {
            var wi = GetComponent<Walls>();
            wallsLengthX = (int)wi.lengthX;
            wallsLengthZ = (int)wi.lengthZ;
            wallsPosX = (int)wi.wallsStartPosition.x;
            wallsPosZ = (int)wi.wallsStartPosition.z;
    
            StartCoroutine(Spawn());
        }
    
        IEnumerator Spawn()
        { 
            for (int i = 0; i < numberOfObjects; i++)
            {
                GameObject newObject = (GameObject)Instantiate(objectToPlace);
                newObject.transform.localScale = new Vector3(newObjectsSize.x, newObjectsSize.y, newObjectsSize.z);
                newObject.transform.localPosition = GenerateRandomPositions(newObject);
                newObject.name = "Spawned Object";
                newObject.tag = "Spawned Object";
                objects.Add(newObject);
                yield return new WaitForSeconds(spawnSpeed);
                currentObjects += 1;
            }
        }
    
        private Vector3 GenerateRandomPositions(GameObject newObject)
        {
            float paddingX = Mathf.Clamp(newObject.transform.localScale.x, 0, wallsLengthX) / 2f;
            float paddingZ = Mathf.Clamp(newObject.transform.localScale.z, 0, wallsLengthZ) / 2f;
            float originX = wallsPosX + paddingX - wallsLengthX / 2f;
            float originZ = wallsPosZ + paddingZ - wallsLengthZ / 2f;
            float posx = UnityEngine.Random.Range(originX, originX + wallsLengthX - paddingX);
            float posz = UnityEngine.Random.Range(originZ, originZ + wallsLengthZ - paddingZ);
            float posy = Terrain.activeTerrain.SampleHeight(new Vector3(posx, 0, posz));
    
            return new Vector3(posx, posy, posz);
        }
    }
    

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class WayPoints : MonoBehaviour
    {
        public GameObject[] waypoints;
        public Transform target;
        public float moveSpeed = 10f;
        public float moveSpeed1 = 10f;
        public float slowDownSpeed = 3f;
        public float reverseSlowDownSpeed = 3f;
        public float rotationSpeed = 1f;
    
        private Transform myTransform;
        private int targetsIndex = 0;
        private Vector3 originalPosition;
        private GameObject[] robots;
    
        public Transform reverseTarget;
        private int reverseTargetsIndex = 0;
        private Vector3 reverseOriginalPosition;
    
        public bool random = false;
    
        void Awake()
        {
            myTransform = transform;
        }
        // Use this for initialization
        void Start()
        {
            waypoints = GameObject.FindGameObjectsWithTag("Spawned Object");
    

    第一个脚本生成新的10个立方体。 但是第二个脚本waypoints变量只得到1个“衍生对象”,而不是10个。

    当我使用断点时,我看到它正在执行循环中的第一个脚本一次:

    for (int i = 0; i < numberOfObjects; i++)
    

    但是,它会跳转到第二个脚本,得到一个“衍生对象”,然后返回到第一个脚本,完成循环的其余部分。

    我想要的是,它将首先使整个循环生成10个立方体,然后用第二个脚本将它们全部获取。

    我甚至在编辑:编辑>项目设置>脚本执行顺序

    1 回复  |  直到 7 年前
        1
  •  5
  •   Foggzie    7 年前

    Spawn() 协同程序:

    yield return new WaitForSeconds(spawnSpeed);
    

    这个 Start() 函数的调用顺序是正确的,但第一个脚本只是开始一个协同程序,该程序在每次迭代后生成。在第一次收益率之后,它将一直持续到这一点 WaitForSeconds 末端;同时,第二个脚本将运行其 开始()

    作为一种解决方案,您将无法使用脚本执行顺序来修复此问题。您的第二个脚本必须等到第一个脚本运行完其 繁殖() 协同程序。有很多方法可以做到这一点,但最简单的方法是暴露 Coroutine 返回的对象 StartCoroutine() 或者做一些像 bool DoneSpawning 在您的 SpawnObjects