答:ios
装箱操做:程序员
值类型隐式转换为object类型或由此值类型实现的任何接口类型的过程。面试
1.在堆中开辟内存空间。算法
2.将值类型的数据复制到堆中。数据库
3.返回堆中新分配对象的地址。express
拆箱操做:编程
object类型显示转换为值类型或从接口类型到实现该接口值类型的过程。设计模式
1.判断给定类型是不是装箱时的类型。数组
2.返回已装箱实例中属于原值类型字段的地址。缓存
答:attribute翻译成特性,用来标识类,方法 。
property翻译为属性,性质用于存取类的字段 。
markup翻译成标记。
tag翻译成标签。
答:程序集的一个重要特性是它们包含的元数据描述了对应代码中定义的类型和方法。
答:ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所作的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
out 关键字会致使参数经过引用来传递。这与 ref 关键字相似,不一样之处在于 ref 要求变量必须在传递以前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。
答:1) new 运算符 :用于建立对象和调用构造函数。
2) new 修饰符 :用于向基类成员隐藏继承成员。
3) new 约束 :用于在泛型声明中约束可能用做类型参数的参数的类型。
答:string str = "" 初始化对象分配空间。
string str = null 表示一个空引用,没有占用空间。//实际状况是,string为null时依然为"",但该题常考。
答:序列化是将对象状态转换为可保持或传输的格式的过程。 与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,能够轻松地存储和传输数据。
答:
1) sealed 修饰符能够应用于类、实例方法和属性。密封类不能被继承。密封方法会重写基类中的方法,但其自己不能在任何派生类中进一步重写。当应用于方法或属性时,sealed 修饰符必须始终与 override一块儿使用。
2) 将密封类用做基类或将 abstract 修饰符与密封类一块儿使用是错误的。
3) 结构是隐式密封的;所以它们不能被继承。
答:
相同点:
1) 语法相似。
不一样点:
1) class是引用类型,继承自System.Object类; struct是值类型,继承自System.ValueType类,所以不具多态性。可是注意,System.ValueType是个引用类型。
2) 从职能观点来看,class表现为行为; 而struct经常使用于存储数据。
3) class支持继承,能够继承自类和接口; 而struct没有继承性,struct不能从class继承,也不能做为class的基类,但struct支持接口继承。
4) 实例化时,class要使用new关键字; 而struct能够不使用new关键字,struct在声明时就进行了初始化过程,全部的成员变量均默认为0或null。
答:1) 堆栈的空间有限,对于大量的逻辑的对象,建立类要比建立结构好一些。
2) 结构表示如点、矩形和颜色这样的轻量对象。例如,若是声明一个含有 1000 个点对象的数组,则将为引用每一个对象分配附加的内存。在此状况下,结构的成本较低。
3) 在表现抽象和多级别的对象层次时,类是最好的选择。
4) 大多数状况下该类型只是一些数据时,结构时最佳的选择。
答:
抽象类:
1) 抽象方法只做声明,而不包含实现,能够当作是没有实现体的虚方法。
2) 抽象类不能被实例化。
3) 抽象类能够但不是必须有抽象属性和抽象方法,可是一旦有了抽象方法,就必定要把这个类声明为抽象类。
4) 具体派生类必须覆盖基类的抽象方法。
5) 抽象派生类能够覆盖基类的抽象方法,也能够不覆盖。若是不覆盖,则其具体派生类必须覆盖它们。
接口:
1) 接口不能被实例化。
2) 接口只能包含方法声明。
3) 接口的成员包括方法、属性、索引器、事件。
4) 接口中不能包含常量、字段(域)、构造函数、析构函数、静态成员。
5) 接口中的全部成员默认为public,所以接口中不能有private修饰符。
6) 派生类必须实现接口的全部成员。
7) 一个类能够直接实现多个接口,接口之间用逗号隔开。
8) 一个接口能够有多个父接口,实现该接口的类必须实现全部父接口中的全部成员。
抽象类和接口的异同:
相同点:
1) 均可以被继承。
2) 都不能被实例化。
3) 均可以包含方法声明。
4) 派生类必须实现未实现的方法。
区 别:
1) 抽象基类能够定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
2) 抽象类是一个不完整的类,须要进一步细化,而接口是一个行为规范。微软的自定义接口老是后带able字段,证实其是表述一类“我能作。。。”。
3) 接口能够被多重实现,抽象类只能被单一继承。
4) 抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中。
5) 抽象类是从一系列相关对象中抽象出来的概念, 所以反映的是事物的内部共性;接口是为了知足外部调用而定义的一个功能约定, 所以反映的是事物的外部特性。
6) 接口基本上不具有继承的任何具体特色,它仅仅承诺了可以调用的方法。
7) 接口能够用于支持回调,而继承并不具有这个特色。
8) 抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,固然您也能够声明为虚的。
9) 若是抽象类实现接口,则能够把接口中方法映射到抽象类中做为抽象方法而没必要实现,而在抽象类的子类中实现接口中方法。
答:1) 操做系统和运行库环境一般会在应用程序间提供某种形式的隔离。
2) 应用程序域为安全性、可靠性、版本控制以及卸载程序集提供了隔离边界。
3) 应用程序域能够理解为一种轻量级进程。起到安全的做用。占用资源小。
答:为全部变量指定数据类型称为“强类型”。C#是强类型语言。
答:使用基于公共语言运行库的语言编译器开发的代码称为托管代码;托管代码具备许多优势,例如:跨语言集成、跨语言异常处理、加强的安全性、版本控制和部署支持、简化的组件交互模型、调试和分析服务等。
答:CTS:通用系统类型 Common Type System。全部.NET语言共享这一类型系统,实现它们之间无缝的互操做。该方案还提供了语言之间的继承性。
答:CLR:公共语言运行库 Common Language Runtime。是一个运行时环境,它负责资源管理(内存分配和垃圾收集),并保证应用和底层操做系统之间必要的分离。
答:CLS:公共语言规范 Common Language Specification。能够保证C#组件与其余语言组件间的互操做性。
答:1) 委托是一种引用方法的类型。
2) 委托相似于 C++ 函数指针,但它是类型安全的。
3) 委托容许将方法做为参数进行传递。
4) 委托可用于定义回调方法。
答:1) Active Directory存储了有关网络对象的信息,而且让管理员和用户可以轻松地查找和使用这些信息。
2) Active Directory使用了一种结构化的数据存储方式,并以此做为基础对目录信息进行合乎逻辑的分层组织。
答:程序集(中间语言,源数据,资源,装配清单)。
答:1) 值类型一般被分配在栈上,它的变量直接包含变量的实例,使用效率比较高。
2) 引用类型分配在托管堆上,引用类型的变量一般包含一个指向实例的指针,变量经过该指针来引用实例。
3) 一个是值COPY,一个是地址COPY。
值类型 |
引用类型 |
||
内存分配地点 |
分配在栈中 |
分配在堆中 |
|
效率 |
效率高,不须要地址转换 |
效率低,须要进行地址转换 |
|
内存回收 |
使用完后,当即回收 |
使用完后,不是当即回收,等待GC回收 |
|
赋值操做 |
进行复制,建立一个同值新对象 |
只是对原有对象的引用 |
|
函数参数与返回值 |
是对象的复制 |
是原有对象的引用,并不产生新的对象 |
|
类型扩展 |
不易扩展 |
容易扩展,方便与类型扩展 |
答:.NET Framework 的垃圾回收器管理应用程序的内存分配和释放。每次使用 new 运算符建立对象时,运行库都从托管堆为该对象分配内存。只要托管堆中有地址空间可用,运行库就会继续为新对象分配空间。可是,内存不是无限大的。最终,垃圾回收器必须执行回收以释放一些内存。垃圾回收器优化引擎根据正在进行的分配状况肯定执行回收的最佳时间。当垃圾回收器执行回收时,它检查托管堆中再也不被应用程序使用的对象并执行必要的操做来回收它们占用的内存。
答:索引器容许类或结构的实例按照与数组相同的方式进行索引。索引器相似于属性,不一样之处在于它们的访问器采用参数。能够用任意类型索引。
1) 索引器使得对象可按照与数组类似的方法进行索引。
2) get 访问器返回值。set 访问器分配值。
3) this 关键字用于定义索引器。
4) value 关键字用于定义由 set 索引器分配的值。
5) 索引器没必要根据整数值进行索引,由您决定如何定义特定的查找机制。
6) 索引器可被重载。
7) 索引器能够有多个形参,例如当访问二维数组时。
答:1) 进程是系统进行资源分配和调度的单位。
2) 线程是CPU调度和分派的单位。
3) 一个进程能够有多个线程,这些线程共享这个进程的资源。
答:启动一个线程是调用start()方法,致使操做系统将当前实例的状态更改成ThreadState.Running。
答:构造器Constructor不能被继承,所以不能重写override,但能够被重载Overloade。
答:静态成员override、virtual 或 abstract。
抽象类不能是密封的sealed或静态的static。
答:using 关键字有两个主要用途:
1) 做为指令,用于为命名空间建立别名或导入其余命名空间中定义的类型。
2) 做为语句,用于定义一个范围,在此范围的末尾将释放对象。
new 关键字:新建实例或者隐藏父类方法
答:.NET错误处理机制采用try->catch->finally结构。 throw
发生错误时,层层上抛,直到找到匹配的catch为止。
答:error 表示恢复不是不可能但很困难的状况下的一种严重问题。好比说内存溢出。
不可能期望程序能处理这样的状况。
exception 表示一种设计或实现问题。
也就是说,它表示若是程序运行正常,从不会发生的状况。
答:1) TCP(Transmission Control Protocol)传输控制协议:一种面向链接的、可靠的、基于字节流的运输层通讯协议,三次握手。
2) UDP(User Datagram Protocol)用户数据报协议:它不属于链接型协议,于是具备资源消耗小,处理速度快的优势。缺点是易丢失数据包。
答:1) System.String是不可变的字符串。
2) System.StringBuilder存放了一个可变的字符串,并提供一些对这个字符串修改的方法。
3) String类在执行字符串拼接的操做上,用“+”会产生新的对象,占用内存。
4) StringBuilder类只是修改字符串的内容,不创建新的对象。
答:1) const 字段只能在该字段的声明中初始化。
2) 不容许在常数声明中使用 static 修饰符。
3) readonly 字段能够在声明或构造函数中初始化。所以,根据所使用的构造函数,readonly 字段可能具备不一样的值。
4) 另外,const 字段是编译时常数,而 readonly 字段可用于运行时常数。
答:委托能够把一个方法做为参数代入另外一个方法。
委托能够理解为指向一个函数的引用。
事件是一种特殊的委托。
答:在类型或成员的声明中使用 unsafe 修饰符。所以,类型或成员的整个正文范围均被视为不安全上下文,没法由 CLR 进行验证的代码。
答:封装、继承、多态。
答:声明IEnumerable接口或实现GetEnumerator()方法。
答:接口能够继承接口。抽象类能够实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
答:String类是sealed类故不能够继承。
答:数组、String类都没有Length()方法,它们只有Length属性。
答:即便没有建立类的实例,也能够调用该类中的静态方法、字段、属性或事件。若是建立了该类的任何实例,不能使用实例来访问静态成员。静态成员一般用于表示不会随对象状态而变化的数据或计算。
答:1) 虚函数:没有实现的,可由子类继承并重写的函数。
2) 抽象函数:规定其非虚子类必须实现的函数,必须被重写。
答:?:。格式以下:ndition ? first_expression : second_expression。
答:装箱。
答:delegate.
答:[Serializable]
答:要同时修改Equale和GetHash() ? 重载了"==" 就必须重载 "!="。
答:62移动成2的6次方,26。
答:能够使用指针。也就是非安全代码,就是不在 CLR 彻底控制下执行的代码,它有可能会致使一些问题,所以他们必须用 “unsafe” 进行代表。
&是位运算符,表示按位与运算。
&&是逻辑运算符,表示逻辑与(and)
能够。
(1) 实现1
string[] s ={ "111", "22222" };
ArrayList list = new ArrayList();
list.AddRange(s);
(2)实现2
string[] s ={ "111", "22222" };
ArrayList list = new ArrayList(s);
强名是由程序集的标识加上公钥和数字签名组成的,其中,程序集的标识包括简单文本名称、版本号和区域性信息(若是提供的话)。它使用对应的私钥从程序集文件中生成。(程序集文件包含程序集清单,其中包含组成程序集的全部文件的名称和哈希。)
1. for:使用于肯定次数的循环。
2. foreach:使用于遍历的元素是只读的。//Unity中此处是个坑,建议不要用foreach
3. while:次数不肯定,条件随机变化。
4. do...while:次数不肯定,条件随机变化,但至少要保证能被执行一次。
1. 在应用程序和远程设备中使用协议和网络地址初始化套接字。
2. 在应用程序中经过指定端口和地址创建监听。
3. 远程设备发出链接请求。
4. 应用程序接受链接产生通讯scoket。
5. 应用程序和远程设备开始通信(在通信中应用程序将挂起直到通信结束)。
6. 通信结束,关闭应用程序和远程设备的Socket回收资源。
答:会执行,在return前执行。
public class A { public virtual void Fun1( int i ) { Console.WriteLine( i ); } public void Fun2( A a ) { a.Fun1( 1 ); Fun1( 5 ); } } public class B : A { public override void Fun1( int i ) { base.Fun1( i + 1 ); } public static void Main() { B b = new B(); A a = new A(); a.Fun2( b ); b.Fun2( a ); } }
答案:
2
5
1
6
答案:
public static void Main() { int input = int.Parse( Console.ReadLine() ); int sum = 0; for( int i = 0; i <= input; i++ ) { if( ( i % 2 ) == 1 ) { sum += i; } else { sum = sum - i; } } Console.WriteLine( sum ); }
答:不对,有相同的hash code。
答案:能够做用在byte和long上,也能够做用在string上。
答: 1. short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能隐式转化为short型。可修改成s1 =(short)(s1 + 1) 。
2. short s1 = 1; s1 += 1正确。
题目:须要实现对一个字符串的处理,首先将该字符串首尾的空格去掉,若是字符串中间还有连续空格的话,仅保留一个空格,即容许字符串中间有多个空格,但连续的空格数不可超过一个。
答案:
string inputStr = " xx xx ";
inputStr = Regex.Replace( inputStr.Trim(), @"/s+", " " );
int i = 5;
int j = 5;
if( Object.ReferenceEquals( i, j ) )
Console.WriteLine( "Equal" );
else
Console.WriteLine( "Not Equal" );
答案:Not Equal。由于比较的是对象
答:const不能用static修饰。
class A { public virtual void F() { Console.WriteLine( "A.F" ); } } abstract class B : A { public abstract override void F();//abstract与override关键字能够同时使用 }
答案:没有错误!能够经过编译器。
注意:网上有资料说abstract与override关键字不能够同时使用,这种说法是错误的 !
A. public enum var1{ Mike = 100, Nike = 102, Jike }
B. public enum var1{ Mike = “1”, Nike, Jike }
C. public enum var1{ Mike=-1 , Nike, Jike }
D. public enum var1{ Mike , Nike , Jike }
答案B
class A
{
public static int X;
static A()
{
X = B.Y + 1;
}
}
class B
{
public static int Y = A.X + 1;
static B()
{
}
static void Main()
{
Console.WriteLine( "X={0},Y={1}", A.X, B.Y );
}
}
答:x=1,y=2
class Class1
{
private string str = "Class1.str";
private int i = 0;
static void StringConvert( string str )
{
str = "string being converted.";
}
static void StringConvert( Class1 c )
{
c.str = "string being converted.";
}
static void Add( int i )
{
i++;
}
static void AddWithRef( ref int i )
{
i++;
}
static void Main()
{
int i1 = 10;
int i2 = 20;
string str = "str";
Class1 c = new Class1();
Add( i1 );
AddWithRef( ref i2 );
Add( c.i );
StringConvert( str );
StringConvert( c );
Console.WriteLine( i1 );
Console.WriteLine( i2 );
Console.WriteLine( c.i );
Console.WriteLine( str );
Console.WriteLine( c.str );
}
}
答案:10, 21, 0, str, string being converted
注意:此处加逗号“,”是为了答案看起来清晰,实际结果是纵向排列的,由于调用了Console.WriteLine()。
public abstract class A
{
public A()
{
Console.WriteLine( 'A' );
}
public virtual void Fun()
{
Console.WriteLine( "A.Fun()" );
}
}
public class B : A
{
public B()
{
Console.WriteLine( 'B' );
}
public new void Fun()
{
Console.WriteLine( "B.Fun()" );
}
public static void Main()
{
A a = new B();
a.Fun();
}
}
答案:
A
B
A.Fun()
答:
string的字符串为常量不可修改。
1.能够知足字符串常量池的须要。即对于建立相同文本时,string为同一对象。
2.容许string对象缓存HashCode。字符串不变形保证了hash码的惟一性。
3.安全性,string被许多的类库用来当作参数。
StringBuilder实际是一个char类型的集合,完成了组装拼接等工做。
String更适合作程序的参数,StringBuilder用于作String类型的组装。
答:
StringBuilder的优点在于拼接字符串。
//String的优点在于对字符串作一些处理,在使用过程当中看具体的需求。
答:
int number = 46234;
string strNumber=number.ToString();
int length = strNumber.Length;
方法1:
int result=0;
for (int i = 0; i < length; i++)
{
result += number % 10;
number \= 10;
}
方法2:
for (int i = 0; i < length; i++)
{
result += number / (int)Math.Pow(10, i) % 10;
}
方法3:
for (int i = 0; i < strNumber.Length; i++)
{
result += int.Parse(strNumber[i].ToString());
}
注:
答:
冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,若是它们的顺序错误就把他们交换过来。走访数列的工做是重复地进行直到没有再须要交换。
冒泡排序算法的运做以下:
l 比较相邻元素。若是第一个比第二个大,就交换它们。
l 对每一对相邻元素作一样的工做,从开始第一队到结尾的最后一对。在这一点,最后的元素会使最大的数。
l 针对全部的元素重复以上的步骤,除了最后一个。
l 持续每次对愈来愈少的元素重复上面的步骤,知道没有任何一对数字须要比较。
写法1
public void Bubble1(int[] a)
{
bool b;
int tmp;
for (int i = 0; i < a.Length; i++)
{
b = false;
for (int j = i+1; j < a.Length ; j++)
{
if (a[j] > a[i])
{
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
b = true;
}
}
if(!b)break;
}
}
写法2
void Bubble2(int[] a)
{
bool b=false;
int tmp;
for(int i=0;i<a.Length;i++)
{
b=false;
for(int j=0;j<a.Length-i;j++)
{
if(a[j]<a[j+1])
{
tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
b=true;
}
}
if(!b) break;
}
}
写法3
void Bubble3(int[] a)
{
bool b=true;
int j=0;
int temp;
do
{
b=false;
for(int i;i<a.Length-j;i++)
{
if(a[i]<a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
b=true;
}
}
j++;
}
while(b);
}
object o1 = 1;
object o2 = o1;
o1 = 2;
Console.WriteLine(o2);
答:
1;
缘由:o1将数据1在堆中引用赋值给o2,然后又将引用指向数据2,故o2仍指向数据1的引用。
答:
[访问修饰符][可选修饰符] 返回类型 方法名称(参数列表)
{
//方法体;
return 结果;
}
答:
在不少语言当中如Java\C#中字符串string被设计成具备不可变性的。从系统优化方面考虑这样的设计好处主要由三点。
首先,它容许在一个字符串上执行各类操做,而不实际地更改字符串。
字符串不可变,还由于这在操做或访问一个字符串时不会发成线程同步问题。
除此以外,CLR可经过一个String对象共享多个彻底一致的String内容。这样能减小系统中的字符串数量,者正是字符串留用技术的目的。
1.字符串常量池的须要。字符串常量池是内存堆中一个特殊的存储区域,当建立一个string对象时,假设此字符串值已经存在于常量池中,则不会建立一个新的对象,而是引用已经存在的对象。
2.容许string对象缓存HashCode。字符串不变性保证了hash码的惟一性,所以能够放心地进行缓存,这是一种性能优化手段,由于这没必要每次都去计算新的哈希码。
3.安全性。string被许多的类库用来当作参数,例如网络链接URL,文件路径Path,还有反射机制所须要的String参数等,倘若string可变的,将会引发各类安全隐患。
综上,string不可变的缘由包括设计考虑,效率优化问题,以及安全性三大方面。
另:在C++中string类型是可变的。
答:
方法名称相同,但参数列表不一样称为方法重载。用于在不一样条件下解决同一类型的问题。
class A
{
public static int a;
static A()
{
a = B.b + 1;
}
}
class B
{
public static int b;
static B()
{
b = A.a + 1;
}
}
static void Main()
{
Console.WriteLine(A.a);
Console.WriteLine(B.b);
}
答:2 ,1
class C
{
public static int a;
public C()
{
a++;
}
static C()
{
a++;
}
}
static void Main()
{
C c1 = new C();
C c2 = new C();
C c3 = new C();
Console.WriteLine(C.a);
}
答:4
答:
静态函数没有访问修饰符,其余C#代码历来不调用它,但在加载类时,老是由.NET运行库调用它,因此像public或private这样的访问修饰符就没有任何意义。出于一样缘由,静态构造函数不能带任何参数,一个类也只能有一个静态构造函数。静态构造函数只能访问类的静态成员,不能访问类的实例成员。
也就是说只加static不会报错,加了static再加了别的就会报错。
答:(a,b)=>{}
注:该题有两种错误可能:
一种是方法没有些返回值即Func(string a,string b)为 void Func(string a,string b)此时,Lambda表达式可写做(a,b)=>{}
一种是Func为Func<string,string>此时Lambda可写做a=>b//a,b为string类型
public static int Fibonacci(int num)//Fibonacci
{
return (num==0||num==1)?1:(Fibonacci(num-2)+Fibonacci(num-1));
}
注:计算斐波那契数列依据数列定义来创建方法是不推荐的写法。由于此时计算第n位的数的时间复杂度为O((3/2)n)。相比较而言,利用循环能够将时间复杂度缩小到O(n)该方法较为实用,并且实现简单,在没有特殊要求的状况下属于建议的写法。另外一种优化的写法能够将时间复杂度优化到O(logn),实现代码较复杂,且隐含的时间常数较大。但适合面试者展现其知识面和代码实现的能力。
两种写法以下:
写法一:
public long Fibonacci1(int num)
{
return (num==0||num==1)?1:(Fibonacci1(num-2)+Fibonacci1(num-1));
}
写法二:
public long Fibonacci2(int num)
{
int result[2]={0,1};
if(n<2)
return result[n];
long fibOne=1;
long fibTwo=0;
long fibN=0;
for(int i=2;i<=n;i++)
{
fibN=fibOne+fibTwo;
fibTwo=fibOne;
fibOne=fibN;
}
return fibN;
}
答:
从概念上区分,值类型时直接存储其值,而引用类型是存储对值的引用。
实际中,对于值类型的对象,初始化一个实例,该实例表明的是其内部存储的数据自己。而引用类型的对象,初始化一个实例,该实例表明的是其初始化数据在内存当中的引用。
值类型隐式继承自System.ValueType.该类为抽象类,只能序列化,不能被显式继承。
值类型:枚举,结构
引用类型:数组,委托,类,接口
答:
ArrayList是非泛型列表,存储数据是把全部的数据都当成object类型数据,存在装箱问题,取出来使用的时候存在拆箱问题,装箱拆箱会使性能变差,并且存在数据安全问题,可是优势在于可让值类型和引用类型相互转换。
List是泛型列表,在使用的时候才会去定义数据类型,泛型避免了拆装箱的问题,存入读取熟读较快,类型也更安全。
解析:首先,这道题的描述是不严谨的,GC做为CLR的一种机制是由系统调用的,只要运行与CLR上的托管代码GC的工做自己是不可避免的。
可是抛开这些细节不谈,我能够在这里写把我认为这道题可能涉及到的东西写一下。
若是只把GC理解成一种能够自动释放内存的方式,使程序员省去了手动释放内存的烦恼,或试图引用已释放的内存空间的错误,这无疑是片面的,虽然这的确是GC很是重要的功能。但GC的做用远不如此。
GC的产生是与CLR堆内存特殊的分配方式有关的。CLR要求全部的资源都从托管堆分配,托管堆有一个指针NextObjPtr它的初始为保留地址空间的基地址。NextObjPtr指向下一个对象在堆中的分配位置。每当添加一个对象,NextObjPtr指针的值就会加上对象占据的字节数。这样作有两个好处:
首先,在许多应用程序中,差很少同时分配的对象彼此间有较强的联系,并且常常差很少在同一时间访问。在垃圾回收环境中,若是对象在内存中连续分配,会因为引用的本地性而得到性能上的提高。具体地说,这意味着进程的工做集小于非托管环境中运行类似的应用程序。
另外一方面,这意味着代码使用的对象能够所有驻留在CPU的缓存中,加快CPU对这些对象的访问速度。
但托管堆具备这些好处,是由于它作了一个至关大胆的假设,地址的空间和存储是无限的。那么如何让它由假设变为可实现的,这就是GC垃圾回收的工做。
GC的垃圾回收算法是基于世代法和启发式算法的。
世代法是指将堆分为0代,1代,2代。每当0代的堆满时就触发一次垃圾回收。当第0代的的内存并没被释放,就会被提高到1代,若是1代在被回收时仍然保留的内存,就会被提高到2代。这样压缩空间的的方法保证了堆内存的连续性,增长了访问对象的速度。而启发式算法是指在基于应用程序对新建对象的模式,进行启发式的对第1代,第2代堆进行释放,或扩大第0代的堆空间。
建议只有在如下两种状况下才调用Dispose或Close:肯定必须清理资源;或者肯定能够安全地调用Dispose或Close,并但愿将对象从中介列表中删除,禁止对象提高(到另外一代)从而提升性能。
那么避免由于GC过程而影响性能的编程方法以下:
答:
语法不一样:
1.抽象类中能够有字段,接口没有。
2.抽象类中能够有实现成员,接口只能包含抽象成员。
3.抽象类中全部成员修饰符均可以使用,接口中全部的成员都是对外的,因此不须要修饰符修饰。
用法不一样:
1.抽象类是概念的抽象,接口关注与行为。
2.抽象类的子类与父类的关系是泛化关系,耦合度较高,而实现类和接口之间是实现关系,耦合度比泛化低。
3.一个类只能继承自一个类,可是能够实现多个接口。
string a="abc";//1个对象
a=(a.ToUpper()+"123").Substring(0,2);
答:三个临时对象
注:string a="abc";//1个对象
a=(a.ToUpper()+"123").Substring(0,2);
a.ToUpper()//1个临时对象
"123"//1个临时对象
a.ToUpper()+"123"//1临时个对象
.Substring(0,2)//1个对象因为它将引用赋给了a因此它不是临时对象
在语句运行时结束后不存在引用的对象。
List<int> Is=new List<int>(new int[]{1,2,3,4,5});
foreach(int item in Is)
{
Console.WriteLine(item*item);
Is.Remove(item);
}
答:会产生运行时错误,抛出一个InvalidOperationException异常,由于foreach是只读的。不能一边遍历一边修改。使用foreach时候不要对内容进行修改。
答:sealed访问修饰符用于类时,表示该类不能被继承;对于方法表示不能重写该方法。当应用于方法或属性时,sealed 修饰符必须始终与 override 一块儿使用。
注:
若要肯定是否密封类、方法或属性,一般应考虑如下两点:
派生类利用自定义类的功能所得到的可能好处。
派生类在修改类以后致使其没法正常工做或按预期工做的可能性。
答:public:对任何类和成员都公开,无限制访问
private:仅对该类公开
protected:对该类和其余派生类公开
internal:只能在包含该类的程序集中访问该类
protected internal:protected+internal
注:
可见性修饰符:
修饰符 |
应用于 |
说明 |
public |
全部类型或成员 |
任何代码都可以访问该项 |
protected |
类型和内嵌类型的全部成员 |
只有派生的类型可以访问该项 |
internal |
全部类型或成员 |
只能在包含它的程序集中访问该项 |
prvate |
类型和内嵌类型的全部成员 |
只能在它所述的类型中访问该项 |
protected internal |
类型和内嵌类型的全部成员 |
只能在包含它的程序集和派生类型的代码中访问该项。 |
其余修饰符
修饰符 |
应用于 |
说明 |
new |
函数成员 |
成员用相同的签名隐藏继承的成员 |
static |
全部成员 |
成员不做用于类的具体实例 |
virtual |
仅函数成员 |
成员能够由派生类重写 |
abstract |
仅函数成员 |
虚拟成员定义了成员的签名,但没有提供实现代码 |
override |
仅函数成员 |
成员重写了继承的而虚拟或抽象成员 |
sealed |
类、方法和属性 |
对于类,不能继承自密封类。对于属性和方法,成员重写已继承的虚拟成员,但任何派生类中的任何成员都不能重写该成员。当应用于方法或属性时,sealed 修饰符必须始终与 override 一块儿使用。 |
extern |
仅静态[DllImport]方法 |
成员在外部用另外一种语言实现
|
答:审查元数据并收集关于它的类型信息的能力。
注:
公共语言运行时程序管理应用程序域,应用程序域构成具备相同应用程序范围的对象周围定义的边界。 此管理包括将每一个程序集加载到相应的应用程序域中和控制每一个程序集内的类型层次结构的内存布局。
程序集包含模块、模块包含类型,而类型包含成员。 反射提供封装程序集、模块和类型的对象。 能够使用反射动态地建立类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。而后,能够调用类型的方法或访问其字段和属性。
Reflection,中文翻译为反射。
这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员能够在程序运行期得到这几个组成部分的相关信息,例如:
Assembly类能够得到正在运行的装配件信息,也能够动态的加载装配件,以及在装配件中查找类型信息,并建立该类型的实例。
Type类能够得到对象的类型信息,此信息包含对象的全部要素:方法、构造器、属性等等,经过Type类能够获得这些要素的信息,而且调用之。
MethodInfo包含方法的信息,经过这个类能够获得方法的名称、参数、返回值等,而且能够调用之。
诸如此类,还有FieldInfo、EventInfo等等,这些类都包含在System.Reflection命名空间下。
答:MONO是.NET的一个开源跨平台工具。.NET只能在Windows下运行,Mono能够实现跨平台,能够运行与Linux,Unix,Mac OS等。
答:
1)单一职责原则:一个类,最好只作一件事,只有一个引发它的变化。
2)开放-封闭原则:对于扩展是开放的,对于更改是封闭的。
3)里氏替换原则:子类必须可以替换其基类。
4)依赖倒置原则:设计应该依赖于抽象而不是具体实现。
A.高层模块不该该依赖底层模块,两个都应该依赖抽象。
B.抽象不该该依赖细节,细节应该依赖抽象(要对抽象编程,不要对实现编程。)
5)接口隔离原则:使用多个小的专门的接口而不要使用一个大的总接口。
6)迪米特法则:若是两个类不彼此直接通讯,那么这两个类就不该当发生直接的相互做用。若是其中一个类须要调用另外一个类的某一个方法的话,能够经过第三者转发这个调用。
7)合成/聚合复用原则:尽可能使用合成/聚合,尽可能不要使用类继承。
注:
答:电脑没有绝对的无序,hashtable是经过哈希码让开发者感受无序。
注:这里的无序是指集合的添加顺序与其输出顺序无关。Hashtable是经过哈希码或哈希函数,对其内部元素进行排列的,因此其元素的添加顺序与其输出顺序无关。
答:
单例: 对象池,游戏管理器
抽象工厂,
状态:有限状态机,
桥接:有限状态机
策略:AI自动行为操控中每种操控算法的独例
注:扩展补充。
建立型模式:单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)、访问者模式。
答:列表:
特色:有序,内存空间连续,读取速度快,大小可变,经过位置索引取元素.
缺点:输入,删除的速度慢
类库已实现:List<T>、 ArrayList
字典:
特色:键值对的集合,经过键查找值,查找方便,无序
类库已实现:Dictionary<TKey,TValue>、Hashtable
栈:
特色:后进前出 LIFO(Last In First Out)
支持操做:入栈,出栈,读栈顶,
类库已实现:Stack<T>、Stack
队列:
特色:前进前出 FIFO(First In First Out)
支持操做:入队,出队,读队首
类库已实现:Queue<T>、Queue
链表:
特色:节点内存空间不连续,插入,删除速度快,读取速度慢.
类库已实现:LinkedList<T>
数组:
特色:内存空间连续,长度固定,读取速度快
类库已实现:Array
树:
特色:能够将对象组织为层次结构,
实现:可以使用设计模式中的组合模式实现树结构
答:
Override: 是指方法的重写,C#中可重写abstract、vritual 、override三类方法,重写是子类重写父类的以上三种方法,是动态绑定的,调用速度比方法隐藏慢,但灵活性好,重写本质是对方法表的修改
Overload:是指方法的重载,一个类中的多个同名方法,参数列表不一样,主要指参数个数或类型不一样,重载的目的是为了让实现类似功能的方法用一个名称表示,方便程序员编写和理解代码。可读性好。
重写和重载都是多态的一种体现。
答:
数组:长度固定,大小不变,存储空间连续,读取速度快,插入,删除速度慢。
集合:长度不定,大小可变,存储空间可能不连续,适合存放不肯定数量的数据。
答:
方法一:实现IComparer, 使用Array.Sort(Array, IComparer )
方法二:使用OrderBy或OrderByDescending 方法加Lambda表达式
如:arr = arr.OrderBy(p=>p.age).ToArray();
答: 在按钮上绑定一个带有OnClick事件List<EventDelegate>;
EventDelegate();
EventDelegate(Callback call);//void Callback()
EventDelegate(MonoBehaviour target,string methodName)
答:必须安装QuickTime播放器,不支持FLV视频格式。
答:MovieTexture。
答:
存储:PlayerPrefs.SetInt ("MyKey", 1);
获取:int myKey = PlayerPrefs.GetInt ("MyKey");
答:
PlayerPrefs.DeleteKey ("MyKey");
PlayerPrefs.DeleteAll ();
答:NavMeshAgent。
答:寻路网格动态碰撞组件,用于运动的物体阻碍寻路物体效果。
答:射线碰到的碰撞信息
答:经过LayerMask(层的遮罩),RaycastHit返回的碰撞的标签。
答:Generic Humanoid类人样式。
关键帧动画
默认骨骼动画(人型)
CAT
动画->点缓存->关键帧
答:
l 简单化对类人角色动画设计与功能实现的工做流程。
l Mecanim动画系统使用一个可视化编程工具来管理动画之间复杂的交互。
l 对完成绑定骨骼的类人角色,可以对身体不一样的地方使用不一样的逻辑进行动画控制。
l 能够在角色动画播放过程当中添加动画事件。
l 人形动画骨骼动画可重复使用。
答:Panel是一个容器,它将包含全部UI小部件,并负责将所包含的部件组合。
Anchor是NGUI中屏幕分辨率的自适应性,来适应不一样的分辨率的屏幕显示。
注:
答:以平面任意两点,取两平面法向量,连接两点线段,线段是否与法向量的夹角来判断是否平行。
法向量若是平行,看线段与法向量的夹角,若是平行则两平面重合,判断边界是否相交。
若是平行,且有夹角,说明不重合两平面平行,必定不相交。
若是法向量不平行,将该线段的在两平面投影方向上的射线判断与平面的边界条件,若是两条射线的交点都在边界内,则相交,不然不相交。
注:
答:MeshCollider是网格碰撞器,对于复杂网状模型上的碰撞检测,比其余的碰撞检测精确的多,可是相对其余的碰撞检测计算也增多了,因此通常使用网格碰撞也不会在面数比较高的模型上添加,而会作出两个模型,一个超简模能表示物体的形状用于作碰撞检测,一个用于显示。
MeshCollider有Mesh属性
答:
答:两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体。
注:动的物体,你但愿发生碰撞效果的物体要带能接受物理引擎的操做,最多见的就是挂载Rigidbody组件。
答:CharacterController自带胶囊碰撞器,里面包含有刚体的属性;
Rigidbody就是刚体,使物体带有刚体的特征。
注:
答:穿透(碰撞检测失败)。将物体移动放在FixedUpdate中,尽可能使用物理引擎本身的移动方法。
避免的方法:把刚体的实时碰撞检测打开Collision Detection修改成Continuous Dynamic
注:
答:
主要是三个阶段:
1.Collider.OnCollisionEnter 进入碰撞,当collider/rigidbody开始触动另外一个rigidbody/collider时OnCollisionEnter被调用。
2.Collider.OnCollisionStay 逗留碰撞,每一个collider/rigidbody触动rigidbody/collider,将在每帧调用OnCollisionStay。通俗的说,一个碰撞器或刚体触动另外一个刚体或碰撞器,在每帧都会调用OnCollisionStay,直到它们之间离开不接触。
3.Collider.OnCollisionExit 退出碰撞,当 collider/rigidbody中止触动另外一个 rigidbody/collider时,OnCollisionExit被调用。
答:
答:主要有关节动画、单一网格模型动画(关键帧动画)、骨骼动画。
1.关节动画:把角色分红若干独立部分,一个部分对应一个网格模型,部分的动画链接成一个总体的动画,角色比较灵活,Quake2中使用这种动画。
2.单一网格模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,而后插值运算实现动画效果,角色动画较真实。
3.骨骼动画,普遍应用的动画方式,集成了以上两个方式的优势,骨骼按角色特色组成必定的层次结构,有关节相连,可作相对运动,皮肤做为单一网格蒙在骨骼以外,决定角色的外观,皮肤网格每个顶点都会受到骨骼的影响,从而实现完美的动画。
答:反转动画,将动画的播放速度调到-1。
答:AddClip 添加剪辑、Blend 混合、Play 播放、Stop 中止、Sample 采样 、CrossFade淡入淡出切换动画、IsPlaying是否正在播放某个动画
答:动画层做为一个具备层级动画编辑概念的工具,能够用来制做和处理任何类型的动画。202,203题
答:ITween是补间动画的一个插件,主要做用就是给出开始、结束的值、时间,此插件实现各类动画,晃动,旋转,移动,褪色,上色,音量控制等等。
方法: 1.MoveTo 物体移动
2.ColorTo:随着时间改变对象的颜色组
3.LookTo:随时间旋转物体让其脸部朝向所提供的Vector3或Transform位置
答:
法线贴图:是一种特殊的纹理,能够应用在3D表面,让低模呈现出更明显的凹凸效果。一
般应用在CG动画、美术效果要求较高的单机游戏
CG动画:游戏中的CG动画实际上是用3D模拟引擎制做的游戏短片,通常画面效果比较真实。
答:Unity支持多线程,若是同时要处理不少事情或者与Unity的对象互动小能够用thread,不然使用coroutine。
注意:1.虽然支持多线程,可是仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用,因此若是使用的话须要把组件中的数值传到开启的新线程中。
2.C#中有lock这个关键字,以确保只有一个线程能够在特定时间内访问特定的对象
答:多线程程序同时运行多个线程,除主线程以外的线程没法访问Unity3D的对象、组件、方法,而在任一指定时刻只有一个协程在运行。
答:在主线程运行时同时开启另外一段逻辑处理,来协助当前程序的执行。使用户能够编写更灵活的程序来控制运动、序列以及对象的行为。
答:所谓四元数,就是把4个实数组合起来的东西。4个元素中,一个是实部,其他3个是虚部
做用:四元数用于表示旋转
优势:
1)能进行增量旋转
2)避免万向锁
3)给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
四元数不会有欧拉角存在的 gimbal lock 问题[万向节死锁]
四元数由4个数组成,旋转矩阵须要9个数
两个四元数之间更容易插值
四元数、矩阵在屡次运算后会积攒偏差,须要分别对其作规范化(normalize)和正交化 (orthogonalize),对四元数规范化更容易
与旋转矩阵相似,两个四元组相乘可表示两次旋转
答:游戏界面能够看到不少摄像机的混合。
答:正交和透视。
正交没法看到一个物体距离本身有多远,或者远近的变化,物体也不会随着距离而收缩,因此通常作2D游戏或者是UI时会使用正交摄像机。
透视通常看物体会随着距离有大小的变化,通常3D游戏里常用这种摄像机。
答:Prefab是预制件(预制物),通常当游戏中须要频繁建立一个物体时,使用预制物能够节省内存,方便建立,方便对游戏物体进行操做,方便对属性进行修改。
答:动态加载再实例化,若是本身不主动清理内存的话,再次加载不会增长内存的,会自动去取以前已经加载好的assets,若是这一个assets你都嫌多的话,那你只能减资源了,好比,模型面数,纹理尺寸等
答:实际光照强度l=环境光(lambient)+漫反射光(Idiffuse)+镜面高光(lspecular)
环境光:lambient=环境光强度(Aintensity)*环境光颜色(Acolor)
漫反射光:ldiffuse=镜面光照强度(Dintensity)*镜面光颜色(Scolor)*(光的反射向量(R).观察者向量(V))^镜面光指数(n)
答:MeshRender是模型渲染的组件,有此组件物体才能显示出来
Material是材质球,实际就是shader的实例,并进行赋值,贴图、纹理、颜色等。
Shader是着色器,其实是一段程序,还能够用来实现一些仅靠贴图不容易实现的效果,如玻璃。
Shader大体分为:1.表面着色器
2.顶点和片元着色器
3.固定功能着色器
答:Alpha Blend是 实现透明效果,Color = 原颜色*alpha/255+目标色*(255-alpha)/255
答:1.使用光照贴图比使用实时光源渲染要快
2.能够下降游戏内存消耗
3.多个物体能够使用同一张光照贴图
答:顶点着色器:顶点着色器是一段执行在GPU上的程序,用来取代fixed pipeline中的
transformation和lighting,Vertex Shader主要操做顶点。
Vertex Shader对输入顶点完成了从local space到homogeneous space(齐次空间)的变换过程,homogeneous space即projection space的下一个space。在这其间共有world transformation, view transformation和projection transformation及lighting几个过程。
答:4种,Directionl light ,Point Light ,Spot Light,Area Light
平行光:Directional Light
点光源:Point Light
聚光灯:Spot Light
区域光源:Area Light
答:FixedUpdate,每固定帧绘制时执行一次,和Update不一样的是FixedUpdate是渲染帧执行,若是你的渲染效率低下的时候FixedUpdate调用次数就会跟着降低。FixedUpdate比较适用于物理引擎的计算,由于是跟每帧渲染有关。Update就比较适合作控制。
答:Awake –>OnEnable->Start
OnEnable在同一周期中能够反复地发生
Awake用于在游戏开始以前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在全部对象被初始化以后调用,因此你能够安全的与其余对象对话或用诸如GameObject.FindWithTag这样的函数搜索它们。每一个游戏物体上的Awke以随机的顺序被调用。所以,你应该用Awake来设置脚本间的引用,并用Start来传递信息。
Start在脚本的生命周期中只被调用一次。它和Awake的不一样是Start只在脚本实例被启用时调用。你能够按需调整延迟初始化代码。Awake老是在Start以前执行。这容许你协调初始化顺序。
但Start能够做为协程,达到在同一周期调用屡次的效果。不过实质上依然是调用一次。
答:ExcutionOrder有关,不设定顺序的时候初始化Start的顺序不肯定。
答:
|
方法名(按脚本声明周期排列) |
做用 |
备注 |
Editor |
Reset |
重置为默认值。 |
在用户点击见识版面的Reset按钮或者首次添加该组件时被调用。此方法只在编辑模式下被调用。 |
Initialization |
Awake |
|
|
OnEnable |
|
|
|
Start |
Start在behaviour的生命周期中只被调用一次。它和Awake的不一样是Start只在脚本实例被启用时调用。你能够按需调整延迟初始化代码。Awake老是在Start以前执行。这容许你协调初始化顺序。 |
Start仅在Update方法第一次被调用前调用。 |
|
Physics |
FixedUpdate |
处理Rigidbody时,须要用FixedUpdate代替Update。例如:给刚体加一个做用力时,你必须应用做用力在FixedUpdate里的固定帧,而不是Update中的帧。(二者帧长不一样) |
若是固定时间步长小于实际帧更新时间,那么每一帧物理周期将会可能发生不止一次。 |
yield WaitForFixedUpdate |
|
||
Internal physics update |
|
||
OnTriggerXXX |
|
||
OnCollisionXXX |
|
||
Input events |
OnMouseXXX |
|
|
Game logic |
Update |
|
若是一个协成以前已经yield了,可是如今因为恢复了,那么将执行剩下的部分。 |
yield null |
|
||
yield WaitForSeconds |
|
||
yield WWW |
|
||
yield StartCoroutine |
|
||
Internal animation update |
|
||
LateUpdate |
|
||
Scene rendering |
OnWillRenderObject |
若是对象可见每一个相机都会调用它。此函数在消隐过程当中被调用,在渲染全部被消隐的物体以前被调用。你能够用它来建立具备依赖性的纹理而且只有在被渲染的物体可见时才更新这个纹理。举例来说,它已用于水组件中。 |
|
OnPreCull |
消隐决定哪一个物体对于相机来讲是可见的.OnPreCull仅是在这个过程被调用。 |
只有脚本被附加到相机上时才会调用这个函数。 |
|
OnBecameVisible |
|
|
|
OnBecameInvisible |
|
|
|
OnPreRender |
在相机渲染场景以前被调用。 |
只有脚本被附加到相机并被启用时才会调用这个函数。 |
|
OnRenderObject |
|
|
|
OnPostRender |
在相机完成场景渲染以后被调用。 |
只有该脚本附于相机并启用时才会调用这个函数。OnPostRender能够是一个协同程序。 |
|
OnRenderImage |
|
|
|
Gizmo rendering |
OnDrawGizmos |
|
只在编辑模式下调用 |
GUI rendering |
OnGUI |
|
在每一帧更新时调用屡次 |
End of frame |
yield WaitForEndOfFrame |
|
|
Pausing |
OnApplicationPause |
|
在程序检测到暂停时,会在帧的结尾处被调用。 |
Disable/enable |
OnDisable |
|
在脚本是失效时被调用,被销毁时也会被调用。若是再启用的话,OnEnable会再一次被调用。 |
Decommissioning |
OnDestroy |
|
|
OnApplicationQuit |
|
|
答:FixedUpdate由于不受到计算机帧频的影响,因此适合于作物理方面的更新。
答:LateUpdate,它是在Update结束后才调用。通常来讲摄像机的跟随,都是在全部Update操做完成后进行的,以避免出现摄像机已经推动了,可是还有角色未刷新的空帧出现。
答:当物体是否可见切换之时。能够用于只须要在物体可见时才进行的计算。
当renderer(渲染器)在任何相机上都不可见时调用:OnBecameInvisible
当renderer(渲染器)在任何相机上可见时调用:OnBecameVisible
答:PlayerPrefs.SetInt()
PlayerPrefs.GetInt()
答:单独的动画状态,混合树。
答:
动画层中的权重是指某个动画层在整个动画中的影响,Weight的取值范围为(0~1)
若权重值为1则此层动画将与整个动画融合
若权重值为0则此层动画与整个动画彻底不融合
答:使用动画层来管理身体不一样部分的复杂状态机。好比:你能够使用下半身(动画)层来管理走动/跑动;使用上半身(动画)层来控制攻击/挥手动做。
Animator anim ;
int idle = Animator.StringToHash("Base Layer.Idle");
AnimatorStateInfo currentBaseStage;
void Start () {
anim = GetComponent<Animator>();
}
void Update () {
currentBaseStage = anim.GetCurrentAnimatorStateInfo(0);
if (currentBaseStage.nameHash == idle && !anim.IsInTransition(0)) {
anim.SetBool("hit", false);
}
答:判断当前播放的动画名字如果默认层的Idle,而且没有在进行动画切换,则设置hit动画参数为false。
答案:9
答:动画事件。
答:
1D是使用一个动画参数来控制blend tree中几个动画判断的融合,
2D是使用两个动画参数来控制blend tree中几个动画判断的融合。
答:
public Camera myCamera;
myCamera.WorldToScreenPoint(hit);
答:网格寻路。
答:
1.Resources.Load();
2.AssetBundle
区别:
Resources资源的加载是动态加载内部的,AssetBundle 是动态加载外部的。
Resources是动态内部调用,Resources在编辑环境下是project窗口的一个文件夹,调用里面的资源,能够用Resources类,好比Resources.Load,打包后这个文件夹是不存在的,会统一辈子成Assets资源。
AssetBundle 是外部调用,要用AssetBundle 首先要先把资源打包为.assetbundle文件,再动态的去加载这个文件,本地或者网络服务器均可以。
WWW读取文件
答: MonoBehaviour.OnLevelWasLoaded
答:Destory
答:获取:GetComponent
增长:AddComponent
没有删除组件只有让组件不生效:enable
答:加载关卡 。
UnityEngine.SceneManagement名称空间下
SceneManager.LoadScene//加载场景
SceneManager.LoadSceneAsync//异步加载场景
答: Debug.Log();
答:层索引。射线。
答:
localPosition:自身位置,相对于父级物体的变换的位置,局部坐标其实就是自身的坐标。
Position:在世界坐标transform的位置,世界坐标是不会变的,一直以世界坐标轴的XYZ为标准。
答:Transform.Rotate()。
答:
public class TestAround : MonoBehaviour
{
public GameObject ObjA;
public GameObject ObjB;
Vector3 NormalVector3;//法线
float speed = 5;
void Start()
{
GetNormal(AroundType.Horizontal);
}
private void GetNormal(AroundType aroundType)
{
Vector3 temp = ObjB.transform.position - ObjA.transform.position;
switch (aroundType)
{
case AroundType.Vertical:
NormalVector3=Vector3.Cross(Vector3.forward,temp);
break;
case AroundType.Horizontal:
NormalVector3 = Vector3.Cross(Vector3.up, temp);
break;
default:
break;
}
}
void Update()
{
Debug.DrawLine(NormalVector3,ObjA.transform.position);
Vector3 temp = ObjB.transform.position - ObjA.transform.position;
Debug.DrawLine(temp, ObjA.transform.position);
Around(ObjA, ObjB);
}
private void Around(GameObject objA, GameObject objB)
{
Quaternion quater=Quaternion.Euler( NormalVector3*Time.deltaTime*speed);
objB.transform.position = quater * objB.transform.position;
}
}
enum AroundType
{
Vertical,
Horizontal
}
答:Transform 父类是 Component
答:添加刚体使小鸟模拟受到重力和空气阻力影响。不添加刚体的话写受力分析。
设横轴为方向的加速度为ax,垂直轴为ay。
小鸟的Vx,Vy
Vx=Vx+t*ax;(Vx>=0)
Vy=Vy+t*ay;
答:PhysicMaterial 物理材质:主要是控制物体的摩擦,弹力等物理属性。
Material材质:主要是控制一个物体的颜色,质感等显示。
答:rigidbody.AddForce/AddForceAtPosition,都在rigidbody系列函数中。
答:Hinge Joint,能够模拟两个物体间用一根链条链接在一块儿的状况,能保持两个物体在一个固定距离内部相互移动而不产生做用力,可是达到固定距离后就会产生拉力。
答: Unity内一种用于实现自动寻路的网格。
答: JavaScript,C#,Boo
答:1)点乘计算两个向量之间的夹角,还可表示某一方向的投影。
2)叉乘获得的是法向量。
3)标准化向量:用在只关系方向,不关心大小的时候。
答:用于表示线性变换:旋转、缩放、投影、平移、仿射。
注意:矩阵的蠕变:偏差的积累。
答:Unicode是国际组织制定的能够容纳世界上全部文字和符号的字符编码方案。
使用动态字体时,Unity将不会预先生成一个与全部字体的字符纹理。当须要支持亚洲语言或者较大的字体的时候,若使用正常纹理,则字体的纹理将很是大。
答:render是渲染器,渲染器能够使物体显示在屏幕上。
MeshRender是网格渲染,SkinnedMeshRender是蒙皮网格渲染器
答:骨骼蒙皮动画,模型自己是静态的,是由于经过蒙皮,使模型每一个点都有Skin数据,Skin数据包括顶点受到哪些骨骼影响以及这些骨骼影响顶点的权重值,还有动画数据,有了Skin数据的模型就能够根据动画数据进行显示动画了。
答:1)将Assets目录和Library目录一块儿迁移。
2)导出包。
3)用unity自带的assets Server功能。
答:LOD是Level of detail简称,意为多层次细节,是最经常使用的游戏优化技术,LOD技术指根据物体模型的几点在显示环境中所处的位置和重要性,决定物体渲染的资源分配,下降非重要物体的面数和细节度,从而得到高效率的渲染运算。
优势:可根据距离动态的选择渲染不一样细节的模型
缺点:增长美工工做量,增大了游戏的容量。
注:精简文字描述。
答:LOD(Level of detail)多层次细节,是最经常使用的游戏优化技术,LOD技术指根据物体模型的几点在显示环境中所处的位置和重要性,决定物体渲染的资源分配,下降非重要物体的面数和细节度,从而得到高效率的渲染运算。
优势:可根据距离动态的选择渲染不一样细节的模型
缺点:增长美工工做量,增大了游戏的容量。
答:自身阴影:因物体自身的遮挡而使光线照射不到它上面的某些可见面
工做原理:利用背面剔除的方法求出,即假设视点在点光源的位置。
投射阴影:因不透明物体遮挡光线使得场景中位于该物体后面的物体或区域收不到光照照射而造成的阴影。
工做原理:从光源处向物体的全部可见面投射光线,将这些面投影到场景中获得投影面,再将这些投影面与场景中的其余平面求交得出阴影多边形,保存这些阴影多边形信息,而后在按视点位置对场景进行相应处理获得所要求的视图(利用空间换时间,每次只需依据视点位置进行一次阴影计算便可,省去了一次消隐过程)如果动态光源此方法就无效了。
答:MipMapping:在三维计算机图形的贴图渲染中有经常使用的技术,为加快渲染进度和减小图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为MipMap。
答:指定身体的某一部分是否参与渲染
答:须要获得Mono.Data.Sqlite.dll 文件与System.Data.dll文件。
答:1.压缩自带类库;
2.将暂时不用的之后还须要使用的物体隐藏起来而不是直接Destroy掉;
3.释放AssetBundle占用的资源;
4.下降模型的片面数,下降模型的骨骼数量,下降贴图的大小;
5.使用光照贴图;
6.使用多层次细节(LOD);
7.使用着色器(Shader);
8.使用预设(Prefab)等。
解析:内存开销无外乎三大部分:1.资源内存占用;2.引擎模块自身内存占用;3.托管堆内存占用
在一个较为复杂的大型项目中,资源的内存占用每每占据了整体内存的70%以上。所以,资源使用是否恰当直接决定了项目的内存占用状况。通常来讲,一款游戏项目的资源主要能够分为如下几种:纹理(Texture),网络(Mesh),动画片断(AnimationClip)、音频片断(AudioClip)、材质(Material)、着色器(shader)、字体资源(Font)以及文本资源(TextAsset)等等。其中,纹理,网格、动画片断和音频片断则容易形成较大内存开销的资源。
纹理资源能够说是几乎全部游戏项目中占据最大内存开销的资源。一个6万片的场景,网格资源最大才不过10MB,但一个2048*2048的纹理,可能直接就达到16MB,所以,项目中纹理资源的使用是否恰当会及大地印象项目的内存占用。
那么,纹理资源再使用时应该注意哪些地方呢?
纹理格式。纹理格式是研发团队最须要关注的纹理属性。由于它不只影响纹理的内粗你占用,同时还决定了纹理的加载效率。通常来讲,咱们建议开发团队尽量根据硬件的种类选择硬件支持的纹理格式好比Android平台的ETC、iOS平台的PVRTC、WindowsPC上的DXT等等。所以,咱们在UWA测评报告中,将纹理格式进行了罗列,一边开发团队进行快速查找,一步定位。
在使用硬件支持的纹理格式时,你可能会遇到如下几个问题:
色阶问题
因为ETC、PVRTC等格式均为有损压缩,所以,当纹理色差范围跨度较大时,均不可避免地形成不一样程度的阶梯状的色阶问题。所以,不少研发团队使用RGBA32/ARGB32格式来实现更好的效果。可是,这种作法将形成很大的内存占用。好比,一样一张1024*1024的纹理,若是不开启Mipmap,而且为PVRTC格式,则其内存占用为512KB,而若是转换为RGBA32位,则极可能占用更达到4MB。因此,研发团队在使用RGBA32或ARGB32格式的纹理时,必定要慎重考虑,更为明智的选择是尽可能减小纹理的色差范围,时期尽量使用硬件支持的压缩格式进行存储。
ETC1不支持透明通道问题
在Android平台上,对于使用OpenGLES2.0的设备,其纹理格式仅能支持ETC1格式,该格式有个较为严重的问题,即不支持Alpha透明通道,使得透明贴图没法直接经过ETC1格式来进行存储。对此。咱们建议研发团队将透明贴图尽量分红两张,即一张RGB24位纹理记录原始纹理的颜色部分和一张Alpha8纹理记录原始纹理的透明通道部分。而后,将这辆张贴图分别转化为ETC1格式的纹理,并经过特定的Shader来进行渲染,从而来达到支持透明贴图的效果。该种方法不只能够极大程度上逼近RGBA透明贴图的渲染效果,同时还能够下降纹理的内存占用,是咱们很是推荐的使用方式。
固然,目前已经有愈来愈多的设备支持了OpenGLES3.0这样Android平台上你能够进一步使用ETC2甚至ASTC,这些纹理格式均为支持透明通道且压缩比更为理想的纹理格式。若是你的游戏适合人群为中高端设备用户,那么不妨直接使用这两种格式来做为主要存储格式。
纹理尺寸
通常来讲,纹理尺寸越大,占用内存越大。
Mipmap功能
Mipmap旨在有效下降渲染带宽的压力,提高游戏的渲染效率。可是,开启Mipmap会有将纹理内存提高1.33倍。对于具备较大纵深感的3D游戏来讲,3D场景模型和角色咱们通常是建议开启Mipmap功能的,但不少2DUI纹理就没必要要了。
Read&Write
通常状况下,文理资源“Read&Write”功能在Unity引擎中是默认关闭的。可是,咱们仍然在项目深度优化时发现了很多项目的纹理资源会开启该选项。对此,咱们建议压发团队密切关注文理资源中该选项的使用,由于开启该选项将会使文理内存增大一倍。
网格资源在比较复杂的游戏中,每每占据较高的内存。对于网格资源来讲,它在使用时应该注意那方面呢?
1) Normal\Color和Tangent(切线)
在咱们深度优化过的大量项目中,Mesh资源的数据常常会含有大量的Color数据,Normal数据和Tangent数据。这些数据的存在将大幅增长Mesh资源的文件体积和内存占用。其中Color数据和Normal数据主要为3DMax、Maya等建模软件导出时设计所生成,而Tangent通常为导入引擎时生成。
更为麻烦的是,若是项目对Mesh进行DrawCallBatching操做的话,那么狠有可能进一步增长整体内存的占用。正因如此,咱们在UWA测评报告中为每一个Mesh展现了其Normal,Color和Tangent属性的具体使用状况,研发团队能够直接针对每种属性进行排序查看,直接定位出现冗余数据的资源。通常来讲这些数据主要为Shader所用,来生成较为酷炫的效果。因此,建议研发团队针对项目中的网格资源进行详细检测,查看该模型的渲染Shader中是否须要这些数据进行渲染。
答:
解析:CPU方面
就目前Unity移动游戏而言,CPU方面的性能开销主要可归结为两大类:引擎模块性能开销和自身代码性能开销。其中,引擎模块中又可细致划分为渲染模块、动画模块、物理模块、UI模块、粒子系统、加载模块和GC调用等等。
经过大量的性能测评数据,咱们发现渲染模块、UI模块和加载模块,每每占用了CPU性能开销的Top3。
1下降DrawCall
下降DrawCall的方法则主要是减小渲染物体的材质种类,并经过DrawCallBatching来减小其数量。Unity文档对DrawCallBatching的原理和注意事项很是详尽,感兴趣的朋友能够直接查看Unity官方文登。
可是,须要注意的是游戏性能并不是DrawCall越小越好。这是由于,决定渲染模块心梗的除了DrawCall以外,还有用于传输渲染数据的总先带宽。当咱们使用DrawCallBatching将同种的材质和网络模型拼合在仪器室,可能会形成同一时间须要传输的数据(Texture、VB/IB等)大大增长,以致于形成堵塞。在资源没法计时传输过去的状况下,GPU只能等待,从而反倒下降了游戏的运行帧率。
DrawCall和总线带宽是天平的两端,咱们须要作的是尽量维持天平的平衡,任何一边太高或太低,对性能来讲都是无益的。
2简化资源
简化资源师很是行之有效的优化手段。在大量的移动游戏中,其渲染资源实际上是过量的。过量的过量的网络资源、不合规的纹理资源等等。
关于渲染模块在CPU方面的优化方法还有不少,好比LOD、Occlusion Culling和Culling Distance等等。
2 UI模块
UI模块一样也是几乎全部的游戏项目中必备的模块。一个性能优异的UI模块能够将游戏的用户体验再抬高一个档次。
在NGUI优化方面,UIPanel.LateUpdate为性能优化的重中之重。
对于UIPanel.LateUpdate的优化,主要着眼与UIPanel的布局,其原则以下:
尽量将动态UI元素和静态UI元素分离到不一样的UIPanel中,从而尽量将由于变更的UI元素引发的冲欧控制在较小的范围内;
尽量让动态UI元素按照同步性进行划分,即运动帧率不一样的UI元素尽量分离放在不一样的UIPanel中;
控制同一个UIPanel中动态UI元素的数量,数量越多,所建立的Mesh越大,从而使得重构的开销曾加。好比战斗过程当中的HUD运动协调会出现的比较多,此时,建议研发团队将运动血条分离成不一样的UIPanel,每组UIPanel下5~10个动态UI为宜。这种作法,其本质是从几率上尽量下降单振中UIPanel的重建开销。
3加载模块
加载模块一样也是任何游戏项目中所不可缺乏的组成成分。与以前两个模块不一样的是,加载模块的性能开销比较集中,主要出现于场景切换处,且CPU占用峰值均较高。
这里,咱们先来讲说场景切换时,其性能开销的主要体现形式。对于目前的Unity版本而言,场景切换时的主要性能开销主要体如今两个方面,前一场景的场景卸载和下一场景的场景加载。下面,咱们就具体来讲说两个方面的性能瓶颈:
1场景卸载,对于Unity引擎而言,场景卸载通常是由引擎自动完成的,即当咱们调用相似Application.LoadLevel的API时,引擎即会开始对上一场景进行处理,其性能开销主要被如下几部分占据。
Destroy
引擎在切换场景时会手机为表示成DontDestoryOnLoad的GameObject及其Component,而后进行Destroy。同时,代码中的OnDestory被触发执行,这里的性能开销主要取决于OnDestroy回调函数中的代码逻辑。
Resources.UnloadUnusedAssets
通常状况下,场景切换过程当中,该API会被调用两次,依次为引擎在切换场景是自动调用,另外一次则为用户手动调用(通常出如今场景加载后,用户调用它来确保上一场景的资源被卸载干净)。在咱们测评过的大量项目中,该API的CPU开销主要集中在500ms~3000m之间。其耗时开销主要取决于场景中Asset和Object的数量,数量越多,则耗时越慢。
2场景加载
场景加载过程的性能开销又可细分红如下几个部分:
资源加载
资源加载几乎占据整个加载过程的90%以上,其加载效率主要取决于资源的加载方式(Resource.Load或AssetBundle加载)、加载量(纹理、网格、材质等资源数据的大小)和资源格式(纹理、音频格式等)。不一样的加载方式、不一样的资源格式,其加载效率可谓千差万别。
Instantiate实例化
在场景加载过程当中,每每伴随着大量的Instantiate实例化操做。在Instantiate实例化时,引擎底层会查看相关的资源是否已经被加载,若是没有,则会先加载其相关资源,再进行实例化,这实际上是你们遇到大多数“Instantiate”实例化问题的根本缘由。
AssetBundle文章中所提倡的资源依赖关系打包并进行预加载,从而来缓解Instantiate实例化的压力。
另外一方面,Instantiate实例化的性能开销还体如今脚本代码的序列化上,若是脚本中序列化的信息不少,则Instantiate实例化时的时间亦会很长。最直接的例子就是NGUI,其代码中存在不少SerializedField标识,从而在实例化时带来了较多的代码序列化开销。所以,在打架增长序列化信息时,这一点是须要你们时刻关注的
以上是游戏项目中性能开销最大的三个模块,固然,游戏类型的不一样、设计的不一样,其余模块仍然会有较大的CPU占用。好比ARPG游戏中动画系统和物理系统,音乐休闲类游戏中的音频系统和例子系统等。
4 代码效率
逻辑代码在一个较为复杂的游戏项目中每每占据较大的CPU开销。这种状况在MOBA\ARPG\MMORPG等游戏类型中很是常见。
在项目优化过程当中,咱们常常会想知道,到底哪些函数占据了大量的CPU开销。同时,绝大多数的项目其中性能开销都遵循着“二八原则”,即80%的性能消耗都集中在20%的函数上。
答:
插件功能 |
插件名称 |
界面制做 |
NGUI |
2D游戏制做 |
2D Toolkit |
可视化编程 |
PlayMaker |
插值插件 |
iTween、HOTween |
路径搜寻 |
SimplePath |
美术及动画制做 |
RageSpline、Smooth Moves |
画面加强 |
Bitmap2Material、Strumpy Shader Editor |
摄像机管理 |
Security Camera |
资源包 |
Nature Pack |
造路插件 |
EasyRoads3D |
即时遮挡剔除/LOD多细节层次 |
Instant Occlusion Culling |
答:是指在显示器上为了显示出图像而通过的一系列必要操做。
渲染管道中的不少步骤,都要将几何物体从一个坐标系中变换到另外一个坐标系中去。
主要有三步:应用程序阶段,几何阶段 光栅阶段
本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。
答:计算机中显示的图形通常能够分为两大类——矢量图和位图。矢量图使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是经过数学公式计算得到的。例如一幅花的矢量图形其实是由线段造成外框轮廓,由外框的颜色以及外框所封闭的颜色决定显示出的颜色。因为矢量图形可经过公式计算得到,因此矢量图形文件体积通常较小。矢量图形最大的优势是不管放大、缩小或旋转等不会失真;最大的缺点是难以表现色彩层次丰富的逼真图像效果。
答:矩阵:横轴排列的二维数据表格
矩阵运算:
加减 限制条件:行和列必须相同,对应相加相减获得结果
乘法 限制条件:要求左矩阵的行和右矩阵的列必须同,行数和左矩阵相等,列数和右矩阵相等,结果的第i行第j列,是左矩阵的第i行和右矩阵的第j列逐个相乘并把结果相加,获得结果是结果 的 第i行第j列。
答:角度和弧度
度和弧度之间的换算 1弧度 = 180度 /pi(约57.3)
1度=pi/180弧度(约0.017)
答:矢量有方向如力速度 标量只有大小没有方向如温度
矢量取模就是只要大小不要方向
单位向量 有方向 大小为1的向量
矢量的加法:是矢量的几何和,服从平行四边形规则
矢量知足交换律,知足结合律
在直角坐标系中,矢量等于骑在坐标轴上投影的矢量之和(二维矢量能够看作三维矢量的特例也就是说,三维成立,二维也成立)
矢量减法:
大小相等 方向相反 称为逆矢量。
任意多个矢量首尾相链接组成闭合多边形,其结果必为0
矢量的乘法:点积(内积、标量积)、叉积(外积)结果是矢量
点积方法 dot
注:这题要问什么?
答:
1.Resources
2.AssetBundle
3.WWW
答:实时光源会对性能有影响,解决方案有如下几种:
1使用unity的烘焙系统烘焙替代实时光源。
2使用三维建模软件的烘焙系统烘焙代替实时光源。
3通常移动端开发实时光源只为了提供实时阴影效果,因此设置实施光照的有效层。
答:
Time.timeScale = 0;便可让游戏暂停。
Time.timeScale = 1时,Update、LateUpdate、FixedUpdate 都按正常的时间来执行。
Time.timeScale = 2时,Update和 LateUpdate的执行速度是以前的2倍,而FixedUpdate仍是按正常时间来执行
答:Prefab能够理解为是一个游戏对象及其组件的集台,做用是使游戏对象及资源可以被重复使用。相同的对象能够经过一个预设来建立,此过程可理解为实例化,预设能够进行批量修改。
答:NGUI 很好的解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,而后修改摄像机的 size 。
注:
答:
SceneManager.LoadScene//加载场景
SceneManager.LoadSceneAsync//异步加载场景
答:一、表面着色器(surface shaders)
一般状况下用户都会使用这种Shader,它能够与灯光、阴影、投影器进行交互。表面着色器的抽象层次比较高,它能够容易地以简洁方式实现复杂的着色器效果。表面着色器可同时正常工做在前向渲染及延迟渲染模式下。表面着色器以句Cg/HLsL语言进行编写。
二、顶点和片断着色器(Vertex and fragment Shaders)
若是须要一些表面着色器没法处理的酷炫效果,或者编写的Shader不须要与灯光进行交互,或是想要的只是全屏图像效果,那么能够使用顶点和片断着色器。这种Shader能够很是灵活地实现须要的效果,可是须要编写更多的代码,而且很难与Unity的渲染管线完美集成。顶点和片断着色器一样是用Cg/HLsL语言来编写。
三、固定功能管线着色器(Fixed Function Shaders)
若是游戏要运行在不支持可编程管线的老旧硬件上,那么须要编写这种Shader了。固定功能管线着色器能够做为片断或表面着色器的备用选择,这在当硬件没法运行那些酷炫Shader的时候,还能够经过固定功能管线着色器来绘制出一些基本的内容。固定功能管线着色器彻底以ShaderLab语言编写,相似于微软的Effects或是Nvidia的CgFX。
答:UI纹理不须要强制使用2次幂,以NGUI举例,NGUI会制做图集,图集是2次幂的。
答:
碰撞器(Collider)有碰撞效果,IsTrigger=false,能够调用OnCollisionEnter/Stay/Exit函数
触发器(Trigger)没有碰撞效果,isTrigger=true,能够调用OnTriggerEnter/Stay/Exit函数
答:TCP是基于链接的,UDP基于无链接的
TCP对系统资源的要求多,UDP较少
UDP程序结构较简单
TCP是面向流数据的,UDP是数据报
TCP保证数据正确性,UDP可能丢包。
TCP保证数据的顺序,UDP不保证。
答:这是由于服务段的LISTEN状态下的SOCKET当收到SYN报文的创建请求后,它能够把ACK和SYN(ACK起应答做用,而SYN起同步做用)放在一个报文里来发送。但关闭链接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你全部的数据都所有发送给对方了,因此你未必会立刻关闭SOCKET,也即你可能还须要发送一些数据给对方以后,再发送FIN报文给对方来表示你赞成如今能够关闭链接了,因此它这里的ACK报文和FIN报文多数状况下都是分开发的。
答:这是由于虽然双反都赞成关闭链接了,并且握手的4个报文也都协调和发送完毕,案例能够直接回到CLOSED状态(就比如从SYN_SEND状态到ESTABLISH状态那样);可是由于咱们必需要家乡网络是不可靠的,你没法保证你最后发送的ACK报文会必定被对方收到,所以对方处于LASK_ACK状态下的SOCKET可能会由于超时未收到ACK报文,而重发FIN报文,因此这个TIME_WAIT状态的做用就是来重发可能都是的ACK报文。
答:角色控制器中Move和SimpleMove函数都是用于实现角色游戏对象移动的函数,它们的区别在于当咱们在每一帧调用SimpleMove函数时,引擎将为该角色控制器对象添加一个重力,而Move函数则不会添加剧力,须要咱们经过代码去实现重力的效果。
答:游戏引擎是指一些已经编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各类编写游戏所须要的各类工具,其目的在于让游戏设计者能容易和快速地作出游戏程序而不用由零开始。大部分都支持多种操做系统平台,如Linux、Mac OS、微软Windows。游戏引擎包含如下系统:渲染引擎(即“渲染器”,含二维图像引擎和三维图像引擎)、物理引擎、碰撞检测系统、音效、脚本引擎、电脑动画、人工智能、网络引擎以及场景管理。
1.Editor
Editor文件夹能够在根目录下,也能够在子目录里,只要名子叫Editor就能够。好比目录:/xxx/xxx/Editor 和 /Editor 是同样的,不管多少个叫Editor的文件夹均可以。Editor下面放的全部资源文件或者脚本文件都不会被打进发布包中,而且脚本也只能在编辑时使用。通常呢会把一些工具类的脚本放在这里,或者是一些编辑时用的DLL。 好比咱们如今要作相似技能编辑器,那么编辑器的代码放在这里是再好不过了,由于实际运行时咱们只须要编辑器生成的文件,而不须要编辑器的核心代码。
2.Editor Default Resources
Editor Default Resources注意中间是有空格的,它必须放在Project视图的根目录下,若是你想放在/xxx/xxx/Editor Default Resources 这样是不行的。你能够把编辑器用到的一些资源放在这里,好比图片、文本文件、等等。它和Editor文件夹同样都不会被打到最终发布包里,仅仅用于开发时使用。
3.Gizmos
我以为这个文件夹其实没什么用处,以下代码所示它能够在Scene视图里给某个坐标绘制一个icon。它的好处是能够传一个Vecotor3 做为图片显示的位置。
4.Plugins
若是作手机游戏开发通常 andoird 或者 ios 要接一些sdk 能够把sdk依赖的库文件 放在这里,好比 .so .jar .a 文件。这样打完包之后就会自动把这些文件打在你的包中。
5.Resources
能够在根目录下,也能够在子目录里,只要名子叫Resources就能够。好比目录:/xxx/xxx/Resources 和 /Resources 是同样的,不管多少个叫Resources的文件夹均可以。Resources文件夹下的资源无论你用仍是不用都会被打包进.apk或者.ipa
Resource.Load :编辑时和运行时均可以经过Resource.Load来直接读取。
Resources.LoadAssetAtPath() :它能够读取Assets目录下的任意文件夹下的资源,它能够在编辑时或者编辑器运行时用,它可是它不能在真机上用,它的路径是”Assets/xx/xx.xxx” 必须是这种路径,而且要带文件的后缀名。
AssetDatabase.LoadAssetAtPath():它能够读取Assets目录下的任意文件夹下的资源,它只能在编辑时用。它的路径是”Assets/xx/xx.xxx” 必须是这种路径,而且要带文件的后缀名。
我以为在电脑上开发的时候尽可能来用Resource.Load() 或者 Resources.LoadAssetAtPath() ,假如手机上选择一部分资源要打assetbundle,一部分资源Resource.Load().那么在作.apk或者.ipa的时候 如今都是用脚原本自动化打包,在打包以前 能够用AssetDatabase.MoveAsset()把已经打包成assetbundle的原始文件从Resources文件夹下移动出去在打包,这样打出来的运行包就不会包行多余的文件了。打完包之后再把移动出去的文件夹移动回来。
6. StreamingAssets
这个文件夹下的资源也会全都打包在.apk或者.ipa 它和Resources的区别是,Resources会压缩文件,可是它不会压缩原封不动的打包进去。而且它是一个只读的文件夹,就是程序运行时只能读不能写。它在各个平台下的路径是不一样的,不过能够用Application.streamingAssetsPath 它会根据当前的平台选择对应的路径。
有些游戏为了让全部的资源所有使用assetbundle,会把一些初始的assetbundle放在StreamingAssets目录下,运行程序的时候在把这些assetbundle拷贝在Application.persistentDataPath目录下,若是这些assetbundle有更新的话,那么下载到新的assetbundle在把Application.persistentDataPath目录下原有的覆盖掉。
由于Application.persistentDataPath目录是应用程序的沙盒目录,因此打包以前是没有这个目录的,直到应用程序在手机上安装完毕才有这个目录。
StreamingAssets目录下的资源都是不压缩的,因此它比较大会占空间。
http://www.xuanyusong.com/archives/3229