前言

小游戏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. hadoop上的C++程序开发

    hadoop可以用C++开发,命令运行方式为pipes,例子:hadoop pipes -conf job_config.xml -input input/myfile.txt -output out ...

  2. hadoop namenode格式化问题汇总

    hadoop namenode格式化问题汇总 (持续更新) 0 Hadoop集群环境 3台rhel6.4,2个namenode+2个zkfc, 3个journalnode+zookeeper-serv ...

  3. 解决ADT大量出现"Unexpected value from nativeGetEnabledTags: 0"的问题

    在过滤器中输入下面的代码即可:(此方法搜索于网略) ^(?!.*(nativeGetEnabledTags)).*$ 

  4. UML之对象图

    对象图对包含在类图中的事物的实例建模,对象图显示了在某一时间点上一组对象以及他们之间的关系.对象图用于对系统的静态设计视图或静态交互视图建模,这包括对某一时刻的系统快照建模,表示出对象集.对象的状态以 ...

  5. Memcached学习笔记 — 第四部分:Memcached Java 客户端-gwhalin(1)-介绍及使用

     介绍 Memcached java client是官方推荐的最早的memcached java客户端.最新版本:java_memcached-release_2.6.1. 官方下载地址:http ...

  6. WINCE的批处理

    WINCE上没有提供象window一样的bat文件,如果需要类似功能可以借助第三方程序MortScript MortScript是一个运行于WINCE上的免费脚本解释程序,脚本文件为.mscr或.mo ...

  7. Media Player Classic - HC 源代码分析 6:MediaInfo选项卡 (CPPageFileMediaInfo)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  8. "《算法导论》之‘栈’":栈的三种实现(静态数组、动态数组及指针)

    本文有关栈的介绍部分参考自网站数据结构. 1. 栈  1.1 栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底( ...

  9. Leetcode_190_Reverse Bits

    ), return 964176192 (represented in binary as00111001011110000010100101000000). 思路: (1)题意为给定无符号32位整数 ...

  10. Linux完整备份工具 - dump, restore(现在基本不用这两个)

    dump 其实 dump 的功能颇强,他除了可以备份整个文件系统之外,还可以制定等级喔!什么意思啊! 假设你的 /home 是独立的一个文件系统,那你第一次进行过 dump 后,再进行第二次 dump ...