Unity中x>4的瓦片点击不显示子物体渲染器问题求助
Unity瓦片点击显示异常问题
我是Unity新手,正在学习开发技巧,以下代码肯定有更优实现方式。我通过x、y变量构建嵌套循环,实例化一批瓦片,每个瓦片内包含一个仅在点击时才显示的子物体(带渲染器)。
目前遇到异常:x>4的瓦片点击后,子物体虽存在但无法显示渲染器;奇怪的是,当将boardSizeY设置为6或更小时,所有x值对应的瓦片点击逻辑都能正常工作。
我已排查x、y的使用场景,也通过删减代码尝试定位问题,但仍毫无头绪,希望能有人指明排查方向。
相关脚本
CaselleTerreno.cs(挂载在游戏对象上的组件)
using UnityEngine; using TMPro; public class CaselleTerreno : MonoBehaviour { public GameObject tilePrefab; private int boardSizeX = 10; private int boardSizeY = 8; public float tileSize = 1f; public Sprite[] spriteSheet; public SpriteRenderer spriteRenderer; public int sliceIndex; public GameObject activeChild; public GameObject RightPane; public TextMeshProUGUI rightText; public GameObject overTileObject; private SpriteRenderer overTileObjectSpriteRenderer; private float randRange; private int OnTileObject; public static class MyConstants { public static readonly string[,] DATA = { {"31", " spreaded remains", "0", "0", "0", "0"}, {"32", " inhanimate creature", "10", "20", "30", "40"}, {"33", "n empty space", "0", "0", "0", "0"}, {"34", " dead creature", "10", "20", "30", "40"}, {"35", " metallic container", "11", "21", "31", "41"}, {"36", " dead bush", "12", "22", "32", "42"}, {"37", " abandoned metal object", "13", "23", "33", "43"}, {"38", "n half open trapdoor", "14", "24", "34", "44"}, {"39", " cocoon of a giant insect", "15", "25", "35", "45"}, {"40", " strange hard box", "16", "26", "36", "46"}, {"41", " strange vial", "17", "27", "37", "47"}, {"42", " giant boulder", "18", "28", "38", "48"}, {"43", " tuft of grass", "19", "29", "39", "49"}, {"44", " bizzarre succulent", "10", "20", "30", "40"}, {"45", " skeletal remain", "11", "21", "31", "41"}, {"46", " colony of arthropods", "12", "22", "32", "42"}, {"47", " packet", "13", "23", "33", "43"}, {"48", " plant", "14", "24", "34", "44"}, {"49", " bush with colorful berries", "15", "25", "35", "45"}, {"50", " fruit tree", "16", "26", "36", "46"}, {"51", " lively tree", "17", "27", "37", "47"}, {"52", " dry tree", "18", "28", "38", "48"} }; } void Start() { spriteSheet = Resources.LoadAll<Sprite>("TilesAtlasTerrain3"); RightPane = GameObject.Find("RightPane"); rightText = RightPane.transform.Find("Canvas/RightText").GetComponent<TextMeshProUGUI>(); for (int x = 0; x < boardSizeX; x++) { for (int y = 0; y < boardSizeY; y++) { randRange = Random.Range(0, 4) * 90f; GameObject tile = Instantiate(tilePrefab, new Vector3(x * tileSize, y * tileSize, 0), Quaternion.identity); tile.name = "Tile " + x + "_" + y; tile.transform.parent = transform; tile.GetComponent<TerrainTileScript>().rightText = rightText; activeChild = tile.transform.Find("SelectedRenderLayer").gameObject; activeChild.SetActive(false); spriteRenderer = tile.GetComponent<SpriteRenderer>(); if (Random.Range(0, 100) < 85){ sliceIndex = 0; } else { sliceIndex = Random.Range(0, 30); } spriteRenderer.sprite = spriteSheet[sliceIndex]; spriteRenderer.transform.Rotate(Vector3.forward, randRange, Space.Self); if (Random.Range(0f, 1f) < 0.725f) { OnTileObject = Random.Range(34, 53); } else { OnTileObject = 33; } overTileObject = tile.transform.Find("OverTileObject").gameObject; overTileObjectSpriteRenderer = overTileObject.GetComponent<SpriteRenderer>(); overTileObjectSpriteRenderer.sprite = spriteSheet[OnTileObject]; overTileObject.transform.Rotate(Vector3.forward, 360f - randRange, Space.Self); tile.GetComponent<TerrainTileScript>().descOnTileObj = MyConstants.DATA[OnTileObject -31, 1]; } } } }
TerrainTileScript.cs(TerrainTile资源的脚本)
using UnityEngine; using TMPro; public class TerrainTileScript : MonoBehaviour { public TextMeshProUGUI rightText; public string descOnTileObj; private void OnMouseDown() { rightText.text = "Clicked tile: " + name+ "\n"; CaselleTerreno caselleTerreno = GetComponentInParent<CaselleTerreno>(); GameObject activeChild = caselleTerreno.activeChild; if (activeChild != null) { activeChild.SetActive(false); } activeChild = transform.Find("SelectedRenderLayer").gameObject; activeChild.SetActive(true); caselleTerreno.activeChild = activeChild; GameObject OverActiveChild = transform.Find("OverTileObject").gameObject; SpriteRenderer spriteRenderer = OverActiveChild.GetComponent<SpriteRenderer>(); if (spriteRenderer != null) { string spriteName = spriteRenderer.sprite.name; string indexString = spriteName.Substring(spriteName.Length - 2, 2); rightText.text += "(contiene " + indexString + ")\n"; rightText.text += "There is a" + descOnTileObj + " here.\n"; } } }
排查方向
- 检查
CaselleTerreno中全局变量activeChild的覆盖问题:实例化所有瓦片时该变量会被逐个覆盖,点击瓦片时依赖它关闭上一个激活的子物体,可能出现逻辑错误。建议改为让每个瓦片自行管理激活状态,或用集合保存所有激活的子物体。 - 验证
transform.Find("SelectedRenderLayer")的有效性:在OnMouseDown中添加Debug.Log(activeChild),确认x>4的瓦片是否真的找到了子物体,排查命名或层级错误。 - 检查渲染遮挡与相机视口:确认x>4的瓦片及其子物体是否在相机视野内,子物体的Z轴位置是否被父瓦片遮挡,可尝试调整子物体Z值测试。
- 确认
OnMouseDown触发:在OnMouseDown开头添加Debug.Log("点击瓦片:" + name),检查x>4的瓦片是否能正常触发点击事件,排查碰撞体是否缺失或范围异常。 - 检查数组索引越界:
OnTileObject = Random.Range(34,53),确认spriteSheet长度是否≥53,数组越界会导致内存异常,引发不可预测行为。 - 检查父物体变换:瓦片父物体的缩放、旋转等变换是否导致x>4的瓦片位置偏移,子物体超出相机范围。
内容的提问来源于stack exchange,提问作者Muni Dr. Fractal
相关产品推荐
相关产品推荐

