You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中同标签砖块(tugla)位置更新异常问题求助

问题

我正在用Unity开发一款简单的移动端游戏,尝试修改标签为tugla的砖块位置。需求是:当球击中砖块后,待球触碰地面时更新砖块位置;球触碰砖块时会销毁砖块。目前未击中砖块时功能正常,但击中第二个或其他砖块后,部分砖块无法更新位置——例如游戏中有4个砖块,击中第二个后,仅第三、第四个砖块会移动到新位置。

砖块代码(tugla.cs)

public class tugla : MonoBehaviour
{
    public static int toplamTuglaSayisi;
    public Sprite[] tuglaSprite;
    private int maxCarpmaSayisi;
    private int carpmaSayisi;
    GameObject kirmizitop;

    void Start()
    {
        maxCarpmaSayisi = tuglaSprite.Length + 1;
        toplamTuglaSayisi++;
        kirmizitop = GameObject.FindGameObjectWithTag("kirmizitop");
    }

    void Update()
    {
        // -1.330 -1.868
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        Debug.Log("kirmizi top geçti");
        carpmaSayisi++;
        if (carpmaSayisi >= maxCarpmaSayisi)
        {
            toplamTuglaSayisi--;
            if (toplamTuglaSayisi <= 0)
            {
                Debug.Log("works");
                GameObject.FindObjectOfType<OyunKontrol>().GetComponent<OyunKontrol>().birsonrakisahne();
            }
            Destroy(gameObject);
        }
        else
        {
            GetComponent<SpriteRenderer>().sprite = tuglaSprite[carpmaSayisi - 1];
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.name.Equals("top"))
        {
            carpmaSayisi++;
            if (carpmaSayisi >= maxCarpmaSayisi)
            {
                toplamTuglaSayisi--;
                if(toplamTuglaSayisi <= 0)
                {
                    Debug.Log("works");
                    GameObject.FindObjectOfType<OyunKontrol>().GetComponent<OyunKontrol>().birsonrakisahne();
                }
                Destroy(gameObject);
            }
            else
            {
                GetComponent<SpriteRenderer>().sprite = tuglaSprite[carpmaSayisi - 1];
            }
        }
    }
}

球的代码(top.cs)

public class top : MonoBehaviour
{
    GameObject topataci;
    Rigidbody2D fizik;
    GameObject acigostergesi;
    GameObject[] tugla;

    public GameObject top_arka;

    void Start()
    {
        fizik = GetComponent<Rigidbody2D>();
        topataci = GameObject.FindGameObjectWithTag("topataci");
        acigostergesi = GameObject.FindGameObjectWithTag("acigostergesi");
        tugla = GameObject.FindGameObjectsWithTag("tugla");
    }

    void Update()
    {
        // 注释代码省略
    }

    void OnCollisionEnter2D(Collision2D Collider)
    {
        if (Collider.gameObject.name.Equals("zemin"))
        {
            GetComponent<Rigidbody2D>().velocity = new Vector2(0f, 0f);
            topataci.GetComponent<Transform>().transform.position = new Vector3(0, -6.04f, 0);
            acigostergesi.GetComponent<Transform>().transform.position = new Vector3(transform.position.x, transform.position.y, 10f);
            acigostergesi.GetComponent<Rigidbody2D>().rotation = 0;

            if (tugla.Length <= 0)
            {
                // SceneManager.LoadScene(1);
            }
            else
            {
                for (int i = 0; i < tugla.Length; i++)
                {
                    Debug.Log("Getting new position");
                    tugla[i].GetComponent<Transform>().transform.position += Vector3.down * 0.538f;
                }
            }
        }
    }
}

问题原因

核心问题在于球脚本中的tugla数组只在Start()方法中初始化一次。当砖块被销毁后,数组里依然保留着这些已销毁对象的引用——这些引用不会自动从数组中移除,导致遍历数组时,已销毁的砖块对象无法执行移动操作,而你看到的“仅第三、第四个砖块移动”是因为数组中后面的元素还存活。

修复方案

1. 每次触地时重新获取存活的砖块

移除Start()中初始化tugla数组的代码,改为在球触碰地面时,实时查找所有标签为tugla的存活对象,确保数组里只包含当前存在的砖块。

2. 增加对象有效性判断

遍历数组时,先检查对象是否为null(避免已销毁对象引发的问题),再执行移动操作。

修改后的球脚本(top.cs)

public class top : MonoBehaviour
{
    GameObject topataci;
    Rigidbody2D fizik;
    GameObject acigostergesi;

    public GameObject top_arka;

    void Start()
    {
        fizik = GetComponent<Rigidbody2D>();
        topataci = GameObject.FindGameObjectWithTag("topataci");
        acigostergesi = GameObject.FindGameObjectWithTag("acigostergesi");
    }

    void Update()
    {
        // 注释代码省略
    }

    void OnCollisionEnter2D(Collision2D Collider)
    {
        if (Collider.gameObject.name.Equals("zemin"))
        {
            GetComponent<Rigidbody2D>().velocity = new Vector2(0f, 0f);
            topataci.transform.position = new Vector3(0, -6.04f, 0);
            acigostergesi.transform.position = new Vector3(transform.position.x, transform.position.y, 10f);
            acigostergesi.GetComponent<Rigidbody2D>().rotation = 0;

            // 实时获取当前所有存活的tugla砖块
            GameObject[] tugla = GameObject.FindGameObjectsWithTag("tugla");
            
            if (tugla.Length > 0)
            {
                for (int i = 0; i < tugla.Length; i++)
                {
                    // 确保对象未被销毁
                    if(tugla[i] != null)
                    {
                        Debug.Log("Getting new position");
                        tugla[i].transform.position += Vector3.down * 0.538f;
                    }
                }
            }
            else
            {
                // SceneManager.LoadScene(1);
            }
        }
    }
}

额外优化:Unity中每个GameObject都自带transform属性,无需调用GetComponent<Transform>(),可以直接使用obj.transform简化代码。

内容的提问来源于stack exchange,提问作者Berkay Isıkoglu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:25:04