《U3D高级编程》- UGUI事件模块剖析
UGUI事件模块剖析UGUI事件系统源码剖析图4-1为UGUI内核源码的文件夹结构图。它把UGUI系统分为输入事件、动画、核心渲染三部分。其中动画部分相对比较简单,采用tween补间动画的形式对颜色、位置、大小进行了渐进的操作。tween的原理是启动一个协程,在协程里对元素的属性进行渐进式修改,除了修改属性数值,tween还设置了多种曲线以供选择,比如内翻曲线、外翻曲线等,一个数值从起点到终点的过程可以通过曲线来控制。例如,数字从0到100的变化可在3秒内完成,如果是线性,则在第2秒时的数值应该如下: (100-0) x (2f/3f) =200f/3f=66.666如果使用内翻曲线就不是这个结果了,但它们最终都会到达100,只是过程有点“曲折”,曲线也体现了动画的“有趣“。
下面重点剖析输入事件和核心渲染这两部分
输入事件源码由图4-2可知,UGUI系统将输入事件模块分为四部分,即事件数据模块、输入事件捕获模块、射线碰撞检测模块、事件逻辑处理及回调模块。
下面将分析每一部分的核心源码。
事件数据模块事件数据模块对整个输入事件系统的作用就是,它主要定义并目存储了事件发生时的位置、 ...
《U3D高级编程》- UGUI核心源码剖析
UGUI核心源码剖析UGUI核心源码结构从图4-3可以看出,以文件夹为单位拆分模块,有Culling (裁剪) 、Layout(布局) 、MaterialModifiers (材质球修改器) 、SpecializedCollections(收集)、Utility (实用工具) 、VertexModifiers (页点修改器)。下面对每个模块进行分析。
Culling模块Culling是对模型进行裁剪的工具类,大都用在Mask (遮罩) 上,只有Mask才有裁剪的需求。
如图4-4所示,文件夹中包含四个文件,其中一个是静态类,一个是接口类。
Clipping类中有两个函数比较重要,常被用在Mask的裁剪上,其源代码如下:
123456789101112131415161718192021222324252627282930313233343536373839/// <summary>/// Find the Rect to use for clipping./// Given the input RectMask2ds find a rectangle that is the ...
《U3D高级编程》- Unity3D中C#的底层原理
Unity3D中C#的底层原理Unity底层在运行C#程序时有两种机制,一种是Mono,另一种是IL2CPP。这两种机制到底有什么区别?又是如何运作的呢? 下面来简单介绍一下。
我们知道,在Unity中使用C#语言的一个重要好处就是编译快且开发效率高。但是.NET虽好却只能运行在Windows上(不过现在NetCore可以实现多平台了,只是还不够完善),主要是因为微软没有考虑跨平台而且没有将其开源。后来微软公司向ECMA申请将C#作为一种标准。C#在2003年成为一个ISO标准(ISO/IEC 23270) 。这意味着只要是遵守CLI(Common Language Infrastructure)的第三方就可以将任何一种语言实现到.NET平台上。Mono就是在这种环境下诞生的,Mono的目标就是达成跨平台.NET 4.0的完整功能支持。
与微软的NET Framework (共通语言运行平台)不同,Mono项目不仅可以运行于Windows系统上,还可以运行于Linux、FreeBSD、Unix、OS X和Solaris上,甚至是一些游戏平台上,例如:Playstation 3、Wii或 ...
《U3D高级编程》- 数据表的种类
数据表的种类数据表相当于一个外部的数据库,数据库中存储着与游戏人物相关的数据,只不过这个数据库里的数据是不能更改的。在游戏项目中有不少数据表,因为数据决定了游戏的整个进程,所以怎么用数据表配置数据、配置数据时是否方便成为开发的关键。
最原始的数据方式——代码数据文本数据文本读取规则有很多标准形式,包括JSON、XML、CSV等,这些都是常用的文本读取规则,大多数情况下,使用文本读取字符串形式的数据,然后按规则转化成相应的数据和数据组是极佳的选择。它的优点是,肉眼能很直观地看到数据,也更容易查找问题,还能立即直接对文本进行修改,无须其他工具。
比特流数据比特流数据是一种相对机器来说稍微直接点的数据表现形式。我们是将数据以byte的形式存放在文件里,程序通过读取二进制文件里的数据,按一定的规则将其转化为所需要的数据。相比文本形式的数据文件,比特流数据文件的特点是,占用的空间更小,解析速度更快,但其缺点也存在,通用性较差,数据格式改变比较困难,无法直观看到文件中的内容,也无法做到不依靠程序进行任意修改。
相比文本数据文件,比特流形式的数据文件为什么会更小呢? 比特流在存储数字时会使用二进制格 ...
《U3D高级编程》- 用户界面系统的比较
用户界面系统的比较UGUI系统的原理及其组件使用UGUI系统的运行原理UGUI是在3D网格下建立起来的UI系统,它的每个可显示的元素都是通过3D模型网格的形式构建起来的。当UI系统被实例化时,UGUI系统首先要做的就是构建网格。
也就是说,Unity3D在制作一个图元,或者一个按钮,或者一个背景时,都会先构建一个方形网格,再将图片放入网格中。可以理解为构建了一个3D模型,用一个网格绑定一个材质球,材质球里存放要显示的图片。
这里有一个问题,如果每个元素都生成一个模型且绑定一个材质球存入一张图片,那么界面上成千上万个元素就会拥有成千上万个材质球,以及成千上万张图。这样使得引擎在渲染时就需要读取成千上万张图以及成千上万个材质球,如果GPU对每个材质球和网格都进行渲染,将会导致GPU的负担重大,我们可以理解为一个材质球拥有一个drawcall会导致drawcall过高 (drawcall的原理将在后面章节介绍)。
UGUI系统对这种情况进行了优化,它将一部分相同类型的图片集合起来合成一张图,然后将拥有相同图片、相同着色器的材质球指向同一个材质球,并且把分散开的模型网格合并起来,这样就生成几个 ...
《U3D高级编程》- Unity3D中C#的底层原理1
Unity3D中C#的底层原理(一)Unity底层在运行C#程序时有两种机制,一种是Mono,另一种是IL2CPP。这两种机制到底有什么区别?又是如何运作的呢? 下面来简单介绍一下。
我们知道,在Unity中使用C#语言的一个重要好处就是编译快且开发效率高。但是.NET虽好却只能运行在Windows上(不过现在NetCore可以实现多平台了,只是还不够完善),主要是因为微软没有考虑跨平台而且没有将其开源。后来微软公司向ECMA申请将C#作为一种标准。C#在2003年成为一个ISO标准(ISO/IEC 23270) 。这意味着只要是遵守CLI(Common Language Infrastructure)的第三方就可以将任何一种语言实现到.NET平台上。Mono就是在这种环境下诞生的,Mono的目标就是达成跨平台.NET 4.0的完整功能支持。
与微软的NET Framework (共通语言运行平台)不同,Mono项目不仅可以运行于Windows系统上,还可以运行于Linux、FreeBSD、Unix、OS X和Solaris上,甚至是一些游戏平台上,例如:Playstation 3、W ...
《U3D高级编程》- 软件架构
软件架构架构的意义怎样才算是优秀的软件架构?
1.承载力
2.可拓展性
3.易用性
4.可伸缩性
5.容错性以及错误的感知力软件架构的思维方式
1.分层思维
分层是我们应对和管理复杂性的基本思维武器。面对一个复杂的系统,我们一开始总是无从下手,就好比一下子在我们面前摆了很多的问题,杂乱无章。这很大程度上会导致我们慌张、焦急、惶恐。分层思维,能很好地帮助我们抽象一个复杂系统的架构层次,从而清晰地描述有多少层面的事务需要我们解决,以及解决层级的先后次序。构建一套复杂系统时,我们把整个系统划分成若干个层次,每一层专注解决某个领域的问题,并向上提供服务。这样的抽象做法,让复杂的事务变得更加清晰、有序。有些层次并不一定是横向的,也可以是纵向的,纵向的层次贯穿其他横向层次,称为共享层,如图所示。
2.分治思维
分而治之也是应对和管理复杂性的一般性方法,下图展示的是一个分治的思维流程。对于一个无法一次解决的大问题,我们先把大问题分解成若干个子问题,如果子问题还无法解决,则继续分解成子子问题,直到可以直接解决为止,这就是分解(divide) 的过程;然后将子子问题的解组合成子问题的解,再将子问 ...
《U3D高级编程》- Unity3D中C#的底层原理2
Unity3D中C#的底层原理(二)浮点数的精度问题很多人在项目中会用double类型替代float类型来提高精度,他们错误地认为double类型可以解决精度问题。我正好相反,在编程中极少使用double类型,由于浮点数在大多数项目中并没有使用到特别高的精度,所以float类型基本都够用。其实,即使使用double类型也同样有精度问题,因为浮点数本身就很容易导致不一致的问题。
我们不妨比较float与double,来看看它们有什么不同。float和double所占用的位数不同会导致精度不同,float是32位占用4字节,而double是64位占用8字节,因此,它们在计算时也会引起计算效率的不同。
在实际工作中,我们很多时候想通过使用double替换float来解决精度问题,最后基本都会以失败告终。因此,我们要认清精度这个问题的根源,才能真正解决问题。我们先来看浮点数在内存中到底是如何存储的。
计算机只能识别0和1,不管是整数还是小数,在计算机中都以二进制方式存储在内存中。那么浮点数是以怎样的方式来存储的呢? 根据IEEE 754标准,任意一个二进制浮点数F均可表示为:
F=(-1^s) ...
《大话设计模式》
Chapter3 单一职责原则
单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因。Chapter4 开放-封闭原则
开放-封闭原则:软件实体(类、模块、函数等)应该可以扩展,但是不可修改。Chapter5 依赖倒转原则
依赖倒转原则:
1.高层模块不应该依赖底层模块。两个都应该依赖抽象。2.抽象不应该依赖细节,细节应该依赖于抽象。
里氏替换原则
里氏替换原则(LSP):子类型必须能够替换掉他们的父类型。Chapter6 装饰模式
装饰模式(Decorater):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。
Comp ...
Lua程序设计(语言特性18-23)
Chapter18 迭代器和泛型for18.1 迭代器和闭包迭代器(iterator)是一种可以让我们遍历一个集合中所有元素的代码结构。
所有的迭代器都需要在连续的调用之间保存一些状态,这样才能知道当前迭代所处的位置及如何从当前位置步进到下一位置。对于函数io.read而言,C语言会将状态保存在流的结构体中。对于我们自己的迭代器而言,闭包则为保存状态提供了一种良好的机制。请注意,一个闭包就是一个可以访问其自身的环境中一个或多个局部变量的函数。这些变量将连续调用过程中的值并将其保存在闭包中,从而使得闭包能够记住迭代所处的位置。当然,要创建一个新的闭包,我们还必须创建非局部变量。因此,一个闭包结构通常涉及两个函数:闭包本身和一个用于创建该闭包及其封装变量的工厂(factory)。
作为示例,让我们来为列表编写一个简单的迭代器。与ipairs不同的是,该迭代器并不是返回每个元素的索引而是返回元素的值:
123456789function values(t) local i = 0; return function () i = i + 1; retur ...