yande.re 355745 sample animal_ears cleavage dress marron_(shiratama) shiratama shiratamaco.jpg
上一篇:


第六节 创建面板物体管理器



创建Board脚本。设定scale大小,将地图空间纳入数组,进行空间判断,从而顺利部署建筑。创建一个二维数组,将建筑位置信息一一对应存储进去。x,y轴坐标作为索引。
面板管理主要是控制建筑物生成,完成建筑在世界地图的部署放置,以及一些交互功能。
控制建筑物部署,则需要和一个建筑物生成控制器controller进行交互(后面我们会具体实现),控制器通过检测鼠标所在世界坐标位置,告诉面板管理,我此刻准备将何种建筑放置在何处,此处是否已有建筑,这些信息交互,需要面板管理脚本进行分析交互,然后生成对应实例化建筑,摆放在对应位置。这部分内容是和玩家体验最直接相关,感官最明显的部分,实现原理倒不难,我们这节创建基本的面板控制器,下一节再创建建筑生成控制器,与面板进行交互。
这个game 管理面板board,可以挂载到任何游戏物体上,我们这里挂载到ground地图上好了。
我们之前提到,将整个地图grid网格化,对应一个单位坐标放置存储一个建筑,这样我们可以直接通过坐标值规范摆放建筑,同时坐标值又可以拿来担当数组array的index索引功能,简化整个建筑部署位置判断和建筑信息调取查询。

private Building[,]buildings = new Building[100,100];

一个逗号表示左右可以填写2个常量表达式,表示创建的是二位数组,100,100代表我们数组大小为100x100个元素,这个大小对应咱们ground尺寸,如果你是50x50的ground,自己修改为对应大小即可。
start()中演示:

Buildings[20,30]

这表示第二十行第三十列index的建筑,同时,由于咱们的建筑坐标也是对应1个单元放置一个,这同时也代表这个建筑位于我们坐标系(20,hight,30),这就是简化方案,同时获得建筑在地图坐标上的位置(世界地图上物理位置),和建筑存储在数组中的编号索引(从而获得建筑类型等具体建筑信息)。如果咱们建筑不是一个单元一个单元的,这样我们在世界坐标操作交互建筑的时候,还需要检测碰撞点,判断是否存在实例化建筑,然后查找出索引值,再从数组里寻找对应建筑存储位,再得到建筑具体类型等信息,就来的复杂一些了。
我们直接通过坐标值对应array索引位,去array查找这个索引是否存在建筑,直接就可以判断对应鼠标放的坐标位置是否存在建筑,这样就简化碰撞检测,不需要射线检测或者物理碰撞检测之类的方式判断能否在对应坐标部署建筑。
数组的作用讲解完毕,我们现在考虑鼠标获取建筑后,准备在指定坐标安放建筑,这个功能实现,需要用到对应方法,于是新建一个

public void AddBuilding(Building building,Vector3 position)

因为我们要获得建筑类型和鼠标点击坐标位置两个信息,故返回这两个参数。
这样我们通过调用生成建筑AddBuilding方法,就可以知道需要生成什么类型的建筑,建筑应该摆放在世界地图哪个位置。
对于这个位置,我们鼠标肯定不能得到准确的整数位置信息,很可能是37.633之类的坐标,那么最终下达安放指令,应该给这个方法一个小数坐标对应的最近整数坐标,或者说,告诉这个方法,鼠标位于哪个整数网格里,这就用到了Mathf。round函数了
我们新建一个方法,目的是将传入的position float坐标转换成对应round后的int整数坐标位置,再去刚才的addbuilding方法里调用。

public Vector3 CalculateGridPosition(Vector3 position)
    {
        return new Vector3(Mathf.Round(position.x),1.0f,Mathf.Round(position.z));
    }

好了,坐标转换方法大致意思ok,我们再次进入AddBuilding方法进行具体实现

Building buildingToAdd = Instantiate(building,position,Quaternion.identity);

这句话意思是,我们将要部署的建筑,将它实例化,实例化参数则是,建筑类型,建筑位置,建筑方位,四元数下identity组件代表就是默认摆放方位,我们之前已经处理好了建筑默认方位信息,这里直接用默认的即可。
继续:

Buildings [position.x,position.z]=buildingToAdd;
}

这是什么意思呢?我们刚才实例化了一个建筑,现在要将这个建筑存储到数组里,具体存储到哪个索引位呢?我们刚才说了,利用建筑所在坐标对应整数坐标数值,来当作该建筑对应存储数组里的索引值,我们这里position.x实际上用处不是坐标了,而是要将转化成int后的坐标值引用充当array里面索引值,将每一个实例化出来的建筑,同时存储登记进这个管理array里面,交出对应int后的坐标值,直接作为登记序号,一家人排列的整整齐齐。
好了,加个int转换
Buildings [position.x,position.z]这里的position值转化为int即可,即:

buildings[(int)position.x, (int)position.z] = buildingToAdd;

这句话和 Building buildingToAdd=Instantiate(building,position,Quaternion,identity);连起来,我们目的可以合成一句话,那就是

buildings [(int)position.x, (int)position.z] = Instantiate(building,position,Quaternion.identity);

产生一个新实例化的building,将其具体建筑类型,摆放位置,自身朝向都赋值ok,同时存储该building入编array数组进行保存登记索引位。
最后,我们部署新建筑的时候,需要判断该坐标位是否已经存在建筑,做一个判断方法:

public bool IsBuildingHere(Vector3 position)
{
    return buildings[(int)position.x, (int)position.z]!=null;
}

如果这个索引位不为空,则表示有建筑,返回true,表示已存在建筑。
这个方法到时候调取也是通过数组索引值判断,所以也需要转换为int整数。
这个功能方便之后部署建筑或者拆除建筑进行判断。
好了,目前位置,我们管控建筑物体的控制面板,应该基本功能都完成了,挂载面板到咱们的ground物体吧!
下一节我们将实现物品放置功能和一些面板操作具体实现,这 将与这节的面板控制进行深度交互,后续移除建筑功能和调整建筑摆放方向的功能,等最后再完善细节了。
下一篇:

Last modification:August 6, 2020
If you think my article is useful to you, please feel free to appreciate