Unity3D-iOS中使用Tilemap问题研究以及解决方案

前不久刚刚研究了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)

扫描二维码关注公众号,回复: 2827726 查看本文章

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以后可以把这个问题解决掉吧!如果有人觉得我这个方式麻烦,那么只有去找插件了,毕竟以前很多人都用过的。



猜你喜欢

转载自blog.csdn.net/pz789as/article/details/79662611