前言

小游戏Konster在测试的时候有热心玩家反馈左右移动手感不是很好,最主要的问题是:手指一旦按在手机屏幕的一个方向按钮上,向反方向滑动到另一个方向按钮上是不会改变玩家移动方向的。

具体如下图:

刚开始我按下了→按钮,小怪兽行走到一半的时候我将拇指滑动到了←按钮,但是小怪兽并没有向左移动,然后就继续向右直到撞上尖刺死亡。

原因就是:我写的脚本只监听了按钮的按下和抬起事件。对于拇指在按钮上的滑动没有做响应处理。

所以我决定重写一个JoyStick脚本来控制小怪兽的移动方向。

实现思路

参考了这篇博客【Unity3d基础】Unity3d中利用NGUI实现虚拟摇杆。它实现的是一个360度摇杆。

我要实现的只需要左右感应就行,所以我先将左右按钮的事件监听删掉,保留图片即可。然后在按钮下方添加一个新的滑动条,挂上BoxCollider,将滑动条的左右anchor设置为leftBtn的最左和rightBtn的最右,这样自适应的时候,中间区域会随着按钮的适应和变长变短。上下anchor保持和按钮的设置一样------离屏幕底部一定距离即可。

然后在滑动条物体下面创建一个指示拇指位置的摇杆按钮。

然后我们需要写一个脚本来处理这个条状区域的按下和滑动事件。代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class JoyStick :MonoBehaviour{
public static float direction; //决定玩家的移动方向
public Transform target; //摇杆按钮
public float sensibility = ; //摇杆灵敏度
public float DragDistance; //摇杆平移的最大距离 private void FixedUpdate()
{
if (target.localPosition.x > )
direction = ;
else if (target.localPosition.x == )
direction = ;
else
direction = -;
} void OnDrag(Vector2 delta) //NGUI组件的拖动事件回调
{
float targetPosition = target.localPosition.x + delta.x * sensibility; //下一帧的位置
if(Mathf.Abs(targetPosition) >= DragDistance )
{
if (targetPosition > )
targetPosition = DragDistance;
else
targetPosition = -DragDistance;
}
target.localPosition = new Vector2(targetPosition, target.localPosition.y);
} void OnPress(bool isPressed) //NGUI组件的按住事件回调
{
if (isPressed)
{
Debug.Log(UICamera.currentTouch.pos);
if (UICamera.currentTouch.pos.x > * Screen.width/) //如果点击摇杆区域,判断点击是在中心点右边还是左边
target.localPosition = new Vector2(DragDistance , target.localPosition.y);
else
target.localPosition = new Vector2(-DragDistance, target.localPosition.y);
}
else
target.localPosition = Vector2.zero;
}
}

在这部分代码中,我们用了OnDrag()函数来处理滑动事件,OnPress()来处理抬起和按下事件。需要特别说明的是,这两个函数的调用机制类似unity自带的Update()函数,只不过Update是每一帧都会被调用,而NGUI的相机会每一帧会检测每一个在该相机渲染下可见的NGUI组件触发的事件,然后回调对应的函数。以下为NGUI的基础事件系统:

UIEvents-事件系统
void OnHover (bool isOver):当鼠标移出或者悬停在某个碰撞器上的时候返回布尔值.在触摸设备上不会有作用.
void OnPress (bool isDown):当鼠标或者触摸到碰撞器发生布尔值返回.
void OnSelect (bool selected):当鼠标或者触摸从OnPress发生后的释放将会返回这个布尔值.
void OnClick():和OnSelect的产生条件相同,当点击或触摸碰撞器并且没有发生拖拽时候触发.
void OnDrag (Vector2 delta):当移动鼠标或者触摸按下时候位移超过特定阀值时触发.
void OnDrop (GameObject drag):当鼠标或触摸释放于从发生OnDrag的不同碰撞器伤触发.传递的参数是产生OnDrag的游戏对象.
void OnInput (string text):当一个OnSelect发生后在同一个碰撞器上触发输入.一般只有UIInput用它.
void OnTooltip (bool show):当鼠标悬停超过tooltipDelay时间后触发该命令.触摸设备上不会有作用.

回到正题

在OnDrag函数里,我们直接根据每帧滑动的距离delta来更新target(也就是上面的摇杆按钮Thumb)在滑动条坐标系下的位置(localPosition),然后用一个变量distance限制左右滑动的最大距离,sensibility来控制摇杆按钮的速度,摇杆按钮的初始位置为Vector2.Zero(也就是(0,0))。当localPositon的横坐标大于0时,表示向右滑动,怪兽向右移动;反之向左。

在OnPress函数里,我们根据手指触摸的区域来判断是触摸了滑动条的左半部分还是右半部分,所以我们需要确定滑动条中间位置在屏幕上的坐标。

UICamera.currentTouch.pos这个值是以屏幕的左下角为原点来计算触摸点的坐标,如下图:

所以只要确定了滑动条的中心位置(图中的绿色分割线)在屏幕上的横坐标,就可以根据这个横坐标和触摸点的坐标来判断手指按下的区域是在滑动条左边还是右边了。
最后附上实现效果图: 滑动Drag

按下Press

如果觉得摇杆按钮有点影响美观,可以将它的Sprite精灵的alpha值设置为0,这样效果变成:

这样,一个基本的左右摇杆就完成了(^▽^)。

 参考资料

 Unity3D NGUI事件 UIEvents  作者:脱莫柔

【Unity3d基础】Unity3d中利用NGUI实现虚拟摇杆  作者:coffeecao

Unity3D学习(三):利用NGUI实现一个简单的左右摇杆的更多相关文章

  1. 利用ANTLR4实现一个简单的四则运算计算器

    利用ANTLR4实现一个简单的四则运算计算器 ANTLR4介绍 ANTLR能够自动地帮助你完成词法分析和语法分析的工作, 免去了手写去写词法分析器和语法分析器的麻烦 它是基于LL(k)的, 以递归下降 ...

  2. 利用 nodeJS 搭建一个简单的Web服务器(转)

    下面的代码演示如何利用 nodeJS 搭建一个简单的Web服务器: 1. 文件 WebServer.js: //-------------------------------------------- ...

  3. 《Linux内核分析》第三周笔记 构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS 一.linux内核源代码简介 三大法宝(存储程序计算机.函数调用堆栈.中断)和两把宝剑(中断上下文的切换:保存现场和恢复现场.进程上下文的切换) 1.在lin ...

  4. 利用OD破解一个简单的C语言程序

    最近在学习汇编(看的是王爽老师的<汇编语言(第三版)>),然后想尝试使用OD(Ollydbg)软件破解一个简单的C语言程序练练手. 环境: C语言编译环境:VC++6.0 系统:在Wind ...

  5. linux设备驱动第三篇:写一个简单的字符设备驱动

          在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分 ...

  6. 利用VS2008发布一个简单的webservice

    一个开发好的webservice,怎样发布出去,供其他电脑访问呢? 本文将介绍如何发布一个简单的webservice,其中的内容都是在网上查看别人文章,自己仿照着做了一遍,因此,难免会发生错误,如果发 ...

  7. Asp.NetMVC利用LigerUI搭建一个简单的后台管理详解(函登录验证)

    上一篇 Asp.Net 中Grid详解两种方法使用LigerUI加载数据库数据填充数据分页  了解了LigerUI 中Grid的基本用法  现在结合上一篇的内容做一个简单的后台管理,当然也有前台的页面 ...

  8. 第三周:构造一个简单的LINUX系统MENUOS

    吕松鸿 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...

  9. 【Java学习笔记】如何写一个简单的Web Service

    本Guide利用Eclipse以及Ant建立一个简单的Web Service,以演示Web Service的基本开发过程: 1.系统条件: Eclipse Java EE IDE for Web De ...

随机推荐

  1. 【翻译】使用Ext JS设计响应式应用程序

    原文:Designing Responsive Applications with Ext JS 在当今这个时代,用户都希望Web应用程序无论在形状还是大小上,既能在桌面电脑,也能在移动设备上使用.使 ...

  2. Opencv学习笔记------Harris角点检测

    image算法测试iteratoralgorithmfeatures 原创文章,转载请注明出处:http://blog.csdn.net/crzy_sparrow/article/details/73 ...

  3. 一个 redis 异常访问引发 oom 的案例分析

    「推断的前提是以事实为依据.」 这两天碰到一个线上系统的偶尔出现突然堆内存暴涨,这倒不是个什么疑难杂症, 只是过程中有些思路觉得可以借鉴参考,故总结下并写下来. 现象 内存情况可以看看下面这张监控图. ...

  4. VectorDrawable与AnimatedVectorDrawable

    VectorDrawable  Android L开始提供了新的API VectorDrawable 可以使用SVG类型的资源,也就是矢量图.先来一个例子吧. <?xml version=&qu ...

  5. linux内核 container_ofC语言之应用

    之前在剖析内核链表的文章中就有说到这个 container_of宏展开后的应用技巧. //offset(struct list , list);----->展开后((size_t) & ...

  6. Linux - Shell变量的配置守则

    变量的配置守则 变量与变量内容以一个等号『=』来连结,如下所示: 『myname=VBird』 等号两边不能直接接空格符,如下所示为错误: 『myname = VBird』或『myname=VBird ...

  7. Linux - Bash shell的功能;内建命令type

    命令编修能力 (history): bash 的功能里头,相当棒的一个就是『他能记忆使用过的命令!』 这功能真的相当的棒!因为我只要在命令列按『上下键』就可以找到前/后一个输入的命令!而在很多 dis ...

  8. 熊猫猪新系统测试之二:Mac OS X 10.10 优胜美地

    在第一篇windows 10技术预览版测试之后,本猫为大家呈现另一个刚刚才更新的mac操作系统:"优胜美地".苹果同样一改以猫科动物为代号命名的传统,在10.9的Mavericks ...

  9. OS X10.10下HomeBrew的安装提示

    apple@kissAir: c_src$ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/m ...

  10. MQ队列与哪些机器连接

    1.使用MQ安装用户登录Linux,例如:su - mqm 2.runmqsc Qm1 #Queue 代表要查询的队列3.DISPLAY CONN(*) WHERE(OBJNAME EQ Queue) ...