赞
踩
前不久刚刚研究了Unity3D的Tilemap,在编辑器里面捣鼓了半天,总算是弄明白怎么用了。
昨天想着可以上真机试试看,结果悲剧果然发生了。在iOS平台上无法显示Tilemap!准确来说,是在iOS平台,用代码初始化Tilemap没有效果,log里面你会看到下面的错误:
NullReferenceException: A null value was found where an object instance was required.
at UnityEngine.Tilemaps.TileBase.RefreshTile (Vector3Int position, UnityEngine.Tilemaps.ITilemap tilemap) [0x00000] in <filename unknown>:0
at UnityEngine.Tilemaps.Tilemap.SetTile (Vector3Int position, UnityEngine.Tilemaps.TileBase tile) [0x00000] in <filename unknown>:0
at GameManager+<InitData>c__Iterator0.MoveNext () [0x00000] in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
UnityEngine.Tilemaps.Tilemap:SetTile(Vector3Int, TileBase)
<InitData>c__Iterator0:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
Error running RefreshTile for previous TileNullReferenceException: A null value was found where an object instance was required.
at UnityEngine.Tilemaps.TileBase.RefreshTile (Vector3Int position, UnityEngine.Tilemaps.ITilemap tilemap) [0x00000] in <filename unknown>:0
at UnityEngine.Tilemaps.Tilemap.SetTile (Vector3Int position, UnityEngine.Tilemaps.TileBase tile) [0x00000] in <filename unknown>:0
at GameManager+<InitData>c__Iterator0.MoveNext () [0x00000] in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
UnityEngine.Tilemaps.Tilemap:SetTile(Vector3Int, TileBase)
<InitData>c__Iterator0:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
然后在网上找了很久,也没看见有人说解决方案,这是Unity官网上的问题,目前还没人解决掉。
在贴吧看到这个问题,也没人回答- -
然后就自己各种尝试,看看是不是哪里写错了,或者要弄清楚,这个到底还可以用不?
最后我尝试了好几种方式,弄清楚是怎么回事了,下面是我测试代码:
- //下面测试,如果 i < 25,那么是已经在编辑器中存在的 tile 做的操作
- int len = 5;
- for(int i=0;i<len*len;i++){
- tempIntPoint = new Vector3Int(i%len, i/len, 0);
- // Tile tempTile = testMap.GetTile<Tile>(tempIntPoint);
- // tempTile.color = listColorData[Random.Range(0, listColorData.Count)].mColor;
-
- //这种可以利用同样的Tile设置不同的颜色
- // testMap.RefreshTile(tempIntPoint);
-
- //这种设置颜色之后,所有引用同一个Tile的方块都会变色
- // testMap.SetTile(tempIntPoint, tempTile);
-
- //这种方式同上面的,所有方块都变,但是我这里使用的 Tile 是从预制中加载的
- // baseTile.color = listColorData[Random.Range(0, listColorData.Count)].mColor;
- // testMap.SetTile(tempIntPoint, baseTile);
-
- //因为 baseTile 和 testMap 里面已存在的 tile 引用的是同一个,所以还是会变色
- // baseTile.color = listColorData[Random.Range(0, listColorData.Count)].mColor;
- // testMap.RefreshTile(tempIntPoint);
-
- //这种方式同上,但是使用 Tile 是动态生成的,无法使用,iOS 上报 null 的错误
- // testMap.SetTile(tempIntPoint, listColorData[Random.Range(0, listColorData.Count)].mTile);
-
- //预先设置好的Tile,可以设置,但是不能超过 testMap 已存在的 tile
- // testTile.color = listColorData[Random.Range(0, listColorData.Count)].mColor;
- // testMap.SetTile(tempIntPoint, testTile);
- }
最后得出两个结论:
1、在iOS平台,Tilemap必须要预先设置好,意思就是说一开始在编辑器中填充好一个Tilemap,可以用纯色的色块,设置最大的宽高;
2、Tile不能是有代码创建的,上面第五个尝试就说明了这个问题,就算Tilemap预先填充了Tile,但是Tile是由代码创建的,还是会报错;
所以,这个问题的暂时解决方案就是Tilemap预先填充,Tile可以用同一块,然后在设置时,使用RefreshTile,这样可以达到想要的目标,也不需要想着预先生成多个地图块了。
我现在做的方式是:
1、在编辑器填充 Tilemap,最大化处理;
2、在编辑器中设置好需要用到的Tile;
3、在初始化Tilemap时,可以将Tile的Color的透明度设置为0,然后调用Tilemap的RefreshAllTiles,可以达到清除所有Tile的目的(间接清楚,看不到而已);
4、然后根据数据需要,设置Tile的颜色,图块,调用Tilemap的RefreshTile,这样就可以做到不同图块的显示了;
5、在要点击Tilempa改变图块时,要注意Tilemap的边界问题;
6、完毕!
希望Unity以后可以把这个问题解决掉吧!如果有人觉得我这个方式麻烦,那么只有去找插件了,毕竟以前很多人都用过的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。