本文章使用的Unity版本为 Unity2018.4.36f1,脚本语言为C#
引言:
在上篇文章中,我们实现了我们想要的第一个功能,即根据周围的情况将瓦片图片变为合适的图片。在本篇文章中,我们就来实现第二个功能,这个功能的实现要比第一个容易很多。
正文:
还记得我们的第二个功能要实现一个怎样的功能吗,我们在上一篇文章中是这样描述的:
可以附加一个小人模样的游戏对象,并且每个小人的颜色都是随机得到的。
所以,在这篇文章中,我们要给瓦片附加一个小人,而且这个小人是以GameObject的形式存在的,并且在每次放置瓦片时,这个附加的小人的颜色是随机生成的,并不需要我们手动进行调整。
好,那开始实现!
还记得我们在该系列第二篇文章中讲到,在Tile类里有个成员变量叫gameobject吗,这个
成员变量在Inspector显示的名字叫instancedGameObejct,如下所示:
实际上它在代码中还叫作gameobject,我们通过为这个成员变量赋值(将一个游戏对象拖进变量中,例如某个预制体)来实现给瓦片实例挂载一个游戏对象。如下动图所示:?
记得一定是给我们创建的瓦片实例赋值,而不是我们写的脚本。(废话)
然后我们在用笔刷进行瓦片绘制,会发现,瓦片的旁边多出了一个游戏对象(这篇文章中是个小人)。每创建一个瓦片就会多出一个小人复制体。
是不是很神奇?? ?:)
其实这个实现过程中有一个步骤我没有讲,这是因为MyTile的父类Tile类已经帮我们写好了,这个步骤写在GetTileData方法里:
如上图所示,这一步骤就是将成员变量gameobject(实际上真实名字为instancedGameObejct)赋值给了tileData的gameobject,也就是将这一游戏对象传递给Tilemap系统,让它知道瓦片要挂载什么游戏对象。
那我们来实现最后步,给这个小人一个随机颜色。
这个功能放在StartUp方法里,该系列第一篇文章我们就讲了这个方法的目的:
?使用这个方法来给实例化的游戏对象赋值
说明这个方法很大的一个作用就是为了初始化这个挂载到瓦片上的游戏对象。
让我们看看这个方法:
StartUp(Vector3Int location, ITilemap tilemap, GameObject go)
注意到参数go了吗,这个go就代表挂载到瓦片上的那个游戏对象!
所以我们只要在方法里对go进行操作就行了。
敲出StartUp方法代码
?然后添加相应的逻辑
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
go.transform.position += new Vector3(0, 0.5f, 0);
go.GetComponent<SpriteRenderer>().color = new Color32((byte)Random.Range(1, 266), (byte)Random.Range(1, 266), (byte)Random.Range(1, 266), 255);
}
让小人的坐标往上偏移0.5。然后让颜色等于一个随机颜色。
这里的Color32不懂的话就自行百科吧。用了三个随机数来随机RGB的值,让a值为255。
可能细心的小伙伴也发现了,这个方法的返回值是bool类型的,所以要在最后返回一个bool值。那么为什么要返回bool值呢,这个bool值的真假会影响什么呢。答案是,不知道,Unity官方文档并没有说明,我自己测试过,不管返回真还是假都会正常调用StartUp方法也会顺利执行里面的逻辑,所以只能推测这个方法的返回值是为了方便我们实现一些特殊的逻辑了,例如有些情况返回真,有些情况返回假,然后根据该方法的返回值实现一些逻辑。
那我们就返回一个true吧,看着顺眼点。
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
Debug.Log("good");
go.transform.position += new Vector3(0, 0.5f, 0);
go.GetComponent<SpriteRenderer>().color = new Color32((byte)Random.Range(1, 266), (byte)Random.Range(1, 266), (byte)Random.Range(1, 266), 255);
return true;
}
好了,让我们测试一下功能。
?
没问题,既向上移动了一点距离,又随机生成了颜色。不过细心的小伙伴可能又发现了,小人的颜色不仅在绘制瓦片时随机生成了,在笔刷接近已经放置的瓦片时,瓦片上的小人颜色也会更改,这就和StartUp方法的调用时机有关了,忘记了该方法调用时机的小伙伴可以去第一篇文章重温一下。
当我们点击游戏开始按钮时,该方法在游戏的第一帧也会被调用,所以颜色还会改,每一次游戏都会不同。
好,那我们的所有功能就制作完毕了,我将所有的源代码放在了下方,有需要的小伙伴可自行复制。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
[CreateAssetMenu(menuName = "myTile")]
public class MyTile : Tile
{
public Sprite[] Sprites;
public override void RefreshTile(Vector3Int position, ITilemap tilemap)
{
base.RefreshTile(position, tilemap);
tilemap.RefreshTile(position + new Vector3Int(1, 0, 0));
tilemap.RefreshTile(position + new Vector3Int(-1, 0, 0));
tilemap.RefreshTile(position + new Vector3Int(0, 1, 0));
tilemap.RefreshTile(position + new Vector3Int(0, -1, 0));
}
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
base.GetTileData(position, tilemap, ref tileData);
int index = 0;
index = getIndex(position, tilemap);
tileData.sprite = Sprites[index];
}
public int getIndex(Vector3Int position, ITilemap tilemap)
{
string roadSituation = "";
if (tilemap.GetTile(position + new Vector3Int(-1, 0, 0)) == this)
roadSituation += "a";
if (tilemap.GetTile(position + new Vector3Int(1, 0, 0)) == this)
roadSituation += "b";
if (tilemap.GetTile(position + new Vector3Int(0, 1, 0)) == this)
roadSituation += "c";
if (tilemap.GetTile(position + new Vector3Int(0, -1, 0)) == this)
roadSituation += "d";
switch (roadSituation)
{
case "a":
return 1;
case "b":
return 1;
case "c":
return 0;
case "d":
return 0;
case "ab":
return 1;
case "ac":
return 2;
case "ad":
return 4;
case "bc":
return 3;
case "bd":
return 5;
case "cd":
return 0;
case "abc":
return 6;
case "abd":
return 7;
case "acd":
return 9;
case "bcd":
return 8;
case "abcd":
return 10;
}
return 0;
}
public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go)
{
go.transform.position += new Vector3(0, 0.5f, 0);
go.GetComponent<SpriteRenderer>().color = new Color32((byte)Random.Range(1, 266), (byte)Random.Range(1, 266), (byte)Random.Range(1, 266), 255);
return true;
}
}
如果这篇文章有帮到你,可以点个赞哟~
|