背景

NGUI在处理UI和输入方面确实做的不错,但是现在的问题是公司引入体感之后,是通过手的位置来实现按钮的点击操作,前提我不想改变原先设计好的NGUI界面和机制,怎么破?

NGUI的输入底层机制

NGUI对鼠标或者触摸的位置是通过Camera对NGUI层进行射线检测来获得,然后检测按钮事件、触摸屏Press事件来实现UI的操作,从事件机制上而言,NGUI虽然提供了几种事件机制,但底层还是通过Camera的SendMessage来通知被检测到的控件完成某个事件,OK ,看看代码。

NGUI UICamera中进行射线检测的片段 ,利用当前坐标位置转换到世界坐标系射线

static public bool Raycast (Vector3 inPos)
{
for (int i = ; i < list.size; ++i)
{
UICamera cam = list.buffer[i]; // Skip inactive scripts
if (!cam.enabled || !NGUITools.GetActive(cam.gameObject)) continue; // Convert to view space
currentCamera = cam.cachedCamera;
Vector3 pos = currentCamera.ScreenToViewportPoint(inPos);
            ..

..

        }
     }

 NGUI UICamera 中ProcessMouse()方法利用射线检测当前响应的按钮,并通过Notify()通知控件。

// No need to perform raycasts every frame
if (isPressed || posChanged || mNextRaycast < RealTime.time)
{
mNextRaycast = RealTime.time + 0.02f;
if (!Raycast(Input.mousePosition)) hoveredObject = fallThrough;
if (hoveredObject == null) hoveredObject = genericEventHandler;
for (int i = ; i < ; ++i) mMouse[i].current = hoveredObject;
}

// The button was released over a different object -- remove the highlight from the previous
if ((justPressed || !isPressed) && mHover != null && highlightChanged)
{
currentScheme = ControlScheme.Mouse;
if (mTooltip != null) ShowTooltip(false);
Notify(mHover, "OnHover", false);
mHover = null;
}

NGUI UICamera中封装的通知方法,Camera通过逻辑判断发送不同类型,如在点击的时候发送 :Notify(currentTouch.pressed, "OnClick", null);,在按下时候发送:Notify(currentTouch.current, "OnHover", true);

static public void Notify (GameObject go, string funcName, object obj)
{
if (mNotifying) return;
mNotifying = true; if (NGUITools.GetActive(go))
{
go.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver); if (genericEventHandler != null && genericEventHandler != go)
{
genericEventHandler.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver);
}
}
mNotifying = false;
}

NGUI 中 UIButton中Onclick处理OnClick ()与OnDragOver()事件,是对Notify(currentTouch.pressed, "OnClick", null)的响应,同时通过EventDelegate.Execute(onClick); 来实现委托。

/// <summary>
/// Call the listener function.
/// </summary> protected virtual void OnClick ()
{
if (current == null && isEnabled)
{
current = this;
EventDelegate.Execute(onClick);
current = null;
}
}

OK, 说到底,NGUI底层还是通过SendMessage来实现,那增加一种输入方式怎么破?

解决方案:引入新的射线检测

好的方式是直接修改NGUI底层UICamera代码逻辑,增加一种体感输入,不过涉及到的太多,倒不如再UIROOT或者UICamera增加一个专门用于体感输入方法,把手的位置作为鼠标,增加一个对NGUI层的射线检测机制,对检测到的按钮发送SendMessage消息,当然发送的内容和NGUI中的一样,就可以保证不修改NGUI的UI脚本等等,实现体感输入。代码示例:

/// <summary>
/// 作者:细雨淅淅,地址:http://www.cnblogs.com/zsb517/
/// 摄像机射线检测,对检测到的控件重新设置状态,但不影响鼠标状态
/// </summary>
private void OnRayCollision()
{ if (UICamera == null || CursorGrp == null)
{
return;
} Vector3 realPos = ScreentoWorldPoint();
Ray rayCamera = UICamera.ScreenPointToRay(realPos);
RaycastHit hit; if (Physics.Raycast(rayCamera, out hit, 1000f, LayMaskCollis.value))
{
if (hit.collider == null || hit.collider.gameObject == null)
{
return ;
} if (curButton == null )
{
// Debug.Log(hit.collider.name);
curButton = hit.collider.gameObject.GetComponent<UIButton>();
if (curButton != null)
{
curButton.SetState(UIButtonColor.State.Hover,false);
// curButton.SendMessage("OnHover", true, SendMessageOptions.DontRequireReceiver);
} return;
}
else if (curButton != null)
{
if (curButton != hit.transform.gameObject.GetComponent<UIButton>())
{
//Restore previous button ,and make new button to hover status
//curButton.SendMessage("OnPress", false, SendMessageOptions.DontRequireReceiver);
curButton.SetState(UIButtonColor.State.Normal, false);
curButton = hit.transform.gameObject.GetComponent<UIButton>();
if (curButton)
{
curButton.SetState(UIButtonColor.State.Hover, false);
//curButton.SendMessage("OnHover", true, SendMessageOptions.DontRequireReceiver);
} return;
}
else
{ }
}
}
else
{
if (curButton != null)
{
curButton.SetState(UIButtonColor.State.Hover, false); //curButton.SendMessage("OnPress", false, SendMessageOptions.DontRequireReceiver);
//curButton.SendMessage("OnHover", false, SendMessageOptions.DontRequireReceiver);
curButton = null;
return;
}
} OnReset();
} private Vector3 ScreentoWorldPoint()
{
Vector3 wPos = Vector3.zero;
if (IsMouseOrKinect)
{
wPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, );
}
else
{
if (NIHandInput.GetInstance() != null)
{
Vector2 pos = NIHandInput.GetInstance().ScreenPos; //体感输入中手的位置
wPos = new Vector3(pos.x, pos.y, );
}
} Debuger.Log(wPos);
return wPos;
}

结论

对于输入问题,Unity Input自身还提供了一种机制,不过没做太多研究,但是想把各种输入柔和在一起,确实是一件很纠结的事情,还要多考虑,不仅仅是代码问题,而是改变了整个游戏的体验。

细雨标记: unity

Unity 为NGUI增加体感输入方式的更多相关文章

  1. Kinect+unity 实现体感格斗闯关小游戏

    文章目录 项目地址 1 项目概况 1.1 项目简介 1.2 项目目的 1.3 主要技术 2 设计 2.1 基本概念 2.2 框架 2.3 算法 2.4 模型 2.5 调查问卷 3 实现 3.1 技术难 ...

  2. C#开发体感游戏 Kinect应用知识

    Kinect首先是一个XBox 360外接体感设备,通过无线方式捕捉动作感知.由PrimeSense提供Range Camera技术,同类产品如任天堂Wii.Play Station Move,必须让 ...

  3. 历时一周,unity3d+xtion打造我的第一个休闲体感小游戏《空降奇兵》

    1.游戏介绍 本游戏属于休闲小游戏,主要操作如下: 菜单控制:举起左手或右手,点击左边或者右边的菜单:挥动左手或右手,选择关卡: 操作方式:玩家跳跃,游戏中的伞兵从飞机开始降落:玩家通过控制伞兵的左右 ...

  4. 使用unity3d和tensorflow实现基于姿态估计的体感游戏

    使用unity3d和tensorflow实现基于姿态估计的体感游戏 前言 之前做姿态识别,梦想着以后可以自己做出一款体感游戏,然而后来才发现too young.但是梦想还是要有的,万一实现了呢.趁着p ...

  5. 十大最佳Leap Motion体感控制器应用

    十大最佳Leap Motion体感控制器应用   Leap Motion Controller也许还没有准备好大规模的发售,但是毫无疑问,这款小巧的动作捕捉器是我们见过的最酷的设备之一.这款设备的硬件 ...

  6. 使用HTML5开发Kinect体感游戏

    一.简介 我们要做的是怎样一款游戏? 在前不久成都TGC2016展会上,我们开发了一款<火影忍者手游>的体感游戏,主要模拟手游章节<九尾袭来 >,用户化身四代,与九尾进行对决, ...

  7. 【CityHunter】基于LBS的AR体感游戏设计理念

    本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...

  8. OpenNI结合Unity3D Kinect进行体感游戏开发(转)

    OpenNI结合Unity3D Kinect进行体感游戏开发(转) 楼主# 更多 发布于:2012-07-17 16:42     1. 下载安装Unity3D(目前版本为3.4)2. 下载OpenN ...

  9. 让我们一起摇摆 Turnipbit体感遥控车

    相信大家对Microbit是非常熟悉的,而今天我们做的这个小玩具所用的核心板是Turnipbit,是基于 Microbit开发的一块适合儿童适用的板卡.基本使用原理是一样的,这里就不多介绍了,代码这方 ...

随机推荐

  1. Android打Path的方法

    转自:http://blog.csdn.net/xiangzi10/article/details/42710099 作为程序员,了解diff&patch命 令是非常必要的.比如说我们发现某个 ...

  2. 使用HtmlAgilityPack抓取网页数据

    XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. 下面列出了最有用的路径表达式: nodename:选取此节点的所有 ...

  3. 建模算法(四)——动态规划

    其实我们对着规划接触的最多最熟悉,简单来说就是一个递归问题,递归问题简单的在的地方,编程实现的难度下降了,难的地方是如何构造递归,不好的地方是资源的浪费,但是有些地方编程实现的简单的优势可以无视掉他的 ...

  4. [LintCode] Continuous Subarray Sum II

    Given an integer array, find a continuous rotate subarray where the sum of numbers is the biggest. Y ...

  5. DP+BIT(优化复杂度) UESTC 1217 The Battle of Chibi

    题目传送门 题意:问n长度的序列,找出长度m的上升子序列的方案数. 分析:这个问题就是问:dp[i][j] = sum (dp[i-1][k]) (1 <= k <= n, a[k] &l ...

  6. ural 1283. Dwarf

    1283. Dwarf Time limit: 1.0 secondMemory limit: 64 MB Venus dwarfs are rather unpleasant creatures: ...

  7. BZOJ4295 : [PA2015]Hazard

    第i轮,a[i%n]+=b[i%m]. 枚举i,计算它变为0的次数,假设为t,那么有t=i+kn. 对于所有的i和k,(i+kn)%m形成了若干个总长度为m的环. 对于每个a[i],先在环中求出一轮最 ...

  8. python 中chr(),unichr(),ord()的用法

    chr()根据整数返回对应的字符,也就是讲ascii转换为字符 unichr()将整数返回成unicode字符 ord()将字符转换成ascii码

  9. 【BZOJ】1927: [Sdoi2010]星际竞速(费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1927 题意:n个点的无向图.m条加权边.只能从编号小的到编号大的.可以瞬移,瞬移有时间.每个点只能访 ...

  10. requirejs模块化框架用法分享

      我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一 ...