【Unity3D】利用TextAsset读入文件并生成地图

Unity3D可以利用C#的文件流读入文件,但不建议这样做,因为自身就提供了一个TextAsset用于读入数据,尤其是可以将一个关键的csv和txt文件放到Resource文件中,让发布的时候能让其自动打包,不会让用户轻易修改看上去没这么业余。同时比起《【C#】txt的读写》(点击打开链接)的读入方法,利用TextAsset读入数据,比文件流更加简单。下面举一个例子来说明这个问题。

有一个这样的map.csv地图文件:

1,1,1,1,1,0,1
1,0,0,0,1,0,1
1,0,2,0,2,0,1
1,0,1,0,1,0,1
1,0,1,0,0,0,1
1,0,2,0,2,0,1
1,0,1,1,1,1,1
转成UTF-8编码的,避免乱码,天地可鉴。


要按照上面的地图配置csv(可以用Excel编辑;保存成txt都没问题),生成如下的7x7地图,其中1代表墙高1个单位,2代表墙高2个单位,0代表没有墙。用逗号分割出一个个单位。


地图换一个视觉则如下所示:


当然地图简陋无比,这灯光和摄像机整成的渣画面,绝对无法上架,但原理就是这个原理,你让你的策划MM(哪有这么多MM?有也是有另一半的-_-!)布置一张1个亿x1个亿的地图也是这样生成的。制作过程如下:

我们根本就不需要在场景布置任何东西,你只要将摄像机和灯光放到合适位置就行,设置你可以脚本生成灯光和控制摄像机。我这里是用了一个Point light在这迷宫上方,有更好的灯光布置方式真的请多加指教!你只要在Asset新建一个Rescource文件夹,将上述的Map.csv如同《【Unity3D】BGM》(点击打开链接)中的BGM或者《【Unity3D】对话》(点击打开链接)中的对白导入到这个Rescoure文件夹则行。


整一个空物体布置如下的Map.cs就行。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;//这里用到了C#容器

public class Map : MonoBehaviour
{

    void Start()
    {
        TextAsset textAsset = (TextAsset)Resources.Load("Map");//载入Map.csv,注意不要有其它格式叫Map的,或许有未知错误
        string[] map_row_string = textAsset.text.Trim().Split('\n');//清除这个Map.csv前前后后的换行,空格之类的,并按换行符分割每一行
        int map_row_max_cells = 0;//计算这个二维表中,最大列数,也就是在一行中最多有个单元格
        List<List<string>> map_Collections = new List<List<string>>();//设置一个C#容器map_Collections
        for (int i = 0; i < map_row_string.Length; i++)//读取每一行的数据
        {
            List<string> map_row = new List<string>(map_row_string[i].Split(','));//按逗号分割每个一个单元格
            if (map_row_max_cells < map_row.Count)
            {//求一行中最多有个单元格,未来要据此生成一个Plane来放Cube的
                map_row_max_cells = map_row.Count;
            }
            map_Collections.Add(map_row);//整理好,放到容器map_Collections中
        }

        /*生成一个刚好放好Cube的Plane*/
        GameObject map_plane = GameObject.CreatePrimitive(PrimitiveType.Plane);//生成一个Plane
        map_plane.transform.position = new Vector3(0, 0, 0);//放到(0,0,0)这个位置
        //求其原始大小
        float map_plane_original_x_size = map_plane.GetComponent<MeshFilter>().mesh.bounds.size.x;
        float map_plane_original_z_size = map_plane.GetComponent<MeshFilter>().mesh.bounds.size.z;
        //缩放这个Map到所需大小,刚好和二维表匹配
        float map_plane_x = map_row_max_cells / map_plane_original_x_size;
        float map_plane_z = map_Collections.Count / map_plane_original_z_size;
        map_plane.transform.localScale = new Vector3(map_plane_x, 1, map_plane_z);

        /*在Plane上放Cube*/
        for (int i = 0; i < map_Collections.Count; i++)//Z方向是长度就是容器的大小,也就是map.csv有多少有效的行
        {
            for (int j = 0; j < map_Collections[i].Count; j++)
            {//X方向的宽度就是容器一行中的最大的长度,也就是map.csv中每行最大长度
                int cube_num = int.Parse(map_Collections[i][j]);//将每个单元格的数字转换成整形                
                for (int k = 0; k < cube_num; k++)
                {//根据数字,在一个单元格内生成cube
                    GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    cube.transform.position = new Vector3(-(map_row_max_cells / 2) + i, (float)0.5 + k, -(map_Collections.Count / 2) + j);
                    /*
                     cube所处的坐标就是(-(map_row_max_cells / 2) + i, (float)0.5 + k, -(map_Collections.Count / 2) + j)
                     */
                }
            }
        }
    }

}
整个算法的思想如下图所示:


首先要注意的是,笛卡尔三维坐标系Y是垂直的轴。

然后算法内,在Unity3D你要缩放一个物体,只能用到~.transform.localScale去单位缩放,也就是说只能设置缩放多少倍,但我们就是要将原本默认的10x10的Plane缩放的7x7该怎么做呢?就是要利用~.GetComponent<MeshFilter>().mesh.bounds.size.X/Y/Z;求出该物体在X/Y/Z轴的原始尺寸,然后再用7/这个原始尺寸,就是我们要这个物体缩放的比例。

最后,至于这些二维表文件配合容器处理的思想,可以参考《【C#】读取txt、csv等二维表》(点击打开链接)和《【Java】一行代码读完记事本中的二维表》(点击打开链接)我已经一些再写了,不赘述了。


  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值