C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想
如果你接触过《设计模式》、软件架构的编程思想,就会知道优秀的设计准则:“组合优于继承的”。
这句话很简短,但开始学习OOP的时候,真切的是—-不太好理解(以我个人当初学习为例)。
OOP的继承思想
![]()
在设计主角(Player)的时候,为了能够复用A、B、C的功能,我开始把A、B、C按照继承来写,多了一些Virutal\Override\Protected等修饰符,功能没有任何问题,就是有些别扭。如Start、Update方法,只能在A中采用模板方法处理,万一B、C、Player中直接用了Start、Update方法,会导致奇奇怪怪的问题;同时在继承的基类中,无形之间多了一些包袱,对于Player不得不使用A、B、C的函数、变量(非private的)。
整个关系变为了:
- Player is a A
- Player is a B
- Player is a C
心理上疙疙瘩瘩的,总觉得有点别扭。
OOP的组合思想
![]()
以前使用组合思想较多的是构建树、树叶模型,例如电信中的网元模型。这种思想,属于Unity 3D的核心思想–组件。在Player、A、B、C中可自由使用Start、Update函数(请不考虑执行顺序,脚本组件的先后顺序外部可调整,但是意义不大),最重要的是,关系理顺了—主角变成更积极、主动。
- Player have a A
- Player have a B
- Player have a C
- 在Unity 3D中,可复用的几乎全部为封装为了组件,eg: transform、rigibody、render、camera、***.cs脚本;为了配合方便的使用非内置的组件,可使用gameObject.AddComponent<T>()、gameObject.GetComponent<T>()来添加、获得组件(一般是自定义的脚本)。
这里我举一个实际的例子,在《Unity 3D手机游戏开发》第二版的“太空射击游戏”中,有一个需求,需要给游戏中可复用的GameObject添加自动销毁的功能(通过时间计时器,或者触发器添加),代码很简单,不到100行,要添加的GameObject有5、6个,虽然工作量不大,但总不能每个都拷贝一遍代码吧。
开始我是按照OOP继承做的,
![]()
看了几天,很不爽,后来重构为如下图:
![]()
这样使得自动销毁组件的功能发挥的更加灵活、机动,即不必拘泥于静态的继承思想来实现。
从这个重构过程中,我学到Unity 3D组件思想的闪闪发光……
附录:完整的自动销毁组件代码:
public class AutoDestoryComponent : MonoBehaviour
{
#region ICanCache
public ParticleSystem[] m_pss = null;
public int m_life = 1; //3条命
public float m_AutoDeadTime = 3;//3s自动销毁private int m_life_Base = 3; //3条命【恢复用】
private float m_AutoDeadTime_Base = 3;//3s自动销毁【恢复用】【-1:表示不自动销毁,如Enemy】void Update()
{
//需要自动销毁
if (m_AutoDeadTime_Base >= 0)
{
m_AutoDeadTime -= Time.deltaTime;if (m_AutoDeadTime <= 0)
{
InnerDead();
return;
}
}if (m_life <= 0)
{
InnerDead();
}
}/// <summary>
/// 设置自动销毁数据
/// </summary>
/// <param name="life_base">默认生命值</param>
/// <param name="autoDeadTime_base">-1不自动销毁;其他数据代表销毁时间(单位s)</param>
public void SetBasePara(int life_base = 1, float autoDeadTime_base = -1)
{
m_AutoDeadTime = m_AutoDeadTime_Base = autoDeadTime_base;
m_life = m_life_Base = life_base;
}//是否启用
public bool IsUse { get; set; }
//死后位置
public Vector3 DeathPosition
{
get
{
return new Vector3(2000, 2000, 2000);
}
}//复活
public void Init(Vector3 position, Quaternion rotation)
{
transform.gameObject.SetActive(true);
transform.position = position;
transform.rotation = rotation;
IsUse = true;
foreach (ParticleSystem item in m_pss)
{
item.Play(true);
}//有些绕
m_life = m_life_Base;
m_AutoDeadTime = m_AutoDeadTime_Base;
}private void InnerDead()
{
IsUse = false;
transform.position = DeathPosition;
foreach (ParticleSystem item in m_pss)
{
item.Stop(true);
}this.gameObject.SetActive(false);
}
#endregion
}
包括系统自带的Audio、Transform、Camera、Image、Button等等。GameObject是一个容器,没有Image的GameObject,只要新建一个空的GameObject,添加Image Component极为Image GameObject对象的。
也即是在Unity3D中,很少用GameObject.ID的概念,而是用GameObject.Tag、GameObject.name来区分不同的GameObject,且Tag、name不唯一。
结论:在Unity3D中,万事万物都是Component。
C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想的更多相关文章
- C#程序员整理的Unity 3D笔记(十):Unity3D的位移、旋转的3D数学模型
遇到一个想做的功能,但是实现不了,核心原因是因为对U3D的3D数学概念没有灵活吃透.故再次系统学习之—第三次学习3D数学. 本次,希望实现的功能很简单: 如在小地图中,希望可以动态画出Player当前 ...
- 【转载】国外程序员整理的Java资源大全
以下转载自: 推荐!国外程序员整理的Java资源大全中文版 https://github.com/akullpp/awesome-java英文版 Java 几乎是许多程序员们的入门语言,并且也是 ...
- 推荐!国外程序员整理的 PHP 资源大全
推荐!国外程序员整理的 PHP 资源大全 2014/08/02 · PHP, 工具与资源 · 8.5K 阅读 · 1 评论· php 分享到:0 与<YII框架>不得不说的故事—安全篇 R ...
- 《程序员思维修炼》读书笔记——week4
<程序员思维修炼>读书笔记——week4 PB16061441 陈昶金 这周读的是Andy Hunt的著作<程序员思维修炼>,这本书对于我这种刚刚入门的新手很友好,大多是讲一些 ...
- 国外程序员整理的Java资源大全分享
Java 几乎是许多程序员们的入门语言,并且也是世界上非常流行的编程语言.国外程序员 Andreas Kull 在其 Github 上整理了非常优秀的 Java 开发资源,推荐给大家. 译文由 Imp ...
- 【转】国外程序员整理的Java资源大全
Java几乎是许多程序员们的入门语言,并且也是世界上非常流行的编程语言.国外程序员Andreas Kull在其Github上整理了非常优秀的Java开发资源,推荐给大家.译文由ImportNew- 唐 ...
- 国外程序员整理的Java资源
好资料,慢慢学习.http://www.importnew.com/14429.html 构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理, ...
- 推荐!国外程序员整理的Java资源大全
http://www.importnew.com/14429.html 本文由 ImportNew - 唐尤华 翻译自 github akullpp.欢迎加入翻译小组.转载请见文末要求. 构建 这里搜 ...
- 国外程序员整理的Java资源大全
构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...
- 【185天】黑马程序员27天视频学习笔记【Day14-下】
叨逼叨两句 不容易,白天被叫去帮忙,不得已晚上来挑灯夜战,熬到2点,总算完成任务了. 我打算下周开始换一个更新时间,每次把deadline设置为晚上12点,都会接近或者超过这个时间,之后改成中午12点 ...
随机推荐
- PostgreSQL的 initdb 源代码分析之八
继续分析 由于 我并未进行特殊的参数设置,所以 (strlen(default_text_search_config) == 0) 成立. 故 调用 default_text_search_con ...
- 赵雅智_ContentProvider
ContentProvider介绍 ContentProvider是不同应用程序之间进行交换数据的标志API 也就是说:一个应用程序通过ContentProvider暴露自己的数据操作接口,那么无论该 ...
- C++的XML编程经验――LIBXML2库使用指南[转]
C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...
- 分享一个圆角自定义的漂亮AlertDialog
\res\drawable-hdpi\bg_title_custom_dialog.xml: <?xml version="1.0" encoding="utf-8 ...
- 解决IE下jquery ajax无法获得最新数据的问题(IE缓存)
今天修改一个bug,利用ajax查询数据,在谷歌浏览器下可以获取到最新数据,而在IE中获得是旧数据,无法获得最新的数据,经查资料,才发现时IE缓存再作怪. 发现此ajax请求用的get方式,每次请求的 ...
- 也谈OpenFlow, SDN, NFV
Copyright (2014) 郭龙仓. All Rights Reserved. OpenFlow 传统的网络环境中,仅仅有路由器/交换机之间的接口/协议是标准化的,可是在网络设备内部,数据平面和 ...
- PAT 1001
Calculate a + b and output the sum in standard format -- that is, the digits must be separated into ...
- C++的64位整数
在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647.而unsig ...
- android scrollview主要的问题
项目做多了之后,会发现其实 ScrollView嵌套ListVew或者GridView等很常用,但是你也会发现各种奇怪问题产生.根据个人经验现在列出常见问题以及代码最少最简单的解决方法. 问题一 : ...
- Windows Azure 微软公有云体验(三) IIS中文编码解决方案
Windows Azure 微软公有云已经登陆中国有一段时间了,现在是处于试用阶段,Windows Azure的使用将会给管理信息系统的开发.运行.维护带来什么样的新体验呢? Windows Azur ...