Unity Notes之屏幕触点轨迹的平滑
来源:互联网 发布:mysql怎么打开 编辑:程序博客网 时间:2024/05/16 02:07
最近在做一个移动设备上的触控系统需求,基本的要求点是,通过手指在屏幕上指定区域内的滑动点击来控制一个对象在空间或屏幕上的位置移动。具体的应用场合:
- 通过屏幕点击来精确控制对应的武器光标的位置;
- 得到较为精确且平滑的、用户在屏幕拖拽移动时的拖尾效果;
但是这里边会遇到一个问题,移动设备直接得到的Input中的touch信息其实是有噪声的,这些噪声一方面来自于硬件touch感应设备,另外一些来自于用户自己的操作,而噪声在使用中的表现就是转换后的信号会有较大的jitter现象。比如用来控制一个屏幕上的光标,那么这个光标的位置可能就会一直在抖动。因而如果对信息的平滑度要求过高的话必须得对这些原始的输入信号进行滤波才可以,即在输入的触点信号上施加一个低通滤波器,以便过滤掉其中的高频信息保留较为稳定的低频信息。
为了良好的用户体验,这里对使用的一个较合理的低通滤波器的设计要求如下:
- 低速移动下的误差不能太大,否则用户不能实现精确控制;
- 高速移动下的迟滞不能太大,否则用户感觉系统反应迟钝;
单纯的不考虑速度的低通滤波器(如Unity doc中关于multi touch所提供的低通滤波方法)虽然可以得到平滑的目的,但是却会带来较大的迟滞;所以这里边就涉及到一个对速度的考量,即通过速度来确定需要过滤掉的信号的尺度,而对速度与位置的平滑则直接使用指数平滑(Exponential smoothing)。加上速度判断后,可以针对不同的速度,对滤波的尺度进行不同的设定,从而在快慢速移动时都得到比较优化的效果。结合上述考虑最终实现了一下,得到的效果还是比较理想的(应用实例参考死亡之屋手游版中的武器控制手感)。对应的代码如下:
void LowPassFilter(Vector2 currentPosition, Vector2 currentVelocity, float dt){ if (Mathf.Approximately((currentVelocity - mFilteredVelocity).sqrMagnitude, 0)) { mFilteredVelocity = currentVelocity; } else { mFilteredVelocity = FilterKernel(currentVelocity, mFilteredVelocity, Alpha(Vector2.one, dt)); } if (Mathf.Approximately((currentPosition - mFilteredPosition).sqrMagnitude, 0)) { mFilteredPosition = currentPosition; } else { Vector2 cutoffFrequency; cutoffFrequency.x = mJitterReduction + 0.01f * mLagReduction * Mathf.Abs(mFilteredVelocity.x); cutoffFrequency.y = mJitterReduction + 0.01f * mLagReduction * Mathf.Abs(mFilteredVelocity.y); mFilteredPosition = FilterKernel(currentPosition, mFilteredPosition, ComputeExpSmoothingFactor(cutoffFrequency, dt)); }}Vector2 ComputeExpSmoothingFactor(Vector2 cutoff, float dt){ float tauX = 1 / (2 * Mathf.PI * cutoff.x); float tauY = 1 / (2 * Mathf.PI * cutoff.y); float fX = 1 / (1 + tauX / dt); float fY = 1 / (1 + tauY / dt); fX = Mathf.Clamp(fX, 0, 1); fY = Mathf.Clamp(fY, 0, 1); return new Vector2(fX, fY);}Vector2 FilterKernel(Vector2 current, Vector2 previous, Vector2 expFactor){ float x = expFactor.x * current.x + (1 - expFactor.x) * previous.x; float y = expFactor.y * current.y + (1 - expFactor.y) * previous.y; return new Vector2(x, y);}运行效果动态截图如下(其中的jitterReduction和lagReduction分别设置为1):
其中的蓝色线条为过渡后的轨迹,黄色线条为原始点击的轨迹,圆圈为过滤后的光标位置。
0 0
- Unity Notes之屏幕触点轨迹的平滑
- 屏幕触点
- Unity之DOTweenPath轨迹移动
- 点击iPhone屏幕,大头针落在触点的代码
- 地图轨迹平滑算法
- 轨迹平滑方法
- Unity Notes之控制粒子系统的最大粒子数量
- Unity Notes之Android版本的联机调试备忘
- Unity Notes之配置文件基于内容的差异化更新
- unity之屏幕截图
- unity发射弓箭轨迹的实现
- unity发射弓箭轨迹的实现
- unity发射弓箭轨迹的实现
- unity发射弓箭轨迹的实现
- unity发射弓箭轨迹的实现
- Unity Notes之发布包精简
- Unity Notes之协程(Coroutine)简析
- <Unity笔记>Unity2D游戏的平滑旋转
- lvs介绍
- Java核心技术学习笔记之四——泛型程序设计
- 自组织神经网络介绍:自组织特征映射SOM(Self-organizing feature Map),第一部分
- nyoj 最大岛屿
- Android SQLite是线程安全的吗?
- Unity Notes之屏幕触点轨迹的平滑
- 字号 磅值 像素值的对应关系
- linux下cscope 使用方法
- 【UI】【View】随手指运动的小球
- 分布式消息队列的设计和使用
- Ubuntu下的JDK,Maven环境安装
- 第 1 章 JS 基础语法
- 快速理解Kafka分布式消息队列框架
- UGUI笔记