前言

小游戏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. 使用GDAL工具对FY3系列卫星数据进行校正

    本文档主要对如何使用GDAL提供的工具对FY3系列卫星数据进行校正处理.FY3系列卫星提供的数据一般是以HDF5格式下发,一个典型的FY3A和FY3B的数据文件名如下: FY3A_MERSI_GBAL ...

  2. 更改EBS服务器域名/IP

    more: 341322.1 : How to change the hostname of an Applications Tier using AutoConfig 338003.1 : How  ...

  3. cocos2d 从v1.x升级到v2.x需要注意的几个地方

    首先v1.x一些CCNode定位函数实现的有问题,导致返回的CCPoint的x坐标不正确(超出320后无变化),怀疑是其对屏幕旋转判断的不正确;而且这种现象在iOS 7.1之前的模拟器中运行都正常,在 ...

  4. Android使用统计图AChartEngine 来展示数据

    本文采用的统计图参考:AChartEngine 访问地址 :http://code.google.com/p/achartengine/ 先给出效果图 本文的开发代码主要是这些:对一些代码进行修改 以 ...

  5. javascript语言扩展:可迭代对象(4)

    js 1.7中还包含一个数组推导(array comprehension)的特性,如果不在最后介绍它好像显得不怎么完整. 数组推导其实很简单: let a = [x*x for(x in range( ...

  6. The 6th tip of DB Query Analyzer

      The 6th tip of DB Query Analyzer MA Gen feng (Guangdong Unitoll Services incorporated, Guangzhou ...

  7. WPF如何得到一个在用户控件内部的元素的坐标位置

    例如有这样一个用户控件: <UserControl d:DesignHeight="100" d:DesignWidth="200" ...> &l ...

  8. javah tool for Android Native Application

    javah可以在Eclipse中配置成为External Tools,选择External Tools Configurations,配置如下,经过测试通过. Location: ${system_p ...

  9. partition List(划分链表)

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  10. JavaScript脚本放在哪里用户体验好

    javascript代码写在<head>里面: 由于这时候网页主体(body)还未加载,所以这里适合放一些不是立即执行的自定义函数,立即执行的语句则很可能会出错(视浏览器而定) javas ...