Unity3D学习(三):利用NGUI实现一个简单的左右摇杆

前言

小游戏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 = 1;  //摇杆灵敏度
    public float DragDistance; //摇杆平移的最大距离

    private void FixedUpdate()
    {
        if (target.localPosition.x > 0)
            direction = 1;
        else if (target.localPosition.x == 0)
            direction = 0;
        else
            direction = -1;
    }

    void OnDrag(Vector2 delta)  //NGUI组件的拖动事件回调
    {
        float targetPosition = target.localPosition.x + delta.x * sensibility; //下一帧的位置
        if(Mathf.Abs(targetPosition) >= DragDistance )
        {
            if (targetPosition > 0)
                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 > 7 * Screen.width/32) //如果点击摇杆区域,判断点击是在中心点右边还是左边
                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的OnGUI(),NGUI的相机会向每一个在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

时间: 2024-10-20 18:34:54

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

利用java实现一个简单的远程监控程序

一般的远程监控软件都是用c或者c++等语言开发的,而使用java如何来实现相同的功能呢. 首先我们先介绍一下一个简单的远程监控程序的实现原理. 功能一,远程屏幕监视 (1) 必须要有监控端与被监控端,而且程序保持启动. (2) 被监控端获取本机的屏幕截屏发图给监控端. (3) 监控端在本地窗口中显示被监控端发送过来的图像. (4) (2)(3)步骤重复执行,这时在监控端即可实时监视到被监控端的桌面操作了. 功能二,远程控制 (1) 必须要有监控端与被监控端,而且程序保持启动. (2) 在监控端监

利用VS2008发布一个简单的webservice

一个开发好的webservice,怎样发布出去,供其他电脑访问呢? 本文将介绍如何发布一个简单的webservice,其中的内容都是在网上查看别人文章,自己仿照着做了一遍,因此,难免会发生错误,如果发现错误,希望各位能够指出,谢谢!! 1.准备工作 1.1一个C#开发好的webservice实例.参考下面例子: http://www.cnblogs.com/LCCRNblog/p/3716406.html 1.2安装好IIS,安装过程: http://www.cnblogs.com/LCCRNb

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

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [plain] vie

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

构造一个简单的Linux系统MenuOS 一.linux内核源代码简介 三大法宝(存储程序计算机.函数调用堆栈.中断)和两把宝剑(中断上下文的切换:保存现场和恢复现场.进程上下文的切换) 1.在linux内核源码里面arch占有的代码量相当庞大.arch/x86目录下的代码是我们重点关注的. 2.内核启动相关的代码基本都在init目录下(main.c). start_kernel是初始化linux内核的起点. start_kernel相当于c程序中的main函数 3.linux内核的核心代码在k

利用java实现一个简单的链表结构

定义: 所谓链表就是指在某节点存储数据的过程中还要有一个属性用来指向下一个链表节点,这样的数据存储方式叫做链表 链表优缺点: 优点:易于存储和删除 缺点:查询起来较麻烦 下面我们用java来实现如下链表结构: 首先定义节点类: 复制代码package LinkTest;/** 链表节点类 @author admin */public class Node {private int value;//存储数据private Node next;//下一个节点/** 定义构造器 @param vlau

【sehll学习】linux运维一个简单shell脚本监控系统内存

学习shell脚本入门后,慢慢要尝试编写一些脚本练练手,在这先简单的学习写个系统内存的监控. 1.首先先要确定一下截取一下需要关注的内存使用值,可使用free 命令来操作 free -m 显示 一般在监控内存是我们都是截取 第三行(-/+ buffers/cache)的值.确定后可以使用管道线和grep命令来获取这个的值. free -m | grep - | awk  '{print $4}' 获取到他的值为  858 当中 grep -  就是匹配一下要选取的内容,不太熟悉的可以学习一下gr

如何利用CEF3创建一个简单的应用程序 (Windows Platform)

1. 说明 这篇文章主要讲述如何利用CEF3来创建一个简单的应用程序,引用的是1535及以上版本中包含的 Cefsimple 项目例子.如果想知道关于CEF3更多的使用方法,可以去访问 GeneralUsage. 2. 开始 首先,根据自身所使用的开发平台,可以去 这里 下载对应的发布版本.针对这个教程,我们需要下载1750或者更新的版本.当前支持的平台有Windows, Linux和Mac OS X.每一个版本都包含了当在特定平台上编译特定版本CEF3时所需要的所有文件和资源.您可以通过包含在

如何利用CEF3创建一个简单的应用程序

说明: 这篇文章主要讲述如何利用CEF3来创建一个简单的应用程序,它参考了1535及以上版本中包含的 Cefsimple 项目例子.如果想知道关于CEF3更多的使用方法,可以去访问 GeneralUsage. 开始: 首先,根据自身所使用的开发平台,可以去这里下载对应的发布版本.针对这个教程,我们需要下载1750或者更新的版本.当前支持的平台有Windows, Linux和Mac OS X.每一个版本都包含了当在特定平台上编译特定版本CEF3时所需要的所有文件和资源.您可以通过包含在里边的 RE

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

本Guide利用Eclipse以及Ant建立一个简单的Web Service,以演示Web Service的基本开发过程: 1.系统条件: Eclipse Java EE IDE for Web Developers Java SE 6 Windows XP 2.基本环境搭建: 1)Java SE6 JDK的安装:下载Java SE6 JDK,双击,安装默认选项进行安装即可. 2)Eclipse的安装与配置: 安装时直接解压.     配置处有两点,Window>Preferences>Jav