3. 读取地图

本贴最后更新于 2653 天前,其中的信息可能已经渤澥桑田

流星里地图文件读取出来需要解析 gmb 文件和 des 文件,部分模型可能与 gmc 相关
类似假设点击第一关 炎硫岛 就会触发如下逻辑
读取 sn14.des,为什么是这一个是因为 meteor.res 里指定的
读取 sn14.gmb
des 文件描述了这个关卡里的实体和场景物品列表[虚体]
释义 sn14.des
SceneObjects 66 DummeyObjects 92 场景实体有 66 个 场景物品有 92 个
Object Plane01 物品名称
{
Position: 42.823 13.902 -14.560 位置世界变换
Quaternion: -1.000 0.000 0.000 0.000 旋转世界变换
TextureAnimation: 0 0.000 0.000 UV 动画速度
Custom:自身属性
{
}
}
一般来说 des 文件里每一个实体的模型数据都在 gmb 文件里可以找到,而且坐标,旋转等无需设置,gmb 里的坐标即为世界坐标系,已经跟你算好了
gmb 和 des 是很大关系的,有了世界变换矩阵,很容易就可以将在 gmb 里的顶点数据转换到模型空间,然后再在 u3d 里设置 gameobject 的世界变换矩阵

(2 种有什么区别?)
解释一下,一种是一个 gameObject,放在原点,然后添加 MeshFilter 组件,组件上的 Mesh 顶点数据,与 gmb 文件里一样,但是这种时候,一旦此物体绕 Y 轴旋转,那么就是绕原点过 Y 轴转动
如果是一个 gameObject 设置为 des 文件里描述的坐标,那么其就可以绕自身的轴心过 Y 轴转动,不同的是他的 MeshFilter 里的 Mesh 顶点数据,需要通过 gmb 里的顶点,通过世界变换矩阵的逆矩阵算出来

注意看右上角,坐标

注意看右上角,坐标

场景物品,指的是,属性箱子,武器箱子,酒坛,板凳等一些场景上与玩家发生交互的动态物品,这部分数据一般在 cmodel 下有其对应的 des 文件描述

要用 U3D 里显示一个地图,最好的办法是在编辑状态下调用加载地图函数,然后贴图或者其他不正确的地方,由于地图已经在编辑状态下的场景中,所以我们可以随便调整
还是使用上次创建的工程
要加载地图,数据是必不可少的,类似 des,gmb 还有地图上模型贴图,都要放到 Resources 目录下。
其次,des 文件和 gmc 文件以及 gmc 文件,都需要在后缀上加入.bytes,这个是 u3d 读取自定义数据的方法,如果不清楚可以下载源工程查看目录结构

新建一个编辑器类 LoadInspector 放在"Assets/Meteor/Editor/"目录下
新建一个 MapLoader 类放在"Assets"目录下,此类用于加载地图的静态部分
新建一个 Loader 类放在"Assets"目录下,此类用于加载地图的动态部分
在 MapLoader 类里增加一个接口,我希望加载指定的地图的时候,就读取指定的地图到我的此场景内,并且把所有地图元素添加到一个地图根节点上
于是在 MapLoader 类里设计 public void LoadMap(int level)接口
在 Loader 类里设计 public void LoadSceneObjs(int level)接口

在 LoadInspector 类里添加

[CustomEditor(typeof(Loader))]
public class LoadInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Loader myTarget = (Loader)target;
if (GUILayout.Button("AddSceneObj"))
{
myTarget.LoadSceneObjs(myTarget.LevelId);
}
}
}
[CustomEditor(typeof(MapLoader))]
public class MapLoaderInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
MapLoader myTarget = (MapLoader)target;
if (GUILayout.Button("Load"))
{
myTarget.LoadMap(myTarget.levelId);
}
}
}
新建一个场景叫 MapLoader,创建一个空物体(Map),放在原点(0,0,0)各项属性都重置,无位置,旋转,缩放为 1
在这个物体上加上我们创建的 2 个组件类,一个 MapLoader,一个 Loader
在解读一个地图前,我们需要定义一些资源解析类
DesLoader,GmbLoader,GmcLoader
由于代码量还是有一些,所以还是放图和工程吧

由于原本的游戏工程关联性比较强,所以一些还未实现的模块类似脚本模块,暂时注释起来了,这个工程只加载了地图和场景道具
而且内置的表格数据,关卡 id 15 对应的炎硫岛地图,所以里面的 id 值都填的 15 地图表格文件为 fubenbase.txt,第一个就是 id goodlist 就是关卡的物品列表 sn14 之类的

还是说几点。
第一。由于任意一个关卡,可能引用到任意模型,等数据,所以整个模型,以及贴图等资源都得放到工程里,所以会导致工程比较大【此工程只导入了 sn14 的地图贴图,要导入其他的地图,需要自行导入贴图以及 des gmb 文件】

第二。由于配置里写明了有些模式下,一些物品是不应该出现的,但是工程里是全部显示,所以可能与游戏里剧情模式下物品不是一致的

第三。流星里的 shader 和灯光是全部忽略了的,所以地图和实际显示不一致,这个要自己按照原本流星的 shader 来调整,这部分由于不是太熟悉动态控制创建 shader 并且设置二层的叠加模式,以及一些参数,所以都忽略了
(我个人知道的都是事先写好一个模式的 shader 来使用,如果是这样,就需要把流星使用的 shader 列一个表,按照每个类型的 shader 一个个来写。不过这样比较耗时,每种 shader 组合的方式(参数,包括有无 uv 动画,是否双面,是否透明,以及叠加模式等等)也是太多)

好了,附上一张图

工程地址
http://pan.baidu.com/s/1gfh8tph

代码里有个 BUG,那就是不但实体名称要相同而且实体的序号也要和 gmb 里的模型序号相同,否则 2 个同名称的实体,会导致模型错乱,在皇天城,有二座屋子的楼顶会因此无法正常显示[只需要序号相同,客户端不会判定名字]

2017/10/12 更新
地图读取逻辑应该是
GMB 里每个对象有顶点组(右手坐标系)
DES 文件里有该对象的世界变换矩阵(右手坐标系)
读取时,先用顶点按照 世界变换矩阵的逆矩阵,变换到自身坐标系
然后创建一个 GameObject。添加 MeshFilter 时,把变换到自身坐标系的数据写进其 Mesh 中
然后设置该 GameObject 的世界变换矩阵为 Des 中该对象的一样(坐标系要转换)
这样再针对材质和 Mesh 用 AssetDataBase.CreateAsset(mat[x], "xx.mat") CreateAsset(mesh[x], "xx.asset")存储到本地目录中
这样任意一个地图加载后,如果要其中的某个子物件就可以直接找到 mesh 使用了,很容易就可以修改地图

保存材质列表,需要说一下,一般流星的地图,会这样设计材质引用
首先是材质列表 简单来说,就是一个 unlit/texture 加他指定的一张贴图
其次是 shader 列表
这样我们先生成 与材质列表数量一样多的材质,Material[] mat = new Material[gmb.TexturesCount];
然后对每个材质,赋上贴图
然后针对每个 Mesh 的每个三角面,都会引用一个 shader,而这个 shader 里又会指明用哪个序号的材质,这样每个 Mesh 的每个子网格都有一个材质球和一个 shader 共同起作用。
材质球记录了贴图等一些 shader 相关属性的数据,shader 决定 blend 算法,以及是否双面 透明度

假设以金华城的一个屋子 ian1633 作为示例
读取 sn13.gmb
会得到其中有
45 张贴图

我们创建 45 个材质

	   string shaders = "Unlit/Texture";
    //shaders = "Mobile/Diffuse";
    Material[] mat = new Material[gmb.TexturesCount];
    for (int x = 0; x < gmb.TexturesCount; x++)
    {
        mat[x] = new Material(Shader.Find(shaders));
        string tex = gmb.TexturesNames[x];
        int del = tex.LastIndexOf('.');
        if (del != -1)
            tex = tex.Substring(0, del);
        Texture texture = Resources.Load<Texture>(tex);
        //这里的贴图可能是一个ifl文件,这种先不考虑,手动修改
        if (texture == null)
            Debug.LogError("texture miss:" + tex);
        mat[x].SetTexture("_MainTex", texture);
        mat[x].name = string.Format("{0:D2}_{1:D2}", level, x);
        AssetDatabase.CreateAsset(mat[x], "Assets/Materials/" +  level + "/" + mat[x].name + ".mat");
        AssetDatabase.Refresh();
    }

48 个 shader

然后这个 mesh 引用了 22,16,15,17,19,这 5 个 shader
22 号引用的第 20 号贴图 贴图名称 sn13h07.jpg
16 号引用的第 15 号贴图,贴图名称 sn13h03.jpg
...

这样通过引用贴图,实际就是找到了对应的材质球,然后赋给网格材质球数组就可以了
List targetMat = new List();
targetMat.Add(mat[shader 数据里的贴图序号]);
MeshRenderer mr = objMesh.AddComponent();
mr.materials = targetMat.ToArray();
这样网格就可以勉强显示出贴图了(shader 里其他的参数对效果起了很大影响,但是在这里统一使用的是 unlit/texture 无光照贴图,这样地图上很多东西显示还是不正常的)

举个例子,在地图里有一些阴影贴图,代表模型受光照后投射到地面(或其他模型)上的影子。
还是用金华城举例子
他第二个元件就是
sd003,命名上就有 shadow003 缩写的示意,他是一个桥下的阴影
所以我们在之前的基础上给这个模型的材质,换一个 shader 用来显示阴影
shader 分有光和无光跟光照有关系。
总之现在的手游采用的方式都是 场景静态物烘产生 Lightmap,动态物用 light probe 打区域灯,角色用 projector 做投影。
完毕后让 sd003 的材质球使用这个 shader,然后在材质球参数上调整 Times 参数,就可以看到这个阴影贴图,会变暗或者变亮,看上去就好像阳光照在其上的物体所形成的阴影一样

Times 参数很大,导致很暗

调整 shader 的参数 Times 后像阴影了

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • gRpc
    11 引用 • 9 回帖 • 82 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    98 引用 • 345 回帖
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 215 关注
  • abitmean

    有点意思就行了

    31 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    77 引用 • 430 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 425 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 72 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 2 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 236 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 1 关注
  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    23 引用 • 32 回帖 • 1 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    92 引用 • 752 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 86 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 1 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    498 引用 • 1388 回帖 • 262 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    8 引用 • 30 回帖 • 414 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 13 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 148 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 263 关注