目录
  
  《ATD》 游戏简介
  
  《ATD》 整体结构
  
  《ATD》 游戏机制
  
  Buff机制
  
  Skill机制
  
  结语
  
  《ATD》 游戏简介
  
  游戏类型:塔防+RPG的3D游戏
  
  游戏要素:3D 塔防 英雄 建筑树 搭配
  
  主体玩法:游戏里将会有一波波怪物进攻基地。玩家可以建造塔来防御敌人,同时也可以控制单独的个体英雄角色来攻击敌人。
  
  游戏模式:
  
  第三人称视角的RPG模式
  
  上帝视角的建造模式
  
  控制方式:在游戏中使用Tab按键,切换这两种操作模式:
  
  RPG模式下:WASD控制移动,Space跳跃,鼠标左键普通攻击。
  
  建造模式下:鼠标左键建造,E销毁已建造的建筑。
  
  数字键1,2,3,4,5,6控制物品栏,对应英雄技能或者建筑安放。
  
  胜利条件:消灭所有敌人 或者 坚持到时间结束
  
  失败条件:基地生命值为0 或者 英雄死亡
  
  《ATD》 整体结构
  
  一般来说,整个Unity游戏项目整体结构,我比较偏向分为如下5部分:
  
  场景对象: 不会产生互动的可视物体对象,例如地型/建筑/灯光。
  
  游戏对象: 参与互动的游戏对象,例如英雄/怪物/塔。
  
  游戏逻辑: 负责控制游戏的逻辑,其逻辑对象一般是单例的。
  
  非游戏性对象: 负责增强游戏效果,但不是直接的游戏逻辑,例如UI/HUD/特效/声音。
  
  工具: 负责辅助编码,例如日志工具,调试工具。
  
  在《ATD》游戏项目里,我是这样设置游戏对象目录的:
  
  注:“个体”在《ATD》里的术语表示游戏对象单位。
  
  《ATD》 游戏机制
  
  通过分析《ATD》策划案,确立了两种基本游戏机制:
  
  Buff机制
  
  Skill机制(技能机制)
  
  Buff机制
  
  和策划商量后,策划制作了下面一张含所有Buff属性的Excel表:
  
  由于策划还没想好Buff名字,直接套用装备或者技能名字来命名Buff。
  
  首先,使用了一个数据类型BuffData,用于完全映射Buff在表格的所有属性:
  
  public class BuffData
  
  {
  
  public int ID;
  
  public string Name;
  
  public int HpChange; //血量变化
  
  public double HpChange_p; //血量百分比变化
  
  public int AttackChange; //攻击力变化
  
  public double AttackChange_p; //攻击力百分比变化
  
  public double AttSpeedChange_p; //攻击速度百分比变化
  
  public double SpeedChange_p; //速度百分比变化
  
  public int HpReturnChange; //血量恢复数值
  
  public double HpReturnChange_p; //血量百分比恢复数值
  
  public int AddReviveCount; //增加复活次数
  
  public bool isDecelerate; //减速
  
  public bool isVertigo; //眩晕
  
  public bool isParalysis; //麻痹
  
  public bool isSleep; //睡眠
  
  public bool isBound; //束缚
  
  public bool isBurn; //点燃
  
  public bool isCharm; //魅惑
  
  public bool isIncreaseAttSpeed; //攻速提高
  
  public bool isPoisoning; //中毒
  
  public bool isImmuneControl; //免疫控制
  
  public bool isRevenge; //复仇
  
  public bool isTaunt; //嘲讽
  
  public bool isIncreaseHpReturn; //回血速度提高
  
  public bool isIncreaseAttack; //攻击力提高
  
  }
  
  然后我们就可以用一个List
  
  //全局单例类
  
  public class BuffDataBase : MonoBehaviour
  
  {
  
  //读取excel插件生成的json文件
  
  public TextAsset BuffDataJson;
  
  //存储BuffData的列表
  
  private List<BuffData> buffDatas;
  
  //全局单例实现
  
  //...
  
  //根据ID获取相应的BuffData对象
  
  public BuffData GetBuffData(int ID){
  
  //...
  
  }
  
  }
  
  为了表示游戏对象动态得到/失去一个Buff而从BuffDataBase找到对应并拷贝一份BuffData对象/释放掉一份BuffData对象显然是不明智的。(BuffData所占空间大,开销大)
  
  正确的做法应该是使用索引/引用的方式,例如某个游戏对象持有3号索引,则表示它当前受一个3号Buff影响。
  
  为了引入Buff的时间有效性,则进一步封装索引,于是编写了下面一个Buff类:
  
  public class Buff
  
  {
  
  public int ID; //BuffData的ID(索引)
  
  public double time; //持续时间
  
  public int repeatCount; //重复次数
  
  public bool isTrigger; //是否触发类型
  
  }
  
  因为每个Buff的时间有效性都有所不同:有些Buff是一次性触发Buff;也有一些是持续性Buff,持续N秒;还有一些是被动buff,永久生效。
  
  所以我这里就总结了个规则,Buff主要分为两种类型:
  
  持续型(Non-Trigger):开始对属性造成生效影响一次,有效时间结束时造成失效影响一次。例如一段时间内增加攻速Buff
  
  非持续型(Trigger):有效时间内,每一帧对属性造成生效影响一次。例如一次性伤害Buff,光环Buff。
  
  然后Buff的有效时间取决于2个属性:
  
  持续时间(time):每帧持续时间减少DeltaTime
  
  触发次数(repeatCount):每帧触发次数减一
  
  当一个Buff对象,持续时间 <= 0 并且 触发次数为0,则应视为失效。特殊地,触发次数为-1时,表示无限时间。
  
  这样Buff/BuffData/BuffDataBase基本构造就这样了:
  
  整个游戏同种类Buff只用存储一份BuffData;但是可以有很多个对象持有索引/引用,指向这个BuffData
  
  游戏对象持有Buff对象,通过BuffDataBase访问BuffData的数据,然后利用这些数据对游戏对象属性造成影响
  
  看到这里,可能会有人想到前面有个问题:对于任意一种Buff,它往往有很多属性是false或者0,使用这种完全映射会不会很影响空间占用或者效率。
  
  首先,空间占用绝对不用担心,因为前面BuffDataBase机制保证同种Buff只有唯一BuffData副本,其所有BuffData总共占用量不过几kb而已。
  
  其次,至于效率,例如说某个Buff对某个游戏对象造成影响,因为是完全映射,所以需要对该游戏对象每个属性都要进行更新,其实这也并不是太糟糕。而且只要游戏对象有比较好的Buff计算方式,可以让一个Buff对象的整个有效周期只对对象造成两次影响计算(生效影响,失效影响),避免每帧出现影响多余的计算,这样就很不错了。
  
  Skill机制
  
  可以说技能是我比较头疼的部分。
  
  看到那千奇百怪的Skill需求时,然后才总结出大概这几个分类:
  
  主动Buff技能 = 主动释放,生成一个Buff
  
  被动Buff技能 = 初始化时,生成一个Buff
  
  召唤技能 = 生成一个游戏对象
  
  指向性技能 = 主动释放,对锁定的目标生成一个Buff
  
  最后我决定使用继承接口的方式来实现Skill:
  
  技能接口类:
  
  public interface ISkill
  
  {
  
  // 技能初始化接口
  
  void InitSkill(Individual user);
  
  // 使用技能接口
  
  void ReleaseSkill(Individual user);
  
  /// 技能每帧更新
  
  void UpdateSkill(Individual user);
  
  /// 技能是否冷却
  
  bool IsColdTimeEnd();
  
  // 技能冷却百分比
  
  float GetColdTimePercent(www.baikayule.cn);
  
  }
  
  需要注意的一点是,技能并不是主动释放时调用一个自定义的技能函数即可完事:
  
  例如持续性的范围技能,需要每帧调用散发Buff的函数。
  
  所以一个ISkill对象 该有这3种重要的接口方法:初始化/主动释放/每帧更新
  
  下面是其中一个派生类的具体实现:
  
  由于进度未完,目前只有两个派生类:Buff技能类和召唤技能类。
  
  Buff技能类暂时包含了ActiveBuff技能类和PassiveBuff技能类的功能。
  
  // 示例:Buff技能类
  
  public class BuffSkill : ISkill
  
  {
  
  public int buffID; //目的Buff
  
  public bool isAura = true; //光环
  
  public bool releasable = true; //是否主动释放
  
  public float range = 0.01f; //范围
  
  private float coldTime = 5.0f; //冷却时间
  
  private float timer =www.baikayul.com 5.0f; //冷却计时
  
  public BuffSkill(int buffID,bool releasable = true,bool isAura = true, float range = 0.01f)
  
  {
  
  this.buffID = buffID;
  
  this.isAura = isAura;
  
  this.range = range;
  
  this.releasable = releasable;
  
  }
  
  public void InitSkill(Individual master)
  
  {
  
  if (!releasable && !isAura)
  
  {
  
  var individual =www.huashengyLe.com master.GetComponent<Individual>();
  
  master.GetComponent<MessageSystem>(www.qifeimn.com).SendMessage(2, individual.ID,buffID);
  
  }
  
  }
  
  public void ReleaseSkill(Individual master)
  
  {
  
  if (releasable && IsColdTimeEnd())
  
  {
  
  timer = 0.0f;
  
  Factory.TraversalIndividualsInCircle(
  
  (individual) => { master.GetComponent<MessageSystem>().SendMessage(2, individual.ID, buffID); }
  
  , master.transform.position, range);
  
  }
  
  }
  
  public void UpdateSkill(Individual master)
  
  {
  
  //增加计时
  
  timer =Mathf.Min(www.feishenbo.cn timer+Time.deltaTime, coldTime+0.1f);
  
  if (!releasable && isAura)
  
  {
  
  Factory.TraversalIndividualsInCircle(
  
  (individual) => { master.GetComponent<MessageSystem>().SendMessage(2, individual.ID, buffID); }
  
  , master.transform.position, range);
  
  }
  
  }
  
  public float GetColdTimePercent(www.chuangyyuLe.com)
  
  {
  
  if (!releasable) return 1.0f;
  
  return timer / coldTime;
  
  }
  
  public bool IsColdTimeEnd(www.xingyunylpt.com)
  
  {
  
  return timer > coldTime;
  
  }
  
  }
  
  派生类的构造函数很重要,这样即使硬编码了4个技能派生类,通过不同的数据参数传入,也能产生更多不同的技能对象。
  
  最后还应该再写一个SkillDataBase全局单例类,它负责读取策划写的技能配置文件,来初始化出来一些Skill对象,以供游戏对象使用。
  
  不过项目代码还没写完,因此目前是直接在SkillDataBase的初始化函数直接硬编码3个技能。
  
  //TODO
  
  //目前硬编码给玩家赋予3个技能
  
  HeroSkills.Add(new BuffSkill(6,www.qunfLtie.com true, true, 5.0f)); //主动技能:嘲讽Buff
  
  HeroSkills.Add(new BuffSkill(0, false, false)); //被动技能:回血buff
  
  HeroSkills.Add(new BuffSkill(14, true, false)); //主动技能:攻速戒指buff
  
  以后的话,SkillDataBase的初始化函数应该是读取某种配置文件,然后生成若干个对应的技能对象分配给游戏对象使用:
  
  结语
  
  《ATD》只是社团部门内提出的一个游戏项目,而我负责这个项目的程序架构设计,然而中途开发因为不少事,我们不得不放弃了这个项目。因此才想写点东西总结一下开发这个项目时的经验。
  
  之后还会有新博文来更新这个系列,大概涉及《ATD》的游戏对象模型,全局游戏逻辑,UI/HUD/特效/声音管理,工具等,也同时会分享一些trick。

转载于:https://www.cnblogs.com/qwangxiao/p/11191913.html

Unity《ATD》塔防RPG类3D游戏架构设计(一)相关推荐

  1. 使用Unity创建塔防游戏(Part2)

    How to Create a Tower Defense Game in Unity – Part 2 原文地址:https://www.raywenderlich.com/107529/unity ...

  2. Unity 3D 环境特效||Unity 3D 游戏场景设计实例

    Unity 3D 环境特效 一般情况下,要在游戏场景中添加雾特效和水特效较为困难,因为需要开发人员懂得着色器语言且能够熟练地使用它进行编程. Unity 3D 游戏开发引擎为了能够简单地还原真实世界中 ...

  3. Unity空间与运动(中山大学3D游戏作业3)

    Unity空间与运动(中山大学3D游戏作业3) 目录 Unity空间与运动(中山大学3D游戏作业3) 一.程序验证 物体运动的本质 三种方法实现抛物线运动 实现太阳系 二.牧师与恶魔游戏 代码仓库:h ...

  4. 3D游戏引擎设计 实时计算机图形学的应用方法 第2版 pdf 带索引书签目录

    3D游戏引擎设计  实时计算机图形学的应用方法  第2版 目录 第1章 概述 1.1 图形硬件和游戏发展史 1.2 本书版本与软件发展史 1.3 章节导读 第2章 图形系统 2.1 基础知识 2.1. ...

  5. 3D游戏建模设计需要美术基础吗,0基础可以学吗

    经常会碰到会多同学会问游戏建模设计需要美术基础吗? 游戏建模设计需要多好的美术功底? 今天我们就聊聊3D游戏建模设计之美术基础 三维软件是工具,美术基础是内力,工具只是熟能生巧的过程,美术基础决定在建 ...

  6. 如何实现游戏架构设计

    1.什么是架构设计 最近公司招人,我负责面试程序员,人事发给我很多简历,我在阅读他们的简历时,经常会看到说自己会客户端架构设计,但当问到他们什么是架构设计时,基本上是一无所知.出现这种情况原因:一是自 ...

  7. 3D引擎架构设计高级篇

    3D引擎架构设计最核心的技术包括:引擎框架设计,引擎内存管理,大场景加载以及卸载,引擎的渲染,模型骨骼插件:其他的模块还有粒子,AI,行为树,UI等等吧. 市场上对于引擎开发的需求也是比较大的,而且薪 ...

  8. 3D引擎架构设计篇-姜雪伟-专题视频课程

    3D引擎架构设计篇-169人已学习 课程介绍         本课程是针对3D引擎架构设计,涵盖引擎的基础模块,多线程基础框架,大场景加载,地形多纹理优化技术,GPU优化渲染,物理引擎,AI算法以及A ...

  9. 【游戏策划】《游戏架构设计与策划基础》学习收获要点-------任务与关卡的设计

    游戏任务情节结构: 直线型结构 玩家的任何决定基本不会对游戏最终走向产生影响. 多分支结构 玩家的决定会影响游戏走向并且可能影响到最终的结局. 注:游戏资源中的重要部分应该被主要的情节共享,一直到它们 ...

最新文章

  1. vue 实践技巧合集
  2. 高德地图只显示一个省_浅谈当下各种导航软件:高德地图、百度地图、腾讯地图...
  3. 【省选2020A卷】作业题【矩阵树】【扩域】【莫比乌斯反演】
  4. Web Hacking 101 中文版 十一、SQL 注入
  5. 计算机科学中的递归算法是把问题,递归运算法
  6. ****** 四 ******、软设笔记【数据结构】-排序、插入排序、选择排序
  7. JAVA包装类及自动封包解包示例代码
  8. 490 - Rotating Sentences
  9. imx8开发之~源码编译
  10. YOLOv3的环境配置
  11. 【2019】【论文笔记】基于混合石墨烯金属结构的可重构THz Vivaldi天线——
  12. 跑马灯的一些使用心得
  13. win7连接惠普打印机p1108
  14. RFC7515- JSON Web Signature (JWS)(JSON Web签名)
  15. 转载:解决服务器上 w3wp.exe 和 sqlserver.exe 的内存占用率居高不下的方案
  16. 【信号处理】python按原理实现BPSK、QPSK、QAM信号调制
  17. 【汇编语言实战】一元二次方程ax2+bx+c=0求解(含源码与过程截屏,可修改参数)
  18. 用dictionary写火星文翻译器
  19. Dew Lab Studio
  20. python dll注入监听_注入方式,劫持dll注入的实现

热门文章

  1. NSFC: 研究意义的写法
  2. 简单好用的书签管理器OneNav
  3. C++如何使用友元类
  4. 根据公司名称生成base64 logo(python文字转图片)
  5. go语言协程和线程区别
  6. File zilla远程连接服务器报错:服务器发回了不可路由的地址,使用服务器地址代替...
  7. 电脑端音乐播放器html5,原生js的音频播放器,兼容pc端和移动端(原创)
  8. Unity区分安卓,苹果是平板还是手机
  9. 无线局域网针对共享信道问题为什么采用CSMA/CA而不是CSMA/CD
  10. idea git工具不见了