一、问题
最近在做一个unity仿真培训项目的一个回放功能。这个仿真演练项目中,玩家以第一人称视角进行操作,键盘控制移动,通过鼠标点击场景中的物体进行操作。回放功能要求完全再现用户的整个演练过程,类似于魔兽争霸中的录像回放功能。
二、思路
1、录制视频。此方法最省时省事,但是录制视频得到的文件太大,在某些场合不允许(比如在线播放,存储空间受限,用户太多等情况)。
2、记录事件。以触发事件的方式模拟再现用户的行为,这种方法虽然得到的文件较小,但是有可能产生较为严重的偏差,不能完全再现用户的演练过程。
三、我的实验过程。
1、不采取录制视频的方式。
2、使用记录事件保存关键信息存储到txt文件中,程序开始时根据处于的模式来选择是读取回放文件进行驱动还是用户直接操作进行驱动程序的运行。要求在保证偏差在可接受范围内所存储的文件越小越好。知乎上有关于魔兽争霸录像回放的机制分析,挺不错的,还涉及到随机数的产生问题,可以参考下。实验过程及遇到的问题如下:
(1)在文件开始处记录程序版本信息,场景名称等。程序版本使用Applcation.Version,但是只在unity5.x中才有,4.x中只有unityVersion;
(2)每一帧都记录数据,刚开始想记录帧数作为每一帧的开始标志,但是这样做实在是很不理想的方法,既浪费空间又不利于计算及回放文件的移植
(3)记录一些键盘、鼠标按下事件,并将其存储为16进制字母以减少空间占用;
(4)记录unity项目中设置的一些轴值及跳跃触发,在回放时读取这些轴值并对第一人称控制器的控制脚本发送这些数据以实时驱动计算。后来发现在第一人称控制器 的控制脚本中所有的位置移动都和当前的帧率关联,由于回放时Time.deltaTime与用户实际演练操作时对应帧的值不一样,那么这一帧的位置偏移也会产生偏差, 最终因累积效应导致很大的偏差。取消这种关联之后自己添加变量,记录帧的Time.deltaTime,也传递到控制脚本中,发现位置依旧有偏差,但是 要小了许多,问题得不到解 决,故放弃使用这种方法,转而直接记录位置信息,同时取消记录跳跃触发事件,这样回放时位置相当精确。
(5)记录视角变化信息。视角的控制是由第一人称控制器绕Y轴的旋转和摄像机绕x轴旋转叠加而成的,故需要记录两种轴值,此处记录的是欧拉角。刚开始为了减小 占用空间,只保留1位小数,后来考虑到视角的偏差可能导致鼠标位置的偏差,所以取消了保留1位小数位数的操作。至此,玩家的控制基本可以正常记录和回放 了。
(6)记录事件。(待续)