当前位置: 首页 > news >正文

【Unity优化】优化Android平台拖动地图表现

一、Android平台上拖动不平滑的现象

        团队使用的热更新框架还是比较老的ToLua,拖动地图的逻辑,实现的方案是,在地图上放置一个合适大小的Image组件作为Raycast Target的对象,统一接受和处理跟地图拖动相关的逻辑。        

        在C#层专门建立一个DragManager作为拖动事件管理器,其内部实现了IDragHandler,IPointerDownHandler,IPointerUpHandler,IScrollHandler等EventSystem事件接口。DragManager根据游戏交互的需求,实现了:单指拖动,双指拖动,短按,长按等接口。Lua层注册对应的函数,实现对应的响应时间事件。

        单指拖动地图在Lua层的逻辑为,计算当前次的单指拖动事件在屏幕上的位置,以及上次事件在屏幕上的位置,计算屏幕上的拖动位移。由于我们游戏是2D游戏,使用的平视相机,因此可以简单的将屏幕上的位移通过相机参数简单映射为世界坐标系相机的移动距离,计算方式既可以使用相机的ScreenToWorldPoint接口,也可以通过orthographicSize和Screen.height的比例换算。

        经过测试,这个方法在iOS平台没有问题,拖动起来非常的丝滑。但是在Android上,拖动起来,有抖动现象,显得游戏卡顿。

二、探究过程

        这种卡顿,初步的设想有以下几种可能:

        1、渲染层面的问题、掉帧等

        由于我们游戏测试环境下一直有帧率显示,用高性能的安卓设备测,完全能跑满60fps,并没有掉帧现象,但是视觉效果上还是显得卡顿。此外,由于我们游戏会锁定帧率,并没有开启垂直同步VSync,经测试,也排除了这种原因。

        2、事件接口的问题

        除了IDragHandler以外,还尝试了自己在Update里使用Input.GetTouch的方式来替代OnDrag事件,但是经过测试,依然会卡顿。

        3、生命周期函数选择问题

        除了在Update里尝试GetTouch,还在FixedUpdate,LateUpdate里尝试了这样的方案,也依然是抖动的。

        4、Lua的调用时机的问题

        由于在Project Setting里的Script Execution Order中将LuaLooper的时机提前,有可能导致Lua的update和渲染不在同一帧。为此,选择了尝试移除Lua的控制逻辑,用最简单的C#脚本去实现。但是经过测试也依然存在抖动现象。

        5、时间获取不对

        由于计算用的是Time.deltaTime,有可能是这个时间和触摸事件发生的时间不一致,因此尝试在C#中,使用System.DateTime.Now去统计时长,并传递给Lua层使用。但是即便这么处理,也依然存在抖动的现象。

        6、屏幕刷新率问题

        由于测试设备有高刷,120帧,怀疑可能和刷新率有关。为此关闭手机的高刷测试,但是测试结果没有改善。

        初步结论,最可能原因有

        1、Unity3d游戏引擎给OnDrag接口或者GetTouch返回的位置值,在Android平台本身就是不及时的,不平滑的

        2、获取事件时获取到position和事件发生的时机还是不对,但是由于Unity有自己的循环周期,无法准确获取事件触发真实时间。

二、插值函数

        既然获取到数值不平滑,能够采取的一个常见策略就是进行插值。一般使用的差值方式有几种:

        1、使用SmoothDamp函数

var smoothPos = Vector3.SmoothDamp(cPos, targetPos, ref currentVelocity, smoothTime);

        2、使用Lerp函数并用一个固定的参数,比如10*dt

Vector3.Lerp(currentPos, targetPos, lerpFactor * Time.deltaTime)

        3、使用Lerp函数并用幂指数函数等作为参数,比如

1.0 - Mathf.Pow(System.Math.E, - powFactor * System.Math.E * dt)

三、选定方案

        最终将调用时机(OnDrag,Update,FixedUpdate,LateUpdate)、插值方式(SmooothDamp,Lerp,LerpPow)以及具体的参数值(smoothTime,lerpFactor , powFactor ) 用不同按钮控制,实现实时调控参数,并打包到安卓测试机上测试。

        实现效果最好的是LateUpdate + SmoothDamp + 合适的参数smoothTime 的方式效果最好,因此选择了在LateUpdate读取GetTouch,用SmoothDamp作为插值函数,并到合适的参数。

四、进一步探究

        以上的方案其实在Android端已经可以取得相对较佳的表现了,唯一一个问题是,拖动的时候由于有插值延时的逻辑在,拖动地图并没有像iOS那么跟手。

        如果希望进一步优化,可以尝试的方向有,在Android原生层使用onTouchEvent事件去获取准确的值,并返回到C#层去使用。但是需要处理和现有事件框架的结合,并做测试。

@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getActionMasked();if(action == MotionEvent.ACTION_DOWN){long eventTime = event.getEventTime();float x = event.getX();float y = event.getY();Log.d(TAG, "onTouchEvent: ACTION_DOWN " + x + " " + y + " " + eventTime);}else if(action == MotionEvent.ACTION_MOVE){long eventTime = event.getEventTime();float x = event.getX();float y = event.getY();Log.d(TAG, "onTouchEvent: ACTION_MOVE " + x + " " + y + " " + eventTime);}else if(action == MotionEvent.ACTION_UP){long eventTime = event.getEventTime();float x = event.getX();float y = event.getY();Log.d(TAG, "onTouchEvent: ACTION_UP " + x + " " + y + " " + eventTime);}return super.onTouchEvent(event);}

由于时间关系,原生层的优化并没有来得及进行完。后续有结果另行记录。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 使用ElementUI + Vue框架实现学生管理系统前端页面设计
  • java中数据访问层userdao接口怎么写
  • IDEA项目启动在不同端口的方法,服务多端口启动
  • CSS3 文本效果(text-shadow,box-shadow,white-space等)文本溢出隐藏并且显示省略号
  • 系统分析师6:计算机网络
  • 46. 把数字翻译成字符串【难】
  • 【软件测试专栏】测试分类篇
  • 【Android】 工具篇:ProxyPin抓包详解---夜神模拟器
  • Elasticsearch检索原理
  • 详解Asp.Net Core管道模型中的五种过滤器的适用场景与用法
  • 人活着的意义是什么
  • [NOI2014] 魔法森林(LCT维护MST)
  • Spring Boot 多数据源配置(JPA)
  • 数据仓库技术选型方案文档
  • 语言桥梁:探索全球最受欢迎的翻译工具,让理解更简单
  • 【前端学习】-粗谈选择器
  • HTML-表单
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • Javascript 原型链
  • JavaScript创建对象的四种方式
  • JDK9: 集成 Jshell 和 Maven 项目.
  • Kibana配置logstash,报表一体化
  • laravel 用artisan创建自己的模板
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Terraform入门 - 3. 变更基础设施
  • vue.js框架原理浅析
  • vue的全局变量和全局拦截请求器
  • 程序员该如何有效的找工作?
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 马上搞懂 GeoJSON
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 如何胜任知名企业的商业数据分析师?
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • MPAndroidChart 教程:Y轴 YAxis
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • 移动端高清、多屏适配方案
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • $().each和$.each的区别
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • $refs 、$nextTic、动态组件、name的使用
  • (4.10~4.16)
  • (Forward) Music Player: From UI Proposal to Code
  • (SpringBoot)第七章:SpringBoot日志文件
  • (zt)最盛行的警世狂言(爆笑)
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)EOS中账户、钱包和密钥的关系
  • (转)项目管理杂谈-我所期望的新人