0%

有哪些优化指标

项目的优化直接影响着应用的使用体验。首先我们需要选择一些指标来作为优化目标:

  • 运行时指标:帧率FPS是我们最常接触,也是体验最明显的性能指标。一个项目15帧基本上是不能用的状态,30帧勉强能用,能做到60帧则会让用户体验有极大的提高。另一方面,运行时内存大小也十分重要,考虑到移动平台内存条件有限,过大的内存占用很容易造成杀后台和进程崩溃。
  • 离线指标:Unity为了尽可能适配所有类型的资产,提供了丰富繁杂的资产导入设置。然而为了普适性,其中很多默认设置存在性能、存储大小、内存大小等方面的浪费,因此如何优化好一个资产的离线设置也对项目很有帮助。另一方面,减小包体大小对于项目的分发也有所帮助,毕竟没有人愿意动不动就下1G的APP。

下面从离线资产优化开始介绍。

阅读全文 »

参考Game Programming Patterns完成的设计模式总结笔记。

命令模式

命令模式本质上希望把一个硬编码的函数解耦成可配置的函数命令,尽可能将功能触发具体功能分离。

如下有一个玩家对象的输入控制功能,其中按下X键对应jump动作。如果我们想要将X键绑定到fireGun功能,那还得去代码里修改对应的硬编码if语句,然后重新编译,重新链接。

1
2
3
4
5
6
7
void InputHandler::handleInput()
{
if (isPressed(BUTTON_X)) jump();
else if (isPressed(BUTTON_Y)) fireGun();
else if (isPressed(BUTTON_A)) swapWeapon();
else if (isPressed(BUTTON_B)) lurchIneffectively();
}
阅读全文 »

点云空间学习

PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation

  • Qi C R, Su H, Mo K, et al. Pointnet: Deep learning on point sets for 3d classification and segmentation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 652-660.

PointNet首次基于原始点云进行深度学习,其提出了点云深度学习的三大原则: 无序性、点间联系、变换一致性。基于此, PointNet在点云上逐点运用了MLP进行变换, 并且构造了T-Net进行对抗点云的仿射变换, 最终使用max pool进行对称聚合。

缺少对局部结构的特征学习

PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space

  • Qi C R, Yi L, Su H, et al. Pointnet++: Deep hierarchical feature learning on point sets in a metric space[J]. Advances in neural information processing systems, 2017, 30.

PointNet没有捕捉到点的局部结构特征,限制了细粒度和复杂场景的识别、泛化能力。PointNet++则引出了一个set abstraction层对点云进行多级学习。set abstraction定义了多级多块的局部邻域结构, 其在每一个局部邻域中都使用了mini-PointNet来进行特征抽取。然而由于点云是非均匀分布的, 不同的局部邻域的密度不一样, 因此PointNet++提出了两种自适应密度的特征融合模块: Multi-scale grouping(MSG)Multi-resolution grouping(MRG)

另外由于部位分割等任务最终需要输出逐点的特征标签, 因此在set abstraction之后, Pointnet++一方面在同一级内进行反距离的插值传播, 另一方面自顶向下进行反向逐级的特征传播。在同一层内对两种传播特征进行拼接, 即得到该层的逐点特征。

阅读全文 »

机制

委托

委托类似于函数指针:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//定义委托类型 / 定义函数指针类型
delegate void MyDelegateType(int a);

//根据类型创建实例对象
MyDelegateType my_delegate_instance=new ();
//注册指向函数
my_delegate_instance+=Func1;
my_delegate_instance+=Func2;
my_delegate_instance+=Func3;
//删除函数
my_delegate_instance-=Func3;
//唤醒函数
my_delegate_instance.Invoke(int_variable);
my_delegate_instance(int_variable);

在我们定义委托类型时,本质上编译器会生成一个继承自标准库的类,如下所示。这个类实际上会形成一个委托的闭包,其会包含调用所需的所有信息,如调用实例、待调用方法的位置。

1
2
3
4
5
6
7
8
9
10
11
12
class MyDelegateType :System.MulticastDelegate
{

//一些继承的重要字段
internal Object _target;//当委托注册了实例方法时,这个字段会填充实例对象,以便调用实例方法。
internal IntPtr _methodPtr;//指针,单播时使用,指向那个注册的方法。
private Object _invocationList;//方法链,多播时使用,指向多个单播委托实例。

//唤醒操作
public virtual void Invoke(int a);
//...其余字段和方法
}

对于单播委托,其会在_methodPtr中直接存储方法地址。然而正如上文所示,一个委托可以注册多个方法。实际上在注册多个方法后,C#会生成一个独立的委托实例,用来指向多个单播委托:

阅读全文 »