代码之家  ›  专栏  ›  技术社区  ›  JmeMcQ

按时间间隔一次销毁一个游戏对象-Unity3d

  •  0
  • JmeMcQ  · 技术社区  · 4 年前

    我在unity3d中使用块预制资源和脚本创建了一个程序生成的“瓷砖地板”,如下所示:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;
    
    public class Wall : MonoBehaviour
    {
        public GameObject block;
        public int width = 10;
        public int height = 10;
        public int timeDestroy = 1;
        List<GameObject> blockList = new List<GameObject>();
        
    
        void Start(){
    
            for (int y=0; y<height; ++y)
            {
                for (int x=0; x<width; ++x)
                {
                    Vector3 offset = new Vector3(x, 0, y);
                    GameObject hello= (GameObject)Instantiate(block, transform.position + offset, Quaternion.identity);
                    blockList.Add(hello);
                }
            }
            
            StartCoroutine(SelfDestruct());
    
        }
    
        void Update()
        {
            SelfDestruct();
        }
        
        IEnumerator SelfDestruct()
        {
            yield return new WaitForSeconds(timeDestroy);
        
            Destroy(blockList[UnityEngine.Random.Range(0,(width*height))]);
            }
        }
    
    
    

    当我运行游戏时,100个区块中的一个已经被摧毁,但是什么也没发生。根据我的脚本,我希望每秒有一个块被破坏,定义如下: yield return new WaitForSeconds(timeDestroy); 其中int timeDestroy=1;

    然后重复,直到所有的障碍都消失——游戏结束。我怎样才能改变我的脚本,让100个游戏对象一个接一个地被销毁,直到一个都没有了?

    0 回复  |  直到 4 年前
        1
  •  0
  •   programmerboy    4 年前

    你需要把你的 IEnumerator SelfDestruct(); 在while循环中:

    IEnumerator SelfDestruct()
    {
        while (1<2)
        {
            Destroy(blockList[UnityEngine.Random.Range(0, (width * height))]);
            yield return new WaitForSeconds( timeDestroy );
        } 
    }
    

    这样,它将继续破坏这些块,你需要移除这些块 SelfDestruct(); 更新中。

    谢谢德胡戈,我忘了^^。

        2
  •  0
  •   derHugo    4 年前

    这里有几个问题

    • 你开始合作 一旦 但它并不真正等待任何事情(只在最后)。任何地方都没有重复。你可能想在那里使用一个循环

    • 你打电话给 SelfDestruct 每一帧 Update 它将执行所有操作直到第一次 yield !

    • 您可能会多次尝试销毁同一对象,因为您从未从列表中删除它们。

    实际上,整个过程可以是一个单一的协同过程!

    我也会使用 Linq OrderBy 将块的顺序随机化 一旦 然后简单地迭代并按照已经随机的顺序逐个销毁它们。

    比如。

    using System.Linq;
    ...
    
    public class Wall : MonoBehaviour
    {
        public GameObject block;
        public int width = 10;
        public int height = 10;
        public int timeDestroy = 1;
        
        // Yes this is valid and Unity will automatically
        // run this as a Coroutine!
        private IEnumerator Start()
        {
            // Don't even need this as a field only locally
            // already pre-allocate the needed amount
            var blockList = new List<GameObject>(height * width);
    
            for (var y = 0; y < height; ++y)
            {
                for (var x = 0; x < width; ++x)
                {
                    var offset = new Vector3(x, 0, y);
                    var newBlock = Instantiate(block, transform.position + offset, Quaternion.identity);
                    blockList.Add(new Block);
                }
            }
            
            // shuffle the blocks once
            var randomizedBlocks = blockList.OrderBy(blockInstance => Random.value);
            // then simply iterate them in already randomized order
            foreach (var blockInstance in randomizedBlocks)
            {
                yield return new WaitForSeconds (timeDestroy);
    
                Destroy(blockInstance);
            }
    
            // Now you additionally also have direct control when they are all destroyed
            Debug.Log("All blocks have been destroyed!");
        }
    }