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

Unity Remote 5运行正常但Android打包后仅生成1个Tile的问题

Unity Android打包后Tile生成异常问题排查与解决

问题现象

  • Unity编辑器、Unity Remote 5环境:屏幕两侧可正常各生成40个Tile
  • Android打包后:仅一侧生成1个Tile即停止运行
  • 已尝试操作:新建场景测试、将脚本从主相机移至空GameObject,问题未解决

相关代码

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

public class Matchager : MonoBehaviour
{
    SpriteRenderer spr1;
    SpriteRenderer spr2;
    [SerializeField] Sprite[] sprotes;
    [SerializeField] GameObject[] Endres;
    [SerializeField] GameObject[] All;
    [SerializeField] GameObject Fold1;
    [SerializeField] GameObject Fold2;
    [SerializeField] GameObject note1;
    [SerializeField] GameObject note2;
    [SerializeField] GameObject note3;
    public static GameObject currentnote;
    public static GameObject currentnote2;
    public static bool notpressable;
    public static bool notpressable2;
    public static bool corunner;
    public static bool corunner2;
    bool runnow;

    private void Start()
    {
        spr1 = Endres[5].GetComponent<SpriteRenderer>();
        spr2 = Endres[6].GetComponent<SpriteRenderer>();
        Invoke("Waiter", 2f);
    }

    private void Update()
    {
        if (Fold1.transform.childCount == 0 && runnow)
            bottomwin();
        else if (Fold2.transform.childCount == 0 && runnow)
            topwin();
    }

    private GameObject GetRandomNote()
    {
        int randomIndex = Random.Range(0, 3);

        switch (randomIndex)
        {
            case 0:
                return note1;
            case 1:
                return note2;
            case 2:
                return note3;
            default:
                return null;
        }
    }

    void Waiter()
    {
        for (int i = 0; i < 40; i++)
        {
            Vector3Int tilePosition = new Vector3Int(0 + (i * 5), -2, 0);
            GameObject tam = Instantiate(GetRandomNote(), Fold1.transform);
            GameObject tam2 = Instantiate(tam, Fold2.transform);
            tam.transform.position = tilePosition;
            tam2.transform.position = -tilePosition;
            if (tam.GetComponent<Matchotes>().Uni == 1)
                tam2.GetComponent<Matchotes>().Uni = 4;
            else if (tam.GetComponent<Matchotes>().Uni == 2)
                tam2.GetComponent<Matchotes>().Uni = 5;
            else if (tam.GetComponent<Matchotes>().Uni == 3)
                tam2.GetComponent<Matchotes>().Uni = 6;
        }
        runnow = true;
    }

    void topwin()
    {
        Fold1.SetActive(false);
        Fold2.SetActive(false);
        foreach (GameObject game in All)
            game.SetActive(false);
        Endres[0].SetActive(true);
        Endres[1].SetActive(true);
        Endres[4].SetActive(true);
        Endres[7].SetActive(true);
        Endres[8].SetActive(true);
        RectTransform rect = Endres[2].GetComponent<RectTransform>();
        RectTransform rect2 = Endres[3].GetComponent<RectTransform>();
        rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, 100);
        rect.localRotation = Quaternion.Euler(rect.localRotation.x, rect.localRotation.x, 180);
        rect2.anchoredPosition = new Vector2(rect.anchoredPosition.x, -100);
        spr1.sprite = sprotes[0];
        spr2.sprite = sprotes[1];
    }

    void bottomwin()
    {
        Fold1.SetActive(false);
        Fold2.SetActive(false);
        foreach (GameObject game in All)
            game.SetActive(false);
        Endres[0].SetActive(true);
        Endres[1].SetActive(true);
        Endres[4].SetActive(true);
        Endres[7].SetActive(true);
        Endres[8].SetActive(true);
        RectTransform rect = Endres[2].GetComponent<RectTransform>();
        RectTransform rect2 = Endres[3].GetComponent<RectTransform>();
        rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, -100);
        rect2.localRotation = Quaternion.Euler(rect.localRotation.x, rect.localRotation.x, 180);
        rect2.anchoredPosition = new Vector2(rect.anchoredPosition.x, 100);
        spr1.sprite = sprotes[2];
        spr2.sprite = sprotes[3];
    }
}

排查与修复方案

1. 主线程阻塞导致中断

Waiter方法在主线程一次性实例化80个对象,Android设备性能不足时会触发卡顿甚至中断执行。
修复:改用协程分步实例化
替换Start和Waiter方法:

private void Start()
{
    spr1 = Endres[5].GetComponent<SpriteRenderer>();
    spr2 = Endres[6].GetComponent<SpriteRenderer>();
    StartCoroutine(WaiterCoroutine());
}

IEnumerator WaiterCoroutine()
{
    yield return new WaitForSeconds(2f);
    for (int i = 0; i < 40; i++)
    {
        Vector3 tilePosition = new Vector3(0 + (i * 5f), -2f, 0f);
        GameObject tam = Instantiate(GetRandomNote(), Fold1.transform);
        GameObject tam2 = Instantiate(tam, Fold2.transform);
        tam.transform.position = tilePosition;
        tam2.transform.position = -tilePosition;

        Matchotes tamMatch = tam.GetComponent<Matchotes>();
        Matchotes tam2Match = tam2.GetComponent<Matchotes>();
        if (tamMatch != null && tam2Match != null)
        {
            if (tamMatch.Uni == 1)
                tam2Match.Uni = 4;
            else if (tamMatch.Uni == 2)
                tam2Match.Uni = 5;
            else if (tamMatch.Uni == 3)
                tam2Match.Uni = 6;
        }
        // 每实例化5个暂停一帧,避免阻塞主线程
        if (i % 5 == 0)
            yield return null;
    }
    runnow = true;
}

2. 空引用异常中断循环

若note1/note2/note3预制体未挂载Matchotes组件,Android平台加载时会触发空引用异常,终止循环。
修复:

  • 检查三个note预制体,确保都挂载Matchotes组件
  • 添加空引用判断(如上代码所示),避免异常崩溃

3. 坐标精度问题

Vector3Int在Android平台可能出现精度丢失,导致后续Tile被渲染到视口外,看起来像停止生成。
修复:改用Vector3浮点类型设置坐标(已包含在协程修复代码中)

4. 渲染层级问题

后续生成的Tile可能超出相机裁剪范围或被遮挡,导致不可见。
修复:

  • 调整相机裁剪面参数,确保覆盖所有Tile的坐标范围
  • 给Tile添加高辨识度颜色,验证是否实际生成但未显示

内容的提问来源于stack exchange,提问作者TFO Society

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:45:11