在沙盒游戏里,能自由建造是很重要的特色,好比说风靡全球的《个人世界》,用一个个方块就能搭建出规模宏大的世界。甚至有偏激的人说,没有自由建造,就不是一个真正的沙盒游戏。的确,沙盒游戏的魅力有很大一部分是能自由构建一个游戏世界。看着本身一砖一瓦搭建起一个城堡世界会颇有成就感的。程序员
现现在的手游,大多数就是一个争斗和炫耀的世界。不论是传奇类的狂霸拽酷,仍是连连看,消消乐等好友排名,就是消费国人的虚荣心。其实,游戏是第九艺术,要上升到艺术的角度。在游戏里,玩家须要一种情感的宣泄和寄托以及体验。数据库
说了这么多,仍是回到正题。我是如何在本身编写的独立游戏《中世纪之路》里实现建筑物的摆放呢?函数
在实现这个功能的时候,我首先考虑的不是代码。而是考虑其余游戏是如何实现这样功能的,有那些能够借鉴的地方。我首先想到了《魔兽争霸》里建筑物的摆放,能够自由的拖放。而后想到了《部落冲突》(简称COC)里的建筑放置方式,在COC里建筑是按格子摆放的,在一个平面上。动画
在个人游戏《中世纪之路》里,我既不想让玩家一砖一瓦的搭建建筑,又想让玩家一下就把建筑总体放置到地上了。我以为像搭积木那样,既能够节省玩家时间,又有建造的乐趣。选定了这种方式后,我就要考虑建筑模块的数据储存方式了:我须要储存单个模块的三维空间里的坐标值(x,y,z的值),同时为了让模型选择,我还须要储存模型的旋转角度数。spa
而后,我还须要考虑如何用鼠标去执行这个操做。我构想的方案是:点击背包里的物品后,一个模型就动态产生,而后跟随鼠标在地面移动。而后按"E"键就放置到地面上鼠标所指的位置(E键放置,是我学《兽人必须死》得来的)。而组件的旋转呢?我考虑的是让鼠标滚轮(也就是中键)滚动时,就绕着Y轴旋转。固然若是更近一步,能够作到绕三个轴都能自由旋转。具体操做见下图:3d
建筑摆放动画code
使用鼠标放置篝火orm
经过上面的操做,咱们能够看到代码的实现效果很好,完美达到了咱们的需求。不过想通了上面的操做原理后,还须要咱们动脑筋来构思,如何用代码来实现这些操做功能。这对新手来讲可能过难了点,但对于有经验的开发者就能比较快的找到近似的解决方案,而后加以改进。blog
我首先想到的是我曾经在手机上作过2D积木的搭建功能。把咱们的操做动做拆解开来,无非就是三个步骤:游戏
1.第一次按下手指或者鼠标,找到初始坐标,让物体动态出如今坐标位置上。
2.而后判断移动状况,让物体跟随鼠标或者手指的移动。
3.最后抬起手指或者鼠标,让物体固定在最后的坐标位置,把坐标数据写入到文本或者数据库里。
想清楚了这三个步骤,咱们就内心底了,咱们只要实现了这三步操做代码,基本上物体摆放功能就能够实现了。
在我实现第一个步骤的时候,我就遇到了个问题。我以前在写搭积木游戏的时候是2D的,坐标很好获取。可是在《中世纪之路》里,我但是要获取的是鼠标在地面上的坐标点啊。我开始用的是两行代码:
Vector3 mousePosition= Input.mousePosition; //获取鼠标所在的坐标 Vector3 mouseWorldPosition =Camera.main.ScreenToWorldPoint(mousePosition) ; //把鼠标的坐标变成3D游戏世界里的空间坐标
我觉得个人思路是没问题的,结果运行代码一看。哈哈,建筑物彻底不是摆在地面上的啊,是在空中的啊。后来查了相关文档才知道,这个鼠标位置是鼠标在屏幕这个立体面上的位置(你能够想象屏幕是一个透明的立体墙,这个墙是树立在地面上的)。再说得专业点,是从主摄像机为起点,鼠标所指为终点的一个射线,与屏幕所在立体面相交的点。对于这个立体面的直观感受,你们能够看看在3D空间里2D UI界面所在的那个面。
因此,上面两行代码是不可以解决问题的。不过这么一分析,我就接触到了射线的概念。我转念一想,若是我找到这个射线和地面相交的焦点不就好了嘛!咱们的思路就变成了如下的伪代码:
1.建立一个从主摄像机为起点,鼠标所指为终点的一个射线Ray。
2.找到Ray和地面Terrain的交点position。
3.把物体的坐标动态建立于position。
核心代码以下:
if (Input.GetMouseButton(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if(Physics.Raycast(ray, out hit)) { if(hit.transform.name=="Terrain") { position = hit.point;//获得与地面碰撞点的坐标 } } }
解决这个核心难题后,移动的代码就很好写了。只要在手指或者鼠标移动的时候,动态更新物体的坐标为新的position就能够了。旋转物体的代码也能够写到一块儿,动态更新物体的旋转度就能够了。这段代码很容易写了,我就不贴出来了,新手能够锻炼自我动手能力。老手早就不用看在眼里了。固然须要提醒的是这段代码是须要在update函数里去运行的。
最后的固定物体坐标的代码,也就演变成了把最后的position记录于文本或者写入数据库了。这些代码都不是有多难写的。
最后回顾下,咱们整个解决问题的思路:
构思操做步骤和方式->分解操做步骤->用代码实现分解后的操做步骤->完善和修正代码
若是你们问我要整个代码,坦白的说:我以为"授人于鱼,不如授于渔"。你们能获取正确解决问题的思路就够了,而后记住核心代码就能够了。作程序员到一个“手中无剑,心中有剑”的境界就够了。固然新手仍是多练练剑,比划比划下招式。
PS:游戏DEMO试玩群:198035671 Unity3d技术交流群:308185833 斗鱼游戏开发直播地址:www.douyutv.com/unity3d