近期学校有一个3d游戏的项目实训,要求学生组成项目组共同完成一个3d游戏的制作。当然,游戏制作过程中的所有任务,包括设计、策划、美工、编码、测试等等,都将由我们自己完成。我们的项目组决定制作一款类似球球大作战以“吞食”为核心玩法的休闲游戏,游戏的主角是鲲(?),另外我们的游戏场景要做成3d版本。我们的项目组采用Unity引擎进行游戏开发,并且打算实现在线多人对战的功能。项目实训开始到今天已经经过约一周时间,在这一周时间内我们其实主要还是以学习为主,不过也完成了游戏指针过程中的一些任务。我在这一周内的学习成果和工作成果主要包括两方面:

一:系统总体设计文档的编写:

这一部分的内容还是比较多的,虽然有一份文档模板,但由于之前没有类似的经验,所以一开始写起来还是觉得有点困难。我在编写文档之前也在网上查阅了一些关于文档编写的资料,同时结合实际的文档编写过程,作出了下面的一些个人总结,包括内容和编写技巧两个方面。

在文档的内容方面:

1.总体设计:主要对整个游戏进行一些概要性的说明,包括功能模块、关卡设计、界面设计、交互事件设计等等。

功能模块可以理解为游戏开发时所需要的一些主要的组件,如场景定义、事件处理等等(功能模块从用户的角度来说也可以游戏提供提供给用户的一些子系统,如好友系统、排名系统等等);

关卡设计中定义主游戏场景中的一些规则;

另外交互事件不只包括玩家输入,也包括AI等元素触发的其他事件。

2.游戏状态转换设计:游戏中的状态包括主界面、游戏进行中等状态。

3.总体架构设计:整个游戏开发过程采用的架构模式。网络多人对战游戏一般采用客户端/服务器的架构模式。

在文档的编写技巧方面:

1.注意文档的内容一定要清晰准确,不能出现“可以这么做”“可能要”之类的话,否则别人看了文档怎么知道是要做还是不要做呢?

2.避免相同的内容重复。一个内容只在文档出现一次,除了避免阅读的人读到相同的内容降低效率,更重要的是可以避免修改文档时带来的麻烦:如果文档中有内容重复,那么一改则全改,而且万一不小心漏了一两处没改呢?(感觉上避免重复的意义跟编程概念中的“函数”的意义有种异曲同工之妙)

3.把握好内容细分的粒度。文档的内容不能太笼统也不能太详细...

二:游戏角色控制脚本的编写:

这一部分算是一个不难不易的技术点,主要是实现通过用户输入操控游戏角色和游戏视角的功能。我们的角色要能够在3D的场景中的3个自由度中移动,所以游戏角色的操控方法其实也不太好设计。而且,我们需要设计一个跟随角色移动的摄像机,这个摄像机本身也有一个活动的范围。经过本人的探索和测试,目前算是初步实现了这样的控制功能,但性能还有待优化。

游戏角色的控制功能:

1.鼠标在游戏画面上移动时,改变游戏角色的朝向。

定义一个Vector3变量保存角色的朝向信息,在每一帧中,获取鼠标的偏移并对应更新其朝向信息,我这里主要通过向量的球面插值(Vector3.Slerp)实现。

2.按下WSAD时,角色移动(移动方向根据其朝向方向决定)。按下W键时向其朝向的方向移动。

每一帧根据输入获取角色移动方向的向量(和其朝向信息有关),根据这个向量更改角色的位置即可。

游戏摄像机的控制功能:

1.跟随游戏角色的移动。

摄像机有一个游戏角色的引用,表示其跟随的对象。摄像机的脚本每一帧获取其跟随游戏角色的朝向方向,确定摄像机的朝向方向(通过球面插值),再根据游戏角色的位置,确定摄像机的位置,然后让摄像机看向游戏角色即可。

2.按下右键,鼠标移动改变摄像机视角(此时不改变游戏角色本身)。

摄像机的脚本本身保存自身的偏移角度数据,当右键按下,鼠标移动改变摄像机偏移角度,由游戏角色的朝向和摄像机的偏移角度共同决定摄像机的最终朝向。

3.松开右键,摄像机归位,要求有平滑过渡。

摄像机归位只需把摄像机的偏移角度置零即可,但要实现平滑效果则不能在一帧之内马上把偏移角度置零,我的方案是让偏移角度逐帧按比例减小直至归零。

//PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : MonoBehaviour
{public float mouseSensitivity = 1.0f;private Vector3 towards;//角色朝向的方向private Vector3 up;//向上向量private Vector3 right;//规定向右向量的y方向分量为0,避免镜头“翻滚”private float speed;private enum MOVE_DIRECTION { FRONT, FRONT_LEFT, FRONT_RIGHT, LEFT, RIGHT };private MOVE_DIRECTION moveDirection;void Start(){speed = gameObject.GetComponent<Player>().speed;towards = new Vector3(0.0f, 0.0f, 1.0f);up = new Vector3(0.0f, 1.0f, 0.0f);right = new Vector3(1.0f, 0.0f, 0.0f);moveDirection = MOVE_DIRECTION.FRONT;}private void FixedUpdate(){if (!Input.GetMouseButton(1))//如果鼠标右键被按下,则不需要对角色的朝向方向作任何修改{float mouseX = -Input.GetAxis("Mouse X") * mouseSensitivity;float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;//ctrlX和ctrlY可置为1或-1,控制角色朝向的操控方式float ctrlX = -1.0f, ctrlY = -1.0f;right = Vector3.Cross(towards, up);towards = Vector3.SlerpUnclamped(towards, up, ctrlY * mouseY / 90.0f);towards.Normalize();//限制最大“俯仰角”不超过45度if (towards.y * towards.y > towards.x * towards.x + towards.z * towards.z){float sqXXZZ = Mathf.Sqrt(towards.x * towards.x + towards.z * towards.z);towards.y = towards.y > 0 ? 0.707f : -0.707f;towards.x = 0.707f * towards.x / sqXXZZ;towards.z = 0.707f * towards.z / sqXXZZ;}towards.Normalize();towards = Vector3.SlerpUnclamped(towards, right, ctrlX * mouseX / 90.0f);towards.Normalize();right = new Vector3(towards.z, 0.0f, -towards.x).normalized;up = Vector3.Cross(right, towards);up.Normalize();}//根据朝向和移动方向最终决定角色的“旋转”float moveHorizontal = Input.GetAxis("Horizontal");float moveVertical = Input.GetAxis("Vertical");Vector3 lookAt = new Vector3();if (moveHorizontal > 0.0f)if (moveVertical > 0.0f)moveDirection = MOVE_DIRECTION.FRONT_RIGHT;elsemoveDirection = MOVE_DIRECTION.RIGHT;else if (moveHorizontal < 0.0f)if (moveVertical > 0.0f)moveDirection = MOVE_DIRECTION.FRONT_LEFT;elsemoveDirection = MOVE_DIRECTION.LEFT;else if (moveVertical >= 0.0f)moveDirection = MOVE_DIRECTION.FRONT;switch (moveDirection){case MOVE_DIRECTION.FRONT:lookAt = towards;break;case MOVE_DIRECTION.FRONT_LEFT:lookAt = Vector3.Slerp(towards, -right, 0.5f);break;case MOVE_DIRECTION.LEFT:lookAt = -right;break;case MOVE_DIRECTION.FRONT_RIGHT:lookAt = Vector3.Slerp(towards, right, 0.5f);break;case MOVE_DIRECTION.RIGHT:lookAt = right;break;}transform.LookAt(gameObject.transform.position + lookAt);//限制不能向后移动if (moveVertical < 0.0f)moveVertical = 0.0f;//更新位置Vector3 move = towards * moveVertical + right * moveHorizontal;gameObject.transform.position += (move.normalized * speed);}public Vector3 GetTowards(){return towards;}
}
//CameraController.csusing System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CameraController : MonoBehaviour
{public GameObject player;public float mouseSensitivity = 3.0f;public float scrollSensitivity = 3.0f;private float distanceToPlayer;public float distanceToPlayerInit = 7.5f;public float maxDistanceInit = 10.0f;public float minDistanceInit = 5.0f;private Vector3 direction;//方向向量,玩家角色指向摄像机//向右向量和向上向量是相对“角色朝向”的private Vector3 up;private Vector3 right;//规定向右向量的y方向分量为0,避免镜头“翻滚”//摄像机本身的偏移角度private float offsetAngleHorizontal;private float offsetAngleVertical;void Start(){distanceToPlayer = distanceToPlayerInit;offsetAngleHorizontal = 0.0f;offsetAngleVertical = 0.0f;}private void FixedUpdate(){if (Input.GetMouseButton(1))//鼠标右键被按下,调整视角{float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;offsetAngleHorizontal += mouseX;offsetAngleVertical += mouseY;}else//视角回归原位,对视角进行平滑过渡{if (Mathf.Abs(offsetAngleHorizontal) < 1e-6)offsetAngleHorizontal = 0.0f;elseoffsetAngleHorizontal *= 0.6f;if (Mathf.Abs(offsetAngleVertical) < 1e-6)offsetAngleVertical = 0.0f;elseoffsetAngleVertical *= 0.6f;}//计算摄像机朝向方向Vector3 playerTowards = player.gameObject.GetComponent<PlayerController>().GetTowards();right = new Vector3(playerTowards.z, 0.0f, -playerTowards.x).normalized;up = Vector3.Cross(playerTowards, right).normalized;direction = Vector3.SlerpUnclamped(playerTowards, right, offsetAngleHorizontal / 90.0f);direction = Vector3.SlerpUnclamped(direction, up, 1.6f + offsetAngleVertical / 90.0f).normalized;//摄像机距离角色的距离根据角色大小来变化float playerSize = player.GetComponent<Player>().GetPlayerSize().x;distanceToPlayer = playerSize * distanceToPlayerInit;float scroll = Input.GetAxis("Mouse ScrollWheel");distanceToPlayerInit -= scroll * scrollSensitivity * playerSize;//滚轮往“上”滚时,摄像机距离拉近distanceToPlayerInit = Mathf.Clamp(distanceToPlayerInit, minDistanceInit, maxDistanceInit);}//摄像机位置的更新一般要放在其跟随物体的更新之后void LateUpdate(){transform.position = player.gameObject.transform.position + direction * distanceToPlayer;transform.LookAt(player.transform);}
}

3d游戏项目实训一周总结相关推荐

  1. 3d游戏项目实训一周总结 2

    在本周的项目实训中,我的主要工作是完善对玩家角色的控制脚本,以及初步实现游戏中的AI功能.该AI功能包括游戏玩家角色的AI功能和游戏非玩家角色的AI功能. 在玩家角色的控制方面,我们增加了新的需求,要 ...

  2. 项目实训第一周2-学习系统的使用

    项目实训第一周2-学习系统的使用 1.代码生成器的使用 2.sql生成器的使用 3.其他组件的使用 1.代码生成器的使用 如图,是代码生成器的基本构造 可以自行定义选择你要生成代码的注释信息,表信息, ...

  3. 项目实训第一周(车道线检测)

    项目实训我主要负责计算机视觉方面,识别出车道线并据此导航.相关内容也更新在我的个人博客上个人网站 相关介绍 车道线检测如果用传统方法,识别速度较慢,效果不够好,容易受到多种因素的干扰,因此我们打算开发 ...

  4. 变电站3D仿真实训系统的特色及优势

    随着国内的电网规模逐年扩大,传统电网的缺陷越发明显,,日常虚拟巡逻检查的内容及频次比较多,消耗的人力也比较高,且还会存在盲区等问题.基于虚拟现实技术,3d建模等技术的变电站vr全景虚拟仿真实训系统,是 ...

  5. 暑期实训第二周周一周二总结

    一.总结 时间飞逝,暑期项目实训转眼来到了第二周.在完成了第一周的需求分析.系统设计.技术学习等阶段后,我们项目组终于进入了编码开发的阶段. 经过分工,我的工作是小程序后端的开发.周一周二两天完成了三 ...

  6. MySQL 实训一周,我一天搞完

    数据库建表插入语句 # 项目一创建库.表.准备数据 # 创建库 create database stumis charset=utf8; show databases; use stumis; #创建 ...

  7. 项目实训第一周工作(3)

    项目实训题目:饮食健康管理系统设计与实现 我的工作:数据清洗 具体工作事项:数据清洗:错误数据处理:图片大小归一化:图片存放位置归并:与数据库同学沟通:不对应(冗余或缺失)图片的删除与处理等. 本博客 ...

  8. (个人)AR电子书系统创新实训第一周(1)

    -我们小组五人在选定了实训的课题之后就开始仔细讨论整个项目的设计.在产品展示上我们分为两部分,一块是纸媒,一块是APP. - 纸媒的展示效果就是,在我们做的宣传册上扫图片就可以获得二维甚至三维的视觉体 ...

  9. (个人)VR实时交互的太极拳学习系统创新实训第一周(2)

    这周主要进行了人物模型和示例动画的制作和利用动捕进行舞蹈学习的论文的学习. 使用Neuron和Motion Builder进行了太极拳动作的采集和处理.以下是我使用Motion Buileder导出模 ...

  10. 项目实训第二周(车道线检测)

    本周工作 上一周对于LaneNet这一模型进行了了相关复现,训练以及测试,因为LaneNet算是比较经典的一个车道线检测模型,距今时间较长,而且其问题我也在上一周的博客中指明,这一周我继续对于近今年国 ...

最新文章

  1. (转载)IP、主机名和域名
  2. SpringMvc自动代理
  3. 凸透镜成像动画可拖动_经典四图八问!这道中考物理题,彻底解决凸透镜成像规律!...
  4. Java入门算法(树篇)
  5. php 数组 定义 遍历,php针对数组的定义、遍历及删除
  6. linux改分区名字,修改分区的label
  7. angular HttpClient getbyid 方法获取数据
  8. okvis odometry的安装与运行
  9. java oom分析_JAVA各种OOM代码示例与解决方法
  10. PrintWindow截取隐藏窗口
  11. littleVGL开发(8):消息弹窗控件(lv_mbox)
  12. 为XCode 6 添加新建类模板
  13. 论文阅读笔记:From Zero-Shot Learning to Cold-Start Recommendation
  14. Greenplum数据库配置管理-参数配置管理和常用参数优化建议
  15. 第十四周 项目1 - 验证算法
  16. 关于Android短信拦截
  17. Html与CSS快速入门01-基础概念
  18. 20 张图表达程序员的心酸
  19. 当clipper遇到重复裁剪框
  20. python11.23

热门文章

  1. 201871010133-赵永军《面向对象程序设计(java)》第二周学习总结
  2. 纳德拉:Windows Phone市场份额虽低 但它“完整了体验”
  3. [计算机毕业设计]数字水印算法
  4. 程序员如何保护自己的颈椎?颈椎操
  5. 由 12306.cn 谈谈高并发+高负载网站性能技术
  6. Hi3519V101运行MPP业务
  7. WiFi万能钥匙+小米手机拿到coffee店WiFi密码
  8. 微信php带菜单事件,phpcms微信插件自定义菜单绑定栏目获取消息的实现与应用
  9. linux默认的超级用户是,Linux操作系统默认的超级用户是()
  10. NO.013-2018.02.18《鹊桥仙·纤云弄巧》宋代:秦观