一.方案选择:

1. 为啥要有路点?

我们的场景是开放的3D场景,赛道设计多种多样,考虑到要获取赛车在赛道上的实时状态,直接从三维空间中获得状态信息是比较困难的。要对赛道本身做适当处理,简化,抽象赛道的功能属性。

2. 一般的赛道属性有哪些?

可行走面,实时朝向,位置,检测点(起点,终点,特殊点)。

3. 使用路点的优点

实现简单:只需要在场景中间布置一系列的点就可以了。
与场景依赖低:无视复杂场景(有中断,不平整,多个Mesh组合)带来的标记复杂性。

4. 使用路点的缺点

无法精准的模拟场景的实际情况:赛道宽度,复杂的交叉情况,一些要求比较高的精准判定等等。

5. 是否有其他替代方案

Read more »

目前网络通信提供的机制

发送消息

1、常规发送消息:

  • NetSys.SendMsg(ESendMsgType type, CSMsgBody body, int cmdID, int seqID)

核心是ESendMsgType,如下所示:

1
2
3
4
5
6
7
public enum ESendMsgType
{
     ReliableMsgToGameSvr,//发送可靠消息也就是所谓的tcp消息到游戏服务器(pvp开局之前的所有消息)
     ReliableMsgToPVPSvr,//发送可靠消息也就是所谓的可靠udp消息到pvp服务器(开始游戏后的比如得分、进球等消息)
     UnReliableMsgToPvpSvr,//发送不可靠消息也就是所谓的udp消息到pvp服务器(同步用的那些关键信息)
}

在调用的时候指定好对应的type类型。

2、包含等待回复的发送消息流程:

1
ReconnectSys.SendGyaranteedMsg(ESendMsgType type , int sendMsgId, CSMsgReqBody sendMsg , int receiveMsgId , DMsgReceiveCallback callback )

这个函数目前仅规定于在跟游戏服务器通信的时候使用,调用这个函数,需要指定对应消息的回复ID,在内部会等待一个回复时间,如果指定时间内,没有消息回复,就直接弹窗进行重连。
这块目前不需要了,要去掉。

Read more »

1、在上线之前安装包可以正常打开游戏,但是上线Google Play之后,打不开游戏。

原因:在创建Google Play游戏项目的时候,参加了Google Play签名计划,会对上线包进行2次签名。而我们上传的包是用的安全中心加壳的包,会导致找到包资源的情况。

解决办法:

(1)上传一个没有加壳的包(在不打算更改包名等情况下,只能采用这种情况)

(2)在创建Google Play游戏项目的时候不要勾选签名计划

2、国内版本全量(增量)升级可以正常垃圾Android安装界面,海外版的话,在android7.0、8.0的机器会报错,无法拉起

原因:国内版用的target sdk是23(对应android6.0),海外版用的是26(对应android8.0),在android7.0中,Google限制了某些权限,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException

解决办法:

(1)回退target sdk(因为Google Play要求11月份上架的应用都只能是26及以上,所以放弃了)

(2)使用FileProvider的方式来生成一个content://格式的URI

Read more »

1、全民飞机大战

在这里插入图片描述

背景: 服务器无游戏逻辑、所有战斗运算都在客户端

整体架构

客户端单独计算逻辑,将结果同步给对方

TCP:用于命令协议。比如:开始游戏、游戏结算、复活等。

UDP:用于游戏玩法同步。比如:飞机移动、怪物掉血以及死亡、时间轴同步、技能表现同步等。

在这里插入图片描述

网络层

1.Udp socket

Read more »

1、纹理压缩:Unity3D引擎对纹理的处理是智能的,不论你放入的是PNG,PSD还是TGA,它们都会被自动转换成Unity自己的Texture2D格式。Texture2D的设置选项中,可以针对不同的平台,设置不同的压缩格式,如IOS设置成PVRTC4,Android平台设置成RGBA16,
RGBA32等同于原图了,优点是清晰、与原图一致,缺点是内存占用十分大。

目前android上虽然支持ETC1,ETC2,ATITC,S3TC(DXTC),PVRTC这五种压缩格式,IOS上支持的压缩纹理格式比较有限,通常使用pvrtc,pvr有2 bits和4 bits两种格式,由于2 bits在画质上的损失过于严重,所以业界一般使用pvrtc RGBA 4bits格式。Android上ETC1压缩格式不支持Alpha通道,采用Alpha通道分离的方式来解决ETC1不支持Alpha通道的问题,实际上Unity5.3之后,Android平台的默认压缩纹理改为ETC2。

ETC2支持半透明,使用也很方便,不过问题是尚未普及,尤其是低端机是不支持ETC2的。Unity对不支持ETC2的机子,在加载图片的时候会解压为RGBA,不过这样就会造成极大的内存浪费,也会严重影响加载速度。

2、通道分离过程:
(1)将带有Alpha通道的图片,另存为两张图片,一张只存RGB信息,另一张只存Alpha信息。建议保持为图片原目录,名称加后缀”_RGB”和”_Alpha”;

(2)带有Alpha通道的图片,所用的Shader要更新为支持RGB和Alpha信息分别从两张不同图片读取;
Shader Properties里添加Alpha信息图片的输入口:_MainTex为Image上自带的Texture,_AlphaCombineTex为合并图像时传入的Texture,AlphaCombineSpriteMask功能为合并两个Texture,生成最终的带Alpha图片:

在这里插入图片描述

在这里插入图片描述

生成Material时,给Shader传入Alpha单通道图片,即上图中的AlphaCombineTex:

在这里插入图片描述

Read more »

问题1:Log输出频繁导致卡顿

解决方法:Log上封装一层,用宏定义或者一个变量作控制输出开关

**问题2:**在Update函数的for、while循环中反复定义变量

在这里插入图片描述

**解决方法:**把定义放在循环外面

在这里插入图片描述

**问题3:**Update函数或者Update里调用的其他的函数,里面包涵了数组的定义

在这里插入图片描述

建议:放在函数外面定义

在这里插入图片描述

Read more »

一个SIFT关键点拥有三个信息:位置,尺度和方向。前面已经介绍了如何精确定位关键点的位置,通过尺度不变性求极值点,可以使其具有缩放不变的性质。现在来谈谈为特征点指定方向参数,使提取的特征对图像旋转具有不变性,从而实现匹配时图像的旋转无关性。最后,再介绍该用什么样的描述符来表达sift特征。

一、关键点方向分配

SIFT特征的一个关键的特性是旋转不变性,实现旋转不变的基本思想是采用“相对”的概念。利用关键点邻域像素的梯度方向分布特性,我们可以为每个关键点指定方向参数方向。而后面定义的关键点描述特征符是相对于这个主方向的,因而可以实现匹配时图像的旋转无关性。我们通过梯度直方图统计法来确定关键点的方向,即统计以关键点为原点,利用所有在此区域内的像素点的梯度形成一个方向直方图。

具体说来,对于每个特征点P(x,y,δ,σ)所处高斯图像金字塔的δ组σ层图像,其像素点L(x,y)的梯度:(这里的图像是高斯模糊后的图像,非高斯差分图像)

梯度的幅值:

梯度的方向:

直方图的横坐标是梯度方向,共 36 项,每项代表了 10 度的范围;纵坐标是梯度大小,对于归到横坐标上任一项内所有的点,将其梯度大小相加,其和作为纵坐标。下图应该有36项,为了示意只画了8项。(根据Lowe的建议,直方图统计半径采用31.5σ)

Read more »

1.整体设计

在这里插入图片描述

IAnimController接口:

对动画控制器整体行为的抽象。包括动画根节点类型AnimRoot,配置加载LoadStates,状态切换方法EnterState和LeaveState以及更新方法OnUpdate等等。此接口存在的意义在于提供给上层以集合的方式操作多个功能不同的具体动画控制器。

BaseAnimController抽象类:

提供一个通用的动画控制机制,主要功能是通过状态切换当前正在播放的动画。
通过派生于此类的具体的类持有单个Animation组件,并指定AnimRoot类型。每一个Animation节点有独一无二的AnimRoot类型。

一个动画节点可以拥有多个激活状态。调用EnterState方法可以激活一个状态,根据这个状态的优先级不同,行为也不同。如果当前优先级没有激活状态,则该状态直接激活。如果当前优先级有其他状态激活,则会先关闭已激活的此优先级状态,再激活这个状态。

Animation会播放最高优先级的动画,直到最高优先级动画播放完毕,或者主动调用了LeaveState方法,或者调用了同优先级的EnterState方法。

具体的AnimController实现:

具体的Controller在构造时指定AnimRoot类型,并传入一个Animation组件对象来初始化。并调用LoadState从表格加载配置,通过OnUpdate驱动默认的状态逻辑。每个AnimController的具体实现可以根据需要重写基类的方法实现定制逻辑。

Read more »

PoolObjectManager实现了一个简单对象池,对象池用于减少内存开销,其原理就是把可能用到的对象,存在一个地方,用的时候就调出来,不用就放回去。而不是要用的时候创建,不用的时候就销毁。不用的时候隐藏并存储下来即可。

在这里插入图片描述

在这里插入图片描述

Read more »

1.实验内容

分析ucore操作系统的相关源码,主要内容为分析一台计算机(部署了ucore)在加电以后,系统是如何从BIOS程序开始一步步初始化、加载bootloader、加载ucore直至ucore中的应用程序正常运行。

2.实验要求

  • 在报告中给出各个阶段的关键步骤;
  • 对自己理解较深的步骤,可以结合具体的数据结构、算法和ucore的相关源码进行详细分析。

3.ucore操作系统简介

ucore是清华大学计算机系操作系统课的教学实验系统,它基于MIT的XV6,主要的修改是把XV6的实验分成多个更小的实验,实验内容包括代码分析、算法实验和扩展实验,从而适应不同能力的同学都能基于这个系统来进行操作系统课程实验。操作系统—ucore,此“麻雀”包含虚存管理、进程管理、处理器调度、同步互斥、进程间通信、文件系统等主要内核功能,总的内核代码量(C+asm)不会超过 5K 行.充分体现了“小而全”的指导思想。ucore 的运行环境可以是真实的 X86 计算机,不过考虑到调试和开发的方便,我们可采用X86模拟器,比如QEMU、BOCHS等,或X86虚拟运行环境,比如VirtualBox、VMware Player等。ucore的开发环境主要是GCC中的gcc、gas、ld 和MAKE等工具,也可采用集成了这些工具的 IDE 开发环境 Eclipse-CDT。运行环境和开发环境既可以在 Linux 或 Windows中使用。按照一个操作系统的开发过程,我们可以有如下的开发步骤:

  1. 启动操作系统的bootloader,用于了解操作系统启动前的状态和要做的准备工作,了解运行操作系统的硬件支持,操作系统如何加载到内存中,理解两类中断–“外设中断”,“陷阱中断”,内核态和用户态的区别;
  2. 内存管理子系统,用于理解x86分段/分页模式,了解操作系统如何管理物理内存和虚存、页表管理、一类中断-“故障中断”、缺页故障处理、基于页的内存替换;
  3. 进程管理子系统,用于了解进程创建、执行、切换和结束的动态管理过程,了解在用户态通过系统调用得到内核态的内核服务的过程;
  4. 处理器调度子系统,用于理解操作系统的调度过程和调度算法;
  5. 同步互斥子系统,用于了解同步互斥的具体实现以及对系统性能的影响,研究死锁产生的原因,以及如何避免死锁;
  6. 进程间通信子系统:用于了解进程间如何进行信息交换和共享;
  7. 文件系统,了解文件系统的具体实现,与进程管理等的关系,了解缓存对操作系统IO访问的性能改进,了解虚拟文件系统(VFS)、buffer cache和disk driver之间的关系;
  8. 网络协议栈(选做):了解网卡驱动、TCP/IP协议栈实现和Web应用。

4.BIOS启动过程

BIOS就是基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片上的程序,保存着计算机最重要的基本输入输出的程序、系统设置信息、开机后自检程序和系统自启动程序。其主要功能是为x86架构的计算机提供最底层的、最直接的硬件初始化设置和控制。一般来说没安装任何操作系统的计算机成为裸机,但是裸机并不裸,因为有BIOS,所以各种硬件仍然可以在你按下启动按钮之后有序的工作,只是这些工作是不为用户提供服务的。BIOS的基本工作任务包括:

  1. POST:开机自检;
  2. 初始化阶段:对DRAM、芯片组,外围设备等设置;
  3. 保存相应数据:在COMS RAM及BIOS数据区保存相应的数据;
  4. 驻入服务例程:写入中断向量表及BIOS的中断服务例程等。
Read more »