游戏开发日记:地图生成器(未完成版本
方案一:单纯使用随机数
思路:单纯随机实例化各种位置和大小的cube,生成墙壁,并且用不同的颜色(随机颜色)标识
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RandomBasedCreater : MonoBehaviour { /// <summary> /// 基本的地图土块元素的prefab,必须填 /// </summary> public GameObject _Cube; /// <summary> /// 地板的Prefab,必须填 /// </summary> public GameObject _Ground; //public Texture2D tex; /// <summary> /// 创造的地图图块数量 /// </summary> [SerializeField] int CubesAmount; // Use this for initialization void Start() { //开始创建墙壁 StartCoroutine(CreatMapBuildWalls(Mathf.Sqrt(CubesAmount),10)); //开始创建地图内容 StartCoroutine(CreatMapRandomly()); } /// <summary> /// 创建墙的协程 /// </summary> /// <param name="halfLength">边长的一半,一般是置为Mathf.Sqrt(CubesAmount)</param> /// <param name="height">墙的高度</param> /// <returns></returns> IEnumerator CreatMapBuildWalls(float halfLength,float height) { List<Vector3> Pos = new List<Vector3>(); Pos.Add(new Vector3(-halfLength, 0, 0)); Pos.Add(new Vector3(halfLength, 0, 0)); Pos.Add(new Vector3(0, 0, -halfLength)); Pos.Add(new Vector3(0, 0, halfLength)); foreach (Vector3 v in Pos) { GameObject go = Instantiate(_Cube, v, Quaternion.identity,transform) as GameObject; if (go.transform.position.x == 0f) { go.transform.localScale = new Vector3(2 * halfLength, 10, 1); } else { go.transform.localScale = new Vector3(1, 10, 2 * halfLength); } //可以改变墙创建的速度 yield return new WaitForSeconds(1); } } /// <summary> /// 随机创建地图的图块协程 /// </summary> /// <returns></returns> IEnumerator CreatMapRandomly() { GameObject Ground = Instantiate(_Ground, transform); Transform GroundTransform = Ground.transform; float _scale = Mathf.Sqrt(CubesAmount); //这个参数用来调节地板大小 GroundTransform.localScale = new Vector3(_scale / 5, _scale, _scale / 5); for (int i = 0; i <= CubesAmount; i++) { //生成的区域范围(调整来控制生成的位置范围 // Vector3 pos = new Vector3(_scale*SmoothRandom.Get(_scale) , 0, _scale * SmoothRandom.Get(_scale)); Vector3 pos = new Vector3(Random.Range(-_scale, _scale), 0, Random.Range(-_scale, _scale)); //Vector3 pos = Mathf.Sqrt(CubesAmount) * SmoothRandom.GetVector3(1000); //下面是一个生成圆形区域的例子.类似地,可以用这个方法来生成一些其他的图形,只要确定其对应的函数就可以了 //分割线----------------------------------------------------- // float _t = Random.Range(-_scale, _scale); // Vector3 pos = new Vector3(_t*Mathf.Sin(_t),0,_t*Mathf.Cos(_t)); //分割线--------------------------------------------------- GameObject _go = Instantiate(_Cube, pos, Quaternion.identity, transform) as GameObject; //随机颜色 _go.GetComponent<MeshRenderer>().material.color = Random.ColorHSV(); //随机大小(可以调整 float rfloat = Random.Range(1, 5f); float yfloat = Random.Range(1, 10f); _go.transform.localScale = new Vector3(rfloat, yfloat, rfloat); //生成速度 yield return new WaitForSeconds(0.001f); print(i); } } }
大概效果如图
感觉非常杂乱无章
如果把生成的cube数目扩大,也许有能用的部分。但是要控制cube的scale的取值范围,最好是通过实验得到一个比较符合需求的scale
方案二:读取图像,然后做运算
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 使用这个类需要注意的是,sourceTex的属性必须将Read/Write Enable设为true(在Advanced选项卡里 /// </summary> public class ImageBasedCreater : MonoBehaviour { //游戏物体的List private List<GameObject> _ListOfGameObjects; //源图像 public Texture2D sourceTex; //生成物体的Prefab public GameObject _Cube; void Start() { //新建物体的列表 _ListOfGameObjects = new List<GameObject>(); //协程生成 StartCoroutine(GenerateImageCubes()); } /// <summary> /// 根据图像生成cube地图的协程 /// </summary> /// <returns></returns> IEnumerator GenerateImageCubes() { //得到源图像的颜色数组 Color[] pix = sourceTex.GetPixels(0, 0, sourceTex.width, sourceTex.height); //迭代次数 int i = 0; //生成位置 Vector3 pos = new Vector3(); //生成的正方形边长 float fx = Mathf.Sqrt(pix.Length); //单次生成数目的计数器 int index = 0; //生成的Cube对象 GameObject go; //遍历颜色数组生成地图 foreach (var c in pix) { pos.x = i / fx; pos.z = i % fx; //if (!(c.r <= 100f/225f && c.g <= 100f / 225f && c.b <= 100f / 225f) ){ go = Instantiate(_Cube, pos, Quaternion.identity); //生成的cube的高度的表达式,可以修改 //float Height= (c.r * c.g * c.b) * 20; float Height = 1; go.transform.localScale = new Vector3(1, Height, 1); //生成原图对应的颜色 go.GetComponent<MeshRenderer>().material.color = c; _ListOfGameObjects.Add(go); //} //循环计数器的递增 i++; // print(c); print("num:" + i + " " + c); //单次生成数目计数器的递增 index++; //控制每次调用生成的cube数目 if (index >= 127) { index = 0; yield return 0; } } } }
然后看下范例
也可以用来生成一些有趣的图形,比如
Chorme图标
UNITY图标
缺点:
可以使用的图形实在是太小了。这种直接生成游戏物体的行为是非常消耗资源的
第三种方法:动态生成mesh