在沙盒游戏里,能自由建造是很重要的特点,比如说风靡全球的《我的世界》,用一个个方块就能搭建出规模宏大的世界。甚至有偏激的人说,没有自由建造,就不是一个真正的沙盒游戏。的确,沙盒游戏的魅力有很大一部分是能自由构建一个游戏世界。看着自己一砖一瓦搭建起一个城堡世界会很有成就感的。

现如今的手游,大多数就是一个争斗和炫耀的世界。不管是传奇类的狂霸拽酷,还是连连看,消消乐等好友排名,就是消费国人的虚荣心。其实,游戏是第九艺术,要上升到艺术的角度。在游戏里,玩家需要一种情感的宣泄和寄托以及体验。

说了这么多,还是回到正题。我是如何在自己编写的独立游戏《中世纪之路》里实现建筑物的摆放呢?

在实现这个功能的时候,我首先考虑的不是代码。而是考虑其他游戏是如何实现这样功能的,有那些可以借鉴的地方。我首先想到了《魔兽争霸》里建筑物的摆放,可以自由的拖放。然后想到了《部落冲突》(简称COC)里的建筑放置方式,在COC里建筑是按格子摆放的,在一个平面上。

在我的游戏《中世纪之路》里,我既不想让玩家一砖一瓦的搭建建筑,又想让玩家一下就把建筑整体放置到地上了。我觉得像搭积木那样,既可以节省玩家时间,又有建造的乐趣。选定了这种方式后,我就要考虑建筑模块的数据储存方式了:我需要储存单个模块的三维空间里的坐标值(x,y,z的值),同时为了让模型选择,我还需要储存模型的旋转角度数。

然后,我还需要考虑如何用鼠标去执行这个操作。我构想的方案是:点击背包里的物品后,一个模型就动态产生,然后跟随鼠标在地面移动。然后按"E"键就放置到地面上鼠标所指的位置(E键放置,是我学《兽人必须死》得来的)。而组件的旋转呢?我考虑的是让鼠标滚轮(也就是中键)滚动时,就绕着Y轴旋转。当然如果更近一步,可以做到绕三个轴都能自由旋转。具体操作见下图:

建筑摆放动画

使用鼠标放置篝火

通过上面的操作,我们可以看到代码的实现效果很好,完美达到了我们的需求。不过想通了上面的操作原理后,还需要我们动脑筋来构思,如何用代码来实现这些操作功能。这对新手来说可能过难了点,但对于有经验的开发者就能比较快的找到近似的解决方案,然后加以改进。

我首先想到的是我曾经在手机上做过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())
{
    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

Unity3D独立游戏开发日记(二):摆放建筑物的更多相关文章

  1. Unity3D独立游戏开发日记(一):动态生成树木

    目前写的独立游戏是一个沙盒类型的游戏.游戏DEMO视频如下: 提到沙盒类型的游戏,就有人给出了这样的定义: 游戏世界离现实世界越近,自由度.随机度越高才叫沙盒游戏.所谓自由度,就是你在游戏里想干啥就干 ...

  2. unity独立游戏开发日记2018/09/27

    今天优化了下昨天的代码,并且添加了树木和其他资源的生成.还修复了接近石头后,挖掘图标不出现的bug.目前可以在unity中稳定60-70fps. 详看文章:https://www.cnblogs.co ...

  3. 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结

    前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...

  4. 关于《Unity3D/2D游戏开发从0到1》书籍再版说明

    关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于U ...

  5. 《Unity3D/2D游戏开发从0到1》正式出版发行

    <Unity3D/2D游戏开发从0到1>正式出版发行 去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息:      书籍的名称: <Uni ...

  6. Unity3D 入门 游戏开发 Unity3D portal game development

    Unity3D 入门 游戏开发 Unity3D portal game development 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com ...

  7. Unity3D手机游戏开发

    <Unity3D手机游戏开发> 基本信息 作者: 金玺曾 出版社:清华大学出版社 ISBN:9787302325550 上架时间:2013-8-7 出版日期:2013 年8月 开本:16开 ...

  8. 项目游戏开发日记 No.0x000005

    14软二杨近星(2014551622) 还有一周就要交项目了, 看着周围的人也都忙碌了起来, 看着大部分人的项目都已经初具容貌, 我们团队里面也搞得人心惶惶, 一来是, 时间不多了, 还有很多事情要做 ...

  9. 项目游戏开发日记 No.0x000002

    14软二杨近星(2014551622) 项目开发的开始, 到现在已经很久了, 软件工程的课也上了很久了, 不过, 我们的游戏现在依然还没有影子, 只能说...还是啥也不会... 从一开始, 兴致勃勃地 ...

随机推荐

  1. 在linux下修改mysql的root密码

    第一种方法: root用户登录系统 /usr/local/mysql/bin/mysqladmin -u root -p password 新密码 enter password 旧密码 第二种方法: ...

  2. centos6.7 安装Docker

      一.查看系统版本 [root@localhost ~]# cat /etc/redhat-release CentOS release 6.7 (Final) 二.安装EPEL 1.进入cento ...

  3. Linux内核阅读相关

    一.likely()与unlikely()函数的意义 http://blog.chinaunix.net/uid-27665626-id-3506567.html 二.TSO.UFO.GSO.LRO. ...

  4. multiprocessing module in python(转)

    序.multiprocessing python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了非常好用的多进程包mu ...

  5. redis watch multi exec 关系

    EXEC 执行所有事务块内的命令. 假如某个(或某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么EXEC 命令只在这个(或这些) key 没有 ...

  6. linux 删除已输入的命令行

    ctrl + w —往前删除一个单词,光标放在最末尾ctrl + k —删除到末尾,光标放在最前面(可以使用ctrl+a) —————————————————————-华丽的分割线ctl + u 删除 ...

  7. xml in hadoop ETL with pig summary

    项目中需要把source为xml的文件通过flume放置到hdfs,然后通过MR导入到vertica中去,我之前做过简单的 尝试,是通过pig的piggybank的xmlloader然后Regex_e ...

  8. UVALive 6257 Chemist's vows --一道题的三种解法(模拟,DFS,DP)

    题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有 ...

  9. C#带cookie Post和Get方式发送数据,保持cookie

    在实际编程中,可能需要读取特定网页的信息,但很多网站需要用户登录后,才能够获取相关的页面内容,这就需要编程者先临时存储当前的cookie,在C#中可以使用CookieContainer 对象来保存登录 ...

  10. js常用宽高属性

    document.body.clientWidth //body对象的宽度 document.body.clientHeight //body对象的高度 document.documentElemen ...