前言

小游戏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. Leetcode_128_Longest Consecutive Sequence

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/43854597 Given an unsorted arra ...

  2. Linux特殊权限分析(第二版)

    SetUID[权限值=4] 问题:为什么普通用户可以修改自己的密码? ll $(which passwd) 1.SetUID:当一个可执行程序/命令具有SetUID 权限,用户执行这个程序时,将以这个 ...

  3. 《java入门第一季》之面向对象(构造方法)

    /* 构造方法: 给对象的数据进行初始化 格式: A:方法名与类名相同 B:没有返回值类型,连void都没有 C:没有具体的返回值 */ class Student { private String ...

  4. 如何取得ChipmunkConstraint实例对象的私有属性

    在 如何用代码禁用SpriteBuilder中创建的关节 一篇中提到了要想禁用一个关节就需要将其无效化. 然后我们在重新创建新关节时,可以参考该关节的原始参数. 但是代码中只能直接访问到bodyA和b ...

  5. 嵌入式C语言查表法的项目应用

    嵌入式C实战项目开发技巧:如果对一个有规律的数组表进行位移操作 就像下面的这个表 之前写过上面这个标题的一篇文章,讲的是以位移的方式去遍历表中的数据,效率非常高,但是,如果要实现一个乱序的流水灯或者跑 ...

  6. java 项目得到jar和classes路径

    java 项目得到jar和classes路径 public static String getJarPath(Class clazz) { String path = clazz.getProtect ...

  7. 【1】mac下面iTerm配置oh-my-zsh教程

    1.安装iterm 地址如下: http://iterm2.com/ 2.安装oh-my-zsh 打开iterm输入如下命令: sh -c "$(curl -fsSL https://raw ...

  8. 服务端技术进阶(二)JBoss和tomcat的区别

    JBoss和tomcat的区别 注意JBoss和tomcat是不一样,JBoss是一个可伸缩的服务器平台,当你的EJB程序编制完成后,如果访问量增加,只要通过增加服务器硬件就可以实现多台服务器同时运算 ...

  9. 和菜鸟一起学linux总线驱动之i2c死锁问题

    不知不觉中已经有好几个月没有写点东西了,懒了就是懒了,说是忙着想把产品做得更好,都是借口,每天花一点时间来写点东西确实很不错,自己也坚持了很久很久,只不过今年以来,发现提高不是很大,能写的东西好少好少 ...

  10. spring boot + quartz 集群

    spring boot bean配置: @Configuration public class QuartzConfig { @Value("${quartz.scheduler.insta ...