位置: 编程技术 - 正文

Unity3D游戏开发最佳实践20技巧(二)(Unity3D游戏开发标准教程)

编辑:rootadmin

推荐整理分享Unity3D游戏开发最佳实践20技巧(二)(Unity3D游戏开发标准教程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:Unity3D游戏开发标准教程,Unity3D游戏开发(第2版)pdf,unity3D游戏开发,Unity3D游戏开发毕业论文,Unity3D游戏开发pdf,Unity3D游戏开发(第2版),Unity3D游戏开发标准教程,unity3D游戏开发,内容如对您有帮助,希望把文章链接给更多的朋友!

欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d培训、学习第一品牌。

Unity3D游戏开发最佳实践20技巧(二)(Unity3D游戏开发标准教程)

【扩展和MonoBehaviourBase】、扩展一个自己的Mono Behaviour基类,然后自己的所有组件都从它派生这可以使你方便的实现一些通用函数,例如类型安全的Invoke,或者是一些更复杂的调用(例如random等等)。、为Invoke, StartCoroutine and Instantiate 定义安全调用方法定义一个委托任务(delegate Task),用它来定义需要调用的方法,而不要使用字符串属性方法名称,例如:public void Invoke(Task task, float time){ Invoke(task.Method.Name, time);}、为共享接口的组件扩展有些时候把获得组件、查找对象实现在一个组件的接口中会很方便。下面这种实现方案使用了typeof,而不是泛型版本的函数。泛型函数无法在接口上工作,而typeof可以。下面这种方法把泛型方法整洁的包装起来。

[C#] ?1//Defined in the common base class for all mono behaviourspublic I GetInterfaceComponent() where I : class{ return GetComponent(typeof(I)) as I;} public static List FindObjectsOfInterface() where I : class{ MonoBehaviour[] monoBehaviours = FindObjectsOfType(); List list = new List(); foreach(MonoBehaviour behaviour in monoBehaviours) { I component = behaviour.GetComponent(typeof(I)) as I; if(component != null) { list.Add(component); } } return list;}、使用扩展来让代码书写更便捷例如:[AppleScript] ?1public staticclassCSTransform{ public static void SetX(this Transform transform,float x) { Vector3newPosition= newVector3(x,transform.position.y,transform.position.z); transform.position=newPosition; } ...}、使用防御性的GetComponent()有些时候强制性组件依赖(通过RequiredComponent)会让人蛋疼。例如,很难在Inspector中修改组件(即使他们有同样的基类)。下面是一种替代方案,当一个必要的组件没有找到时,输出一条错误信息。[AppleScript] ?1public static T GetSafeComponent<</code>T>(this GameObject obj)whereT:MonoBehaviour{ T component=obj.GetComponent<</code>T>(); if(component==null) { Debug.LogError("Expected to find component of type " &#;typeof(T)&#;" but found none",obj); } returncomponent;}【风&#;】、避免对同一件事使用不同的处理风&#;在很多情况下,某件事并不只有一个惯用手法。在这种情况下,在项目中明确选择其中的一个来使用。下面是原因:一些做法并不能很好的一起协作。使用一个,能强制统一设计方向,并明确指出不是其他做法所指的方向;团队成员使用统一的风&#;,可能方便大家互相的理解。他使得整体结构和代码都更容易理解。这也可以减少错误;几组风&#;的例子:协程与状态机(Coroutines vs. state machines);嵌套的Prefab、互相链接的Prefab、超级Prefab(Nested prefabs vs. linked prefabs vs. God prefabs);数据分离的策略;在2D游戏的使用Sprite的方法;Prefab的结构;对象生成策略;定位对象的方法:使用类型、名称、层、引用关系;对象分组的方法:使用类型、名称、层、引用数组;找到一组对象,还是让它们自己来注册;控制执行次序(使用Unity的执行次序设置,还是使用Awake/Start/Update/LateUpdate,还是使用纯手动的方法,或者是次序无关的架构);在游戏中使用鼠标选择对象/位置/目标:SelectionManager或者是对象自主管理;在场景变换时保存数据:通过PlayerPrefs,或者是在新场景加载时不要销毁的对象;组合动画的方法:混合、叠加、分层; 【时间】、维护一个自己的Time类,可以使游戏暂停更容易实现做一个“Time.DeltaTime”和""Time.TimeSinceLevelLoad"的包装,用来实现暂停和游戏速度缩放。这使用起来略显麻烦,但是当对象运行在不同的时钟速率下的时候就方便多了(例如界面动画和游戏内动画)。 【生成对象】、不要让游戏运行时生成的对象搞乱场景层次结构在游戏运行时,为动态生成的对象设置好它们的父对象,可以让你更方便的查找。你可以使用一个空的对象,或者一个没有行为的单件来简化代码中的访问。可以给这个对象命名为“DynamicObjects”。 【类设计】、使用单件(Singleton)模式从下面这个类派生的所有类,将自动获得单件功能:[AppleScript] ?1publicclassSingleton<</code>T>:MonoBehaviourwhereT:MonoBehaviour{ protected static T instance; /** Returnstheinstanceofthis singleton. */ public static T Instance { get { if(instance==null) { instance=(T)FindObjectOfType(typeof(T)); if(instance==null) { Debug.LogError("An instance of "&#;typeof(T)&#; " is needed in the scene, but there is none."); } } returninstance; } }}单件可以作为一些管理器,例如ParticleManager或者AudioManager亦或者GUIManager。对于那些非唯一的prefab实例使用单件管理器(例如Player)。不要为了坚持这条原则把类的层次关系复杂化,宁愿在你的GameManager(或其他合适的管理器中)中持有一个它们的引用。对于外部经常使用的共有变量和方法定义为static,这样你可以这样简便的书写“GameManager.Player”,而不用写成“GameManager.Instance.player”。、在组件中不要使用public成员变量,除非它需要在inspector中调节除非需要设计师(策划or美术)去调节的变量,特别是它不能明确表明自己是做什么的变量,不要声明为public。如果在这些特殊情况下,无法避免,则可使用两个甚至四个下划线来表明不要从外部调节它,例如:public float __aVariable; 、把界面和游戏逻辑分开这一条本质上就是指的MVC模式。所有的输入控制器,只负责向相应的组件发送命令,让它们知道控制器被调用了。举一个控制器逻辑的例子,一个控制器根据玩家的状态来决定发送哪个命令。但是这样并不好(例如,如果你添加了多个控制器,那将会导致逻辑重复)。相反的,玩家对象应该根据当前状态(例如减速、惊恐)来设置当前的速度,并根据当前的面朝向来计算如何向前移动。控制器只负责做他们自己状态相关的事情,控制器不改变玩家的状态,因此控制前甚至可以根本不知道玩家的状态。另外一个例子,切换武器。正确的方法是,玩家有一个函数:“SwitchWeapon(Weapon newWeapon)”供GUI调用。GUI不应该维护所有对象的Transform和他们之间的父子关系。所有界面相关的组件,只负责维护和处理他们自己状态相关的数据。例如,显示一个地图,GUI可以根据玩家的位移计算地图的显示。但是,这是游戏状态数据,它不属于GUI。GUI只是显示游戏状态数据,这些数据应该在其他地方维护。地图数据也应该在其他地方维护(例如GameManager)。游戏玩法对象不应该关心GUI。有一个例外是处理游戏暂停(可能是通过控制Time.timeScale,其实这并不是个好主意)。游戏玩法对象应该知道游戏是否暂停。但是,这就是全部了。另外,不要把GUI组件挂到游戏玩法对象上。这么说吧,如果你把所有的GUI类都删了,游戏应该可以正确编译。你还应该达到:在不需要重写游戏逻辑的前提下,重写GUI和输入控制。、分离状态控制和簿记变量簿记变量只是为了使用起来方便或者提高查找速度,并且可以根据状态控制来覆盖。将两者分离可以简化:保存游戏状态调试游戏状态实现方法之一是为每个游戏逻辑定义一个”SaveData“类,例如:[AppleScript] ?1[Serializable]PlayerSaveData{ public float health;//publicforserialisation,notexposedininspector} Player{ //... bookkeeping variables //Don’t exposestateininspector. Stateis nottweakable. private PlayerSaveData playerSaveData;}、分离特殊的配置假设我们有两个敌人,它们使用同一个Mesh,但是有不同的属性设置(例如不同的力量、不同的速度等等)。有很多方法来分离数据。下面是我比较喜欢的一种,特别是对于对象生成或者游戏存档时,会很好用。(属性设置不是状态数据,而是配置数据,所以我们不需要存档他们。当对象加载或者生成是,属性设置会自动加载。)为每一个游戏逻辑类定义一个模板类。例如,对于敌人,我们来一个“EnemyTemplate”,所有的属性设置变量都保存在这个类中。在游戏逻辑的类中,定义一个上述模板类型的变量。制作一个敌人的Prefab,以及两个模板的Prefab:“WeakEnemyTemplate”和"StrongEnemyTemplate"。在加载或者生成对象是,把模板变量正确的复制。这种方法可能有点复杂(在一些情况下,可能不需要这样)。举个例子,最好使用泛型,我们可以这样定义我们的类:[AppleScript] ?1publicclassBaseTemplate{ ...}publicclassActorTemplate:BaseTemplate{ ...}publicclassEntity<</code>EntityTemplateType>whereEntityTemplateType:BaseTemplate{ EntityTemplateType template; ...}publicclassActor:Entity<</code>ActorTemplate>{ ...}、除了显示用的文本,不要使用字符串特别是不要用字符串作为对象或者prefab等等的ID标识。一个很遗憾的例外是动画系统,需要使用字符串来访问相应的动画。、避免使用public的数组举例说明,不要定义一个武器的数组,一个子弹的数组,一个粒子的数组,这样你的代码看起来像这样:public void SelectWeapon(int index){ currentWeaponIndex = index; Player.SwitchWeapon(weapons[currentWeapon]);} public void Shoot(){ Fire(bullets[currentWeapon]); FireParticles(particles[currentWeapon]); }这在代码中还不是什么大问题,但是在Inspector中设置他们的&#;的时候,就很难不犯错了。我们可以定义一个类,来封装这三个变量,然后使用一个它的实例数组:[Serializable]public class Weapon{ public GameObject prefab; public ParticleSystem particles; public Bullet bullet;} 这样代码看起来很整洁,但是更重要的是,在Inspector中设置时就不容易犯错了。、在结构中避免使用数组举个例子,一个玩家可以有三种攻击形式,每种使用当前的武器,并发射不同的子弹、产生不同的行为。你可以把三个子弹作为一个数组,并像下面这样组织逻辑:public void FireAttack(){ /// behaviour Fire(bullets[0]);} public void IceAttack(){ /// behaviour Fire(bullets[1]);} public void WindAttack(){ /// behaviour Fire(bullets[2]);} 使用枚举&#;可以让代码看起来更好一点:public void WindAttack(){ /// behaviour Fire(bullets[WeaponType.Wind]);} 但是这对Inspector一点也不好。最好使用单独的变量,并且起一个好的变量名,能够代表他们的内容的含义。使用下面这个类会更整洁。[Serializable]public class Bullets{ public Bullet FireBullet; public Bullet IceBullet; public Bullet WindBullet;}这里假设没有其他的Fire、Ice、Wind的数据。、把数据组织到可序列化的类中,可以让inspector更整洁有些对象有一大堆可调节的变量,这种情况下在Inspector中找到某个变量简直就成了噩梦。为了简化这种情况,可以使用一下的步骤:把这些变量分组定义到不同的类中,并让它们声明为public和serializable;在一个主要的类中,把上述类的实例定义为public成员变量;不用在Awake或者Start中初始化这些变量,因为Unity会处理好它们;你可以定义它们的默认&#;;这可以把变量分组到Inspector的分组页签中,方便管理。

[Serializable]public class MovementProperties //Not a MonoBehaviour!{ public float movementSpeed; public float turnSpeed = 1; //default provided} public class HealthProperties //Not a MonoBehaviour!{ public float maxHealth; public float regenerationRate;} public class Player : MonoBehaviour{ public MovementProperties movementProeprties; public HealthPorperties healthProeprties;}

更多精彩请点击

Unity3D如何使用脚本实现跳跃的效果 欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d

unity3d游戏开发之如何快速接入渠道SDK 欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d

Unity3D游戏开发最佳实践技巧(三) 欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d

标签: Unity3D游戏开发标准教程

本文链接地址:https://www.jiuchutong.com/biancheng/372929.html 转载请保留说明!

上一篇:Unity3D中Javascript的基本使用与介绍详解

下一篇:Unity3D如何使用脚本实现跳跃的效果(unity3ds)

  • 劳务费增值税税率13%
  • 应交税费账目处理
  • 外国公司开发古镇
  • 电信发票为什么分开开
  • 飞机发票和行程单可以一起开吗
  • 劳保费属于什么会计科目
  • 劳务公司一般纳税人开票几个点
  • 向关联企业捐赠现金500万元,假定按照税法规定
  • 建筑业预收账款如何缴税
  • 高新技术企业清算所得税率是多少
  • 货款为现金如何做记账账款凭证?
  • 购买国税金税卡年费应该怎么做账务处理?
  • 离退休人员再任职的规定
  • 个体户如何报年报
  • 生育津贴做账法会计准则
  • 稿酬所得个人所得税计算方法
  • 去年的税还能退吗
  • 金税四期什么时候正式上线
  • 预缴税款多缴了怎么办
  • 给员工购买口罩计入什么费用
  • 6%的增值税发票能抵扣13%的吗
  • 收并购股权溢价
  • 收到分红款企业所得税怎么填报
  • 活动策划费可以开专票吗
  • 子公司资不抵债
  • 电子发票字体不同
  • 报销通行费会计分录
  • 营运资金管理策略有哪些
  • 如何理解内容
  • 工会会员会费缴费证明怎么开
  • 在linux系统中拥有
  • 苹果mac系统怎么更新最新版本
  • 月末增值税计算公式
  • 计提本月应交的所得税费用
  • 哈勃太空望远镜取得的部分成果有哪些
  • php的execute
  • php数组排序方法
  • 前端部署发布项目有哪些
  • Vue Element UI 中 el-table 树形数据 tree-props 多层级使用避坑
  • 一般纳税人销售自己使用过的汽车
  • 高速费发票可以重开吗
  • 社会团体不属于财政拨款的对象
  • python 逻辑取反
  • 汽车牌照费用是在哪里开的
  • 临时聘用人员管理办法
  • 坏账核销会计处理
  • 银行代发工资必须要本行的卡吗
  • 普票红冲要不要去收回发票联?
  • 无形资产175加计扣除例题
  • 选用劳务派遣人员
  • 股东投资方式有哪些
  • 车贷管理费合理吗
  • 企业安装电子监控收费吗
  • 车船税没发票只交可以吗
  • 什么是稳岗补贴有多少
  • 可供出售金融资产有哪些
  • 固定资产怎么录入系统
  • 会计凭证发票粘贴
  • linux实现mysql数据库每天自动备份定时备份
  • win8.1语言包下载
  • splash.exe - splash是什么进程 有什么作用
  • rpm包安装位置
  • xp 更新
  • linux怎么使用ssh命令
  • android项目总结
  • 批处理怎么用
  • 关于超链接下列说法中错误的是
  • jquery判断控件是否存在
  • Linux查看所有用户和密码
  • 2024年全年计划
  • 如何用jquery
  • JavaScript+html5 canvas实现图片破碎重组动画特效
  • jquery使用css
  • js判断时间差
  • 每天一篇日记100字
  • 电子税务局登陆密码在哪里修改
  • 办理税控盘的流程
  • 姓名章加不加印字
  • 成都那些地方属于正东方向
  • 零税率,免税不免增值税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设