2017-05-23 14:16:14 m0_37283423 阅读数 1326
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

前段时间总结了下GPU方面的优化,现在来谈谈优化部分Memory,其主要会包括以下方面,之后会不断完善

Unity3D内部的内存

Mono的托管内存

引入的DLL或者第三方DLL所需要的内存

     . . . . . 

进入主题

       上面只是给出了Memory一些方重要的面的优化,之后还会不断对其进行补充。首先我们要讲的是Unity3d的内部内存的优化!
        其主要包括以下方面:
        1.Texture
        2.Mesh
        3.Mode
        4.Audio
        5.Particle
        6.Physics
        7.NGUI
       
        Texture:
         首先当你导进资源时不需要设置压缩模式,把那个勾去掉就OK,做法如图所示:
       
      然后你也可以去掉那个生成MipMaps,虽然它对GPU的显存带宽有所优化,但是会约增加33%的内存开销,一般来说2D游戏的话,所有都不需要勾上,具有3D性质的贴图,我们都需要勾选上那个生成MipMaps具体图和选择看自己的游戏需求!
      最后根据不同平台来选择不同压缩格式的纹理!笔者在这里就介绍Phone端,PC端以及Web,这里主要关注所占内存的大小!
      对于Android选择ETC压缩格式的纹理更好,好在可以节省内存和读取速度快,但是会有所降低图像质量。
       android设备就没有那么好的运气了。由于硬件平台不统一,每个厂商的GPU可能使用不同的纹理压缩格式。所以还是老老实实用PNG比较好。大部分的                Android设备都支持ETC1格式,它也是受OpenGL ES 2.0标准支持的。ETC1不支持Alpha通道,但可以采用一些方法来处理:ETC 纹理压缩和 Alpha 通道          处理 « Mali 开发人员中心 。ETC2支持Alpha通道,但需要 OpenGL ES 3.0标准 支持。但由于硬件平台不统一,每个厂商的GPU可能使用不同的纹理压缩         格式,极少数的GPU甚至对ETC格式支持有问题。所以在Android设备上,目前可以采用ETC1或者PNG/JPEG格式。
       对于IOS选择使用 PVRTC压缩格式的 纹理可以节省大量内存和读取速度快,但是会有所降低图像的质量。
        pvr是iOS设备的图形芯片 PowerVR 图形 支持的专用压缩纹理格式。
      对于PC选择使用DXT压缩格式的纹理可以节省大量内存和读取速度快,但是会有所降低图像的质量。
      对于Web端跟上面一样!
      具体详情可以看下Unity圣典,连接地址:http://game.ceeger.com/Manual/Textures.html.
      

       Mesh:
      这里就讲讲合并网格和压缩网格吧,下面给出代码:
    网格合并
[csharp] view plain copy
  1. <span style="font-family:Comic Sans MS;font-size:12px;color:#660000;">using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class CombineMeshes : MonoBehaviour  
  5. {  
  6.     void Start()  
  7.     {  
  8.         MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();  
  9.         CombineInstance[] combine = new CombineInstance[meshFilters.Length];  
  10.         int i = 0;  
  11.         while (i < meshFilters.Length)  
  12.         {  
  13.             combine[i].mesh = meshFilters[i].sharedMesh;  
  14.             combine[i].transform = meshFilters[i].transform.localToWorldMatrix;  
  15.             meshFilters[i].gameObject.SetActive(false);  
  16.             i++;  
  17.         }  
  18.   
  19.         transform.GetComponent<MeshFilter>().mesh = new Mesh();  
  20.         transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);  
  21.         transform.gameObject.SetActive(true);  
  22.     }  
  23. } </span>  
[csharp] view plain copy
  1. <span style="font-family:Comic Sans MS;font-size:12px;color:#660000;">using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEditor;  
  4.   
  5. public class EditorTools : MonoBehaviour  
  6. {  
  7.   
  8.     [MenuItem("Tools/Save Combine Mesh")]  
  9.     public static void SaveMesh()  
  10.     {  
  11.         Mesh m = Selection.activeGameObject.GetComponent<MeshFilter>().sharedMesh;  
  12.         AssetDatabase.CreateAsset(m, "Assets/tmp/cmbMesh.asset");  
  13.         AssetDatabase.SaveAssets();  
  14.     }  
  15. }  
  16. </span>  
      压缩网格:
      网格和导入的动画剪辑可以被压缩因此它们占去少的空间在你的游戏文件里。压缩可以开启在网格导入设置里,网格和动画压缩使用量化,这意味着它占用少的空间但压缩可能引入一些不准确度。得看你的模型实现什么样的压缩级别是可以接受的。请注意,网格压缩只处理小型数据文件,并不在运行时使用较少的内存。动画关键帧还原生成较小的数据文件和在运行时使用较少的内存,通常你应该总是使关键帧减少。如图所示:
 

网格和动画压缩使用量化,这意味着它占用少的空间但压缩可能引入一些不准确度。为

你的模型实验什么样的压

缩级别是可以接受的。

网格和动画压缩使用量化,这意味着它占用少的空间但压缩可能引入一些不准确度。为

你的模型实验什么样的压

缩级别是可以接受的。


    Mode:
    1.合并使用同贴图的材质球,合并使用相同材质球的Mesh;
  2、角色的贴图和材质球只要一个,若必须多个则将模型离分离为多个部分;
  3、当使用多角色时,将动画单独分离出来;
  4、使用层距离来控制模型的显示距离;
  5、阴影其实包含两方面阴暗和影子,建议使用实时影子时把阴暗效果烘焙出来,不要使用灯光来调节光线阴暗。
  6、少用像素灯和使用像素灯的Shader;
  7、如果硬阴影可以解决问题就不要用软阴影,并且使用不影响效果的低分辨率阴影;
  8、实时阴影很耗性能,尽量减小产生阴影的距离;
  9、允许的话在大场景中使用线性雾,这样可以使远距离对象或阴影不易察觉,因此可以通过减小相机和阴影距离来提高性能;
  10、使用圆滑组来尽量减少模型的面数;
  11、项目中如果没有灯光或对象在移动那么就不要使用实时灯光;
  12、水面、镜子等实时反射/折射的效果单独放在Water图层中,并且根据其实时反射/折射的范围来调整;
  13、碰撞对效率的影响很小,但碰撞还是建议使用Box、Sphere碰撞体;
  14、建材质球时尽量考虑使用Substance;
  15、尽量将所有的实时反射/折射(如水面、镜子、地板等等)都集合成一个面;
  16、假反射/折射没有必要使用过大分辨率,一般64*64就可以,不建议超过256*256;
  17、需要更改的材质球,建议实例化一个,而不是使用公共的材质球;
  18、将不须射线或碰撞事件的对象置于IgnoreRaycast图层;
  19、将水面或类似效果置于Water图层
  20、将透明通道的对象置于TransparentFX图层;
  21、养成良好的标签(Tags)、层次(Hieratchy)和图层(Layer)的条理化习惯,将不同的对象置于不同的标签或图层,三者有效的结合将很方便的按名称、类别和属性来查找;
  22、通过Stats和Profile查看对效率影响最大的方面或对象,或者使用禁用部分模型的方式查看问题到底在哪儿;
  23、使用遮挡剔除(Occlusion Culling)处理大场景,一种较原生的类LOD技术,并且能够“分割”作为整体的一个模型。
      24、骨骼系统不要使用太多;

2017-09-11 19:21:53 pursue16 阅读数 246
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

比如在跑酷游戏当中,人跑到前面去了,后面的人物就要销毁掉,这样就能够保证内存的稳定。所以要动态生成物体。所以得用代码来生成。


通过prefab的门、窗户、地面、墙,将这些搭建起一座房子,将房子保存为prefab。用代码生成多个房子。

void Start () {
		for (int i=0; i<10; i++) {
			GameObject house = (GameObject)GameObject.Instantiate (housePrefab);//这样就克隆了一个房子  用for循环就可以克隆很多个
			//要把prefab房子放到houseprefab里面去
			house.transform.position = new Vector3(-100+i*20,-2,100);
			house.transform.eulerAngles = new Vector3(0,i*10,0);
		}
	}


然后将代码放到main camera里面之后,把prefab物体放到上面,就形成了绑定了



2014-02-05 22:13:42 iboxdb 阅读数 24
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

[b]NoSQL数据库[/b] iBoxDB 支持 Java Android C# .NET Mono Unity3D Xamarin Nashorn Windows Phone

特性: CRUD, 索引, 复合索引, SQL-like查询语言, 事务管理, 并发管理, 内存管理, 数据库热复制, 文件及内存数据库支持, 非结构化数据支持, NoSQL ORM, 高性能, 零配置, 复制运行

[url=http://www.iboxdb.com]iBoxDB for Java Android C# .NET Nashorn Mono Unity3D Xamarin Windows Phone[/url]
2018-01-06 16:36:58 qq_33632356 阅读数 708
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Unity3d笔试题大全
1. [C#语言基础]请简述拆箱和装箱。
答:
装箱操作:
值类型隐式转换为object类型或由此值类型实现的任何接口类型的过程。
1.在堆中开辟内存空间。
2.将值类型的数据复制到堆中。
3.返回堆中新分配对象的地址。
拆箱操作:
object类型显示转换为值类型或从接口类型到实现该接口值类型的过程。
1.判断给定类型是否是装箱时的类型。
2.返回已装箱实例中属于原值类型字段的地址。
2. [.NET(C#)] attribute,property,markup,tap翻译
答:attribute翻译成特性,用来标识类,方法 。
property翻译为属性,性质用于存取类的字段 。
markup翻译成标记。
tag翻译成标签。
3. [.NET(C#)] 程序集的重要特性
答:程序集的一个重要特性是它们包含的元数据描述了对应代码中定义的类型和方法。
4. [.NET(C#)] ref与out关键字
答:ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。
5. [.NET(C#)] new 关键字用法。
答:1) new 运算符 :用于创建对象和调用构造函数。
2) new 修饰符 :用于向基类成员隐藏继承成员。
3) new 约束 :用于在泛型声明中约束可能用作类型参数的参数的类型。
6. [.NET(C#)] C#中,string str = null 与 string str = “”,说明区别。
答:string str = “” 初始化对象分配空间。
string str = null 表示一个空引用,没有占用空间。//实际情况是,string为null时依然为”“,但该题常考。
7. [.NET(C#)]什么是序列化?
答:序列化是将对象状态转换为可保持或传输的格式的过程。 与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
8. [.NET(C#)] sealed 修饰符有什么特点
答:
1) sealed 修饰符可以应用于类、实例方法和属性。密封类不能被继承。密封方法会重写基类中的方法,但其本身不能在任何派生类中进一步重写。当应用于方法或属性时,sealed 修饰符必须始终与 override一起使用。
2) 将密封类用作基类或将 abstract 修饰符与密封类一起使用是错误的。
3) 结构是隐式密封的;因此它们不能被继承。
9. [.NET(C#)] 详述.NET里class和struct的异同。
答:
相同点:
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。
10. [.NET(C#)]如何选择结构还是类。
答:1) 堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些。
2) 结构表示如点、矩形和颜色这样的轻量对象。例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。
3) 在表现抽象和多级别的对象层次时,类是最好的选择。
4) 大多数情况下该类型只是一些数据时,结构时最佳的选择。
11. [.NET(C#)]抽象类(abstract class)和接口(interface)的区别。
答:
抽象类:
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) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。
12. [.NET(C#)]什么叫应用程序域?
答:1) 操作系统和运行库环境通常会在应用程序间提供某种形式的隔离。
2) 应用程序域为安全性、可靠性、版本控制以及卸载程序集提供了隔离边界。
3) 应用程序域可以理解为一种轻量级进程。起到安全的作用。占用资源小。
13. [.NET(C#)]什么是强类型?
答:为所有变量指定数据类型称为“强类型”。C#是强类型语言。
14. [.NET(C#)]托管代码。
答:使用基于公共语言运行库的语言编译器开发的代码称为托管代码;托管代码具有许多优点,例如:跨语言集成、跨语言异常处理、增强的安全性、版本控制和部署支持、简化的组件交互模型、调试和分析服务等。
15. [.NET(C#)]什么是CTS?
答:CTS:通用系统类型 Common Type System。所有.NET语言共享这一类型系统,实现它们之间无缝的互操作。该方案还提供了语言之间的继承性。
16. [.NET(C#)]什么是CLR?
答:CLR:公共语言运行库 Common Language Runtime。是一个运行时环境,它负责资源管理(内存分配和垃圾收集),并保证应用和底层操作系统之间必要的分离。
17. [.NET(C#)]什么是CLS?
答:CLS:公共语言规范 Common Language Specification。可以保证C#组件与其他语言组件间的互操作性。
18. [.NET(C#)]什么是委托?
答:1) 委托是一种引用方法的类型。
2) 委托类似于 C++ 函数指针,但它是类型安全的。
3) 委托允许将方法作为参数进行传递。
4) 委托可用于定义回调方法。
19. [.NET(C#)]活动目录的作用。
答:1) Active Directory存储了有关网络对象的信息,并且让管理员和用户能够轻松地查找和使用这些信息。
2) Active Directory使用了一种结构化的数据存储方式,并以此作为基础对目录信息进行合乎逻辑的分层组织。
20. [.NET(C#)]在.NET中,配件的意思。
答:程序集(中间语言,源数据,资源,装配清单)。
21. [.NET(C#)]值类型和引用类型的区别。
答:1) 值类型通常被分配在栈上,它的变量直接包含变量的实例,使用效率比较高。
2) 引用类型分配在托管堆上,引用类型的变量通常包含一个指向实例的指针,变量通过该指针来引用实例。
3) 一个是值COPY,一个是地址COPY。
值类型
引用类型
内存分配地点
分配在栈中
分配在堆中
效率
效率高,不需要地址转换
效率低,需要进行地址转换
内存回收
使用完后,立即回收
使用完后,不是立即回收,等待GC回收
赋值操作
进行复制,创建一个同值新对象
只是对原有对象的引用
函数参数与返回值
是对象的复制
是原有对象的引用,并不产生新的对象
类型扩展
不易扩展
容易扩展,方便与类型扩展
22. [.NET(C#)].NET中的垃圾回收机制。
答:.NET Framework 的垃圾回收器管理应用程序的内存分配和释放。每次使用 new 运算符创建对象时,运行库都从托管堆为该对象分配内存。只要托管堆中有地址空间可用,运行库就会继续为新对象分配空间。但是,内存不是无限大的。最终,垃圾回收器必须执行回收以释放一些内存。垃圾回收器优化引擎根据正在进行的分配情况确定执行回收的最佳时间。当垃圾回收器执行回收时,它检查托管堆中不再被应用程序使用的对象并执行必要的操作来回收它们占用的内存。
23. [.NET(C#)]什么是索引器?如何使用索引器?
答:索引器允许类或结构的实例按照与数组相同的方式进行索引。索引器类似于属性,不同之处在于它们的访问器采用参数。可以用任意类型索引。
1) 索引器使得对象可按照与数组相似的方法进行索引。
2) get 访问器返回值。set 访问器分配值。
3) this 关键字用于定义索引器。
4) value 关键字用于定义由 set 索引器分配的值。
5) 索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。
6) 索引器可被重载。
7) 索引器可以有多个形参,例如当访问二维数组时。
24. [.NET(C#)]进程和线程的区别。
答:1) 进程是系统进行资源分配和调度的单位。
2) 线程是CPU调度和分派的单位。
3) 一个进程可以有多个线程,这些线程共享这个进程的资源。

[.NET(C#)]启动一个线程是用run()还是start()?
答:启动一个线程是调用start()方法,导致操作系统将当前实例的状态更改为ThreadState.Running。
[.NET(C#)]构造器Constructor是否可被override(重写)?
答:构造器Constructor不能被继承,因此不能重写override,但可以被重载Overloade。
[.NET(C#)]静态成员和抽象类
答:静态成员override、virtual 或 abstract。
抽象类不能是密封的sealed或静态的static。
[.NET(C#)]在C#中using和new这两个关键字有什么意义。
答:using 关键字有两个主要用途:
1) 作为指令,用于为命名空间创建别名或导入其他命名空间中定义的类型。
2) 作为语句,用于定义一个范围,在此范围的末尾将释放对象。
new 关键字:新建实例或者隐藏父类方法
[.NET(C#)].NET的错误处理机制。
答:.NET错误处理机制采用try->catch->finally结构。 throw
发生错误时,层层上抛,直到找到匹配的catch为止。
[.NET(C#)]error和exception有什么区别。
答:error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。
不可能指望程序能处理这样的情况。
exception 表示一种设计或实现问题。
也就是说,它表示如果程序运行正常,从不会发生的情况。
[.NET(C#)]UDP连接和TCP连接的异同。
答:1) TCP(Transmission Control Protocol)传输控制协议:一种面向连接的、可靠的、基于字节流的运输层通信协议,三次握手。
2) UDP(User Datagram Protocol)用户数据报协议:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点。缺点是易丢失数据包。
[.NET(C#)]System.String 和System.StringBuilder有什么区别?
答:1) System.String是不可变的字符串。
2) System.StringBuilder存放了一个可变的字符串,并提供一些对这个字符串修改的方法。
3) String类在执行字符串拼接的操作上,用“+”会产生新的对象,占用内存。
4) StringBuilder类只是修改字符串的内容,不建立新的对象。
[.NET(C#)]const和readonly有什么区别?
答:1) const 字段只能在该字段的声明中初始化。
2) 不允许在常数声明中使用 static 修饰符。
3) readonly 字段可以在声明或构造函数中初始化。因此,根据所使用的构造函数,readonly 字段可能具有不同的值。
4) 另外,const 字段是编译时常数,而 readonly 字段可用于运行时常数。
[.NET(C#)]C#中的委托是什么?事件是不是一种委托?
答:委托可以把一个方法作为参数代入另一个方法。
委托可以理解为指向一个函数的引用。
事件是一种特殊的委托。
[.NET(C#)]什么是受管制的代码?
答:在类型或成员的声明中使用 unsafe 修饰符。因此,类型或成员的整个正文范围均被视为不安全上下文,无法由 CLR 进行验证的代码。
[.NET(C#)]面向对象语言三大特性。
答:封装、继承、多态。
[.NET(C#)]能用foreach遍历访问的对象需要实现什么接口或声明什么方法的类型。
答:声明IEnumerable接口或实现GetEnumerator()方法。
[.NET(C#)]接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
答:接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
[.NET(C#)]是否可以继承String类?
答:String类是sealed类故不可以继承。
[.NET(C#)]数组有没有length()这个方法? String有没有length()这个方法?
答:数组、String类都没有Length()方法,它们只有Length属性。
[.NET(C#)]成员变量和成员函数前加static的作用。
答:即使没有创建类的实例,也可以调用该类中的静态方法、字段、属性或事件。如果创建了该类的任何实例,不能使用实例来访问静态成员。静态成员通常用于表示不会随对象状态而变化的数据或计算。
[.NET(C#)]什么是虚函数?什么是抽象函数?
答:1) 虚函数:没有实现的,可由子类继承并重写的函数。
2) 抽象函数:规定其非虚子类必须实现的函数,必须被重写。
[.NET(C#)]C#中的三元运算符是?
答:?:。格式如下:ndition ? first_expression : second_expression。
[.NET(C#)]当整数a赋值给一个object对象时,整数a将会被?
答:装箱。
[.NET(C#)]委托声明的关键字是?
答:delegate.
[.NET(C#)]在.Net中所有可序列化的类都被标记为?
答:[Serializable]
[.NET(C#)]利用operator声明且仅声明了==,有什么错误么?
答:要同时修改Equale和GetHash() ? 重载了”==” 就必须重载 “!=”。
[智力题] 62-63=1 等式不成立,请移动一个数字(不可以移动减号和等于号),使得等式成立,如何移动?
答:62移动成2的6次方,26。
[.NET(C#)]C#可否对内存进行直接的操作?
答:可以使用指针。也就是非安全代码,就是不在 CLR 完全控制下执行的代码,它有可能会导致一些问题,因此他们必须用 “unsafe” 进行表明。
[.NET(C#)] &和&&的区别。
&是位运算符,表示按位与运算。
&&是逻辑运算符,表示逻辑与(and)
[.NET(C#)]重载的方法是否可以改变返回值的类型?
可以。
[.NET(C#)]如何把一个Array复制到ArrayList里?
(1) 实现1
string[] s ={ “111”, “22222” };
ArrayList list = new ArrayList();
list.AddRange(s);
(2)实现2
string[] s ={ “111”, “22222” };
ArrayList list = new ArrayList(s);
[.NET(C#)]什么是强名?
强名是由程序集的标识加上公钥和数字签名组成的,其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。它使用对应的私钥从程序集文件中生成。(程序集文件包含程序集清单,其中包含组成程序集的所有文件的名称和哈希。)
[.NET(C#)]C#中几种循环的方法,并指出他们的不同:
for:使用于确定次数的循环。
foreach:使用于遍历的元素是只读的。//Unity中此处是个坑,建议不要用foreach
while:次数不确定,条件随机变化。
do…while:次数不确定,条件随机变化,但至少要保证能被执行一次。
[.NET(C#)]请简述一下用Socket进行同步通讯编程的详细步骤
在应用程序和远程设备中使用协议和网络地址初始化套接字。
在应用程序中通过指定端口和地址建立监听。
远程设备发出连接请求。
应用程序接受连接产生通信scoket。
应用程序和远程设备开始通讯(在通讯中应用程序将挂起直到通讯结束)。
通讯结束,关闭应用程序和远程设备的Socket回收资源。
[.NET(C#)] try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在return前执行。
[.NET(C#)] 写出程序的输出结果:
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

[.NET(C#)]求以下表达式的值,写出您想到的一种或几种实现方法:1 - 2 + 3 - 4 +……+ m
答案:
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 );
}

[.NET(C#)]两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
答:不对,有相同的hash code。
[.NET(C#)] swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
答案:可以作用在byte和long上,也可以作用在string上。
[.NET(C#)] short s1 = 1; s1 = s1 + 1;有什么错?short s1 = 1; s1 += 1;有什么错?
答: 1. short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能隐式转化为short型。可修改为s1 =(short)(s1 + 1) 。
short s1 = 1; s1 += 1正确。
[.NET(C#)] 字符串处理问题
题目:需要实现对一个字符串的处理,首先将该字符串首尾的空格去掉,如果字符串中间还有连续空格的话,仅保留一个空格,即允许字符串中间有多个空格,但连续的空格数不可超过一个。
答案:
string inputStr = ” xx xx “;
inputStr = Regex.Replace( inputStr.Trim(), @”/s+”, ” ” );
[.NET(C#)]下面这段代码输出什么?为什么?
int i = 5;
int j = 5;
if( Object.ReferenceEquals( i, j ) )
Console.WriteLine( “Equal” );
else
Console.WriteLine( “Not Equal” );
答案:Not Equal。因为比较的是对象
[.NET(C#)] public static const int A=1;这段代码有错误么?是什么?
答:const不能用static修饰。
[.NET(C#)]下面的代码中有什么错误吗?
class A

{

public virtual void F()

{

Console.WriteLine( “A.F” );

}

}

abstract class B : A

{

public abstract override void F();//abstract与override关键字可以同时使用

}

答案:没有错误!可以通过编译器。
注意:网上有资料说abstract与override关键字不可以同时使用,这种说法是错误的 !
66. [.NET(C#)] 以下是一些C#中的枚举型的定义,其中错误的用法有?
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
67. [.NET(C#)] 下面的例子中产生的输出结果是什么?
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
68. [.NET(C#)] 写出程序的输出结果
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()。
69. [.NET(C#)] 写出程序的输出结果
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()

[C#语言基础]简述string与StringBuilder相比的优点。
答:
string的字符串为常量不可修改。
1.可以满足字符串常量池的需要。即对于创建相同文本时,string为同一对象。
2.允许string对象缓存HashCode。字符串不变形保证了hash码的唯一性。
3.安全性,string被许多的类库用来当做参数。
StringBuilder实际是一个char类型的集合,完成了组装拼接等工作。
String更适合做程序的参数,StringBuilder用于做String类型的组装。
[C#语言基础]C#StringBuilder类型比string类型的优势是什么?
答:
StringBuilder的优势在于拼接字符串。
//String的优势在于对字符串做一些处理,在使用过程中看具体的需求。
[C#语言基础]编写程序判断整数46234的每位相加和。
答:
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

2020-03-31 20:01:44 wuming2016 阅读数 38
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

NativeContainer

        安全系统复制数据过程的缺点在于,它还会隔离每个副本中的Job结果。为了克服此限制,您需要将结果存储在一种称为NativeContainer的共享内存中(所谓共享的意思是主线程和各个Job都能访问)。

       关于NativeContainer,unity有代码级的文档,https://docs.unity3d.com/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerAttribute.html
建议先看本文,先了解概念,再看代码级的文档。

什么是NativeContainer?

NativeContainer是一种托管值类型,为本地内存提供相对安全的C#包装器(wrapper)。它包含一个指向非托管分配的指针。与Unity C#作业系统一起使用时,NativeContainer允许Job访问与主线程共享的数据,而不是使用副本。【个人觉得是为了性能,认同的点赞

可用的NativeContainer类型是什么?

Unity附带了一个NativeContainer称为NativeArray的东西。您还可以NativeArray使用NativeSlice操纵,以NativeArray从特定位置到特定长度获取的子集。

注意:ECS包扩展了Unity.Collections名称空间,以包括其他类型的NativeContainer:

  • NativeList-可调整大小NativeArray。
  • NativeHashMap -键和值对。
  • NativeMultiHashMap -每个键有多个值。
  • NativeQueue- 先进先出(FIFO)队列。
  • NativeContainer和安全系统

安全系统内置于所有NativeContainer类型中。它跟踪对任何对象的读写操作NativeContainer。

注意:所有关于NativeContainer类型的安全检查(例如越界检查,解除分配检查和竞争条件检查)仅在Unity Editor和Play Mode中可用。

此安全系统的一部分是DisposeSentinel和AtomicSafetyHandle。DisposeSentinel如果没有正确释放内存,检测到内存泄漏并给您一个错误。触发内存泄漏错误发生在泄漏发生很长时间之后。

使用AtomicSafetyHandle来转移NativeContainerin代码的所有权。例如,如果两个安排的Job正在写入同一作业NativeArray,则安全系统将引发异常,并显示一条清晰的错误消息,以解释原因以及如何解决该问题。当您安排(schedule)有问题的Job时,安全系统将引发此异常。

在这种情况下,您可以安排具有依赖项的Job。第一个作业可以写入NativeContainer,一旦完成执行,下一个Job就可以安全地对其进行读写NativeContainer。从主线程访问数据时,读取和写入限制也适用。安全系统确实允许多个Job并行地从同一数据读取。

默认情况下,当Job对NativeContainer有权访问时,它同时具有读和写访问权限。此配置可能会降低性能。C#Job System不允许您同时安排(schedule)两个Job,其两个Job都对同一个NativeContainer写入访问权限。

如果Job不需要写入NativeContainer,请用[ReadOnly]属性标记,如下所示:

[ReadOnly]
public NativeArray<int> input;

在上面的示例中,您可以与其他同时执行的Job只读访问NativeArray。

注意:无法防止从Job内部访问静态数据。访问静态数据会绕过所有安全系统,并可能使Unity崩溃。有关更多信息,请参见《C#Job System提示和故障排除》。

NativeContainer内存分配器

创建NativeContainer,必须指定所需的内存分配类型。分配类型取决于Job运行的时间长短。这样,您可以调整分配器以在每种情况下获得最佳性能。NativeContainer有三种用于内存分配和释放的内存分配器(Allocator)。当实例化NativeContainer,需要指定适当的一个。

  • Allocator.Temp
    分配最快。它用于寿命不超过一帧的分配。您不应该将NativeContainer分配使用传递Temp给作业。Dispose从方法调用返回之前,还需要先调用该方法(例如MonoBehaviour.Update或从本机代码到托管代码的任何其他回调)。
  • Allocator.TempJob
    分配Temp速度比慢,但比快Persistent。它用于在四个帧的生命周期内进行分配,并且是线程安全的。如果Dispose在四帧之内没有收到警告,则控制台会输出一条从本机代码生成的警告。大多数小型Job使用此分配类型。
  • Allocator.Persistent
    是最慢的分配,但是可以持续到您需要的时间,并且在整个应用程序的生命周期中(如果需要)。它是直接调用malloc的包装。较长的Job可以使用此分配类型。您不应在性能至关重要的地方使用Persistent

    举个栗子
     
  • NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

    注意:上例中的数字1表示NativeArray的大小。在这种情况下,它只有一个数组元素(因为它仅在result中存储一个数据)。

Unity3d优化总结篇

阅读数 509

MaterialPropertyBlock

阅读数 2521

Unity3D面试题

阅读数 19

没有更多推荐了,返回首页