Unity 为NGUI增加体感输入方式
背景
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 为NGUI增加体感输入方式的更多相关文章
- Kinect+unity 实现体感格斗闯关小游戏
文章目录 项目地址 1 项目概况 1.1 项目简介 1.2 项目目的 1.3 主要技术 2 设计 2.1 基本概念 2.2 框架 2.3 算法 2.4 模型 2.5 调查问卷 3 实现 3.1 技术难 ...
- C#开发体感游戏 Kinect应用知识
Kinect首先是一个XBox 360外接体感设备,通过无线方式捕捉动作感知.由PrimeSense提供Range Camera技术,同类产品如任天堂Wii.Play Station Move,必须让 ...
- 历时一周,unity3d+xtion打造我的第一个休闲体感小游戏《空降奇兵》
1.游戏介绍 本游戏属于休闲小游戏,主要操作如下: 菜单控制:举起左手或右手,点击左边或者右边的菜单:挥动左手或右手,选择关卡: 操作方式:玩家跳跃,游戏中的伞兵从飞机开始降落:玩家通过控制伞兵的左右 ...
- 使用unity3d和tensorflow实现基于姿态估计的体感游戏
使用unity3d和tensorflow实现基于姿态估计的体感游戏 前言 之前做姿态识别,梦想着以后可以自己做出一款体感游戏,然而后来才发现too young.但是梦想还是要有的,万一实现了呢.趁着p ...
- 十大最佳Leap Motion体感控制器应用
十大最佳Leap Motion体感控制器应用 Leap Motion Controller也许还没有准备好大规模的发售,但是毫无疑问,这款小巧的动作捕捉器是我们见过的最酷的设备之一.这款设备的硬件 ...
- 使用HTML5开发Kinect体感游戏
一.简介 我们要做的是怎样一款游戏? 在前不久成都TGC2016展会上,我们开发了一款<火影忍者手游>的体感游戏,主要模拟手游章节<九尾袭来 >,用户化身四代,与九尾进行对决, ...
- 【CityHunter】基于LBS的AR体感游戏设计理念
本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...
- OpenNI结合Unity3D Kinect进行体感游戏开发(转)
OpenNI结合Unity3D Kinect进行体感游戏开发(转) 楼主# 更多 发布于:2012-07-17 16:42 1. 下载安装Unity3D(目前版本为3.4)2. 下载OpenN ...
- 让我们一起摇摆 Turnipbit体感遥控车
相信大家对Microbit是非常熟悉的,而今天我们做的这个小玩具所用的核心板是Turnipbit,是基于 Microbit开发的一块适合儿童适用的板卡.基本使用原理是一样的,这里就不多介绍了,代码这方 ...
随机推荐
- .net学习笔记----利用System.Drawing.Image类进行图片相关操作
C#中对图片的操作主要是通过System.Drawing.Image等类进行. 一.将图片转换为字节流 /// <summary> /// 图片处理帮助类 /// </summary ...
- js打印html中的内容
js打印方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
- Html页面插入flash代码
转自:http://www.educity.cn/jianzhan/402117.html 转自:http://www.cnblogs.com/yxc_fj/articles/1390621.html ...
- Ecological Premium
#include<bits/stdc++.h> using namespace std; int main() { int n,m; unsigned long long int a,b, ...
- C# http 发送post或get请求
/// <summary> /// 向服务器提交XML数据 /// </summary> /// <param name="url">远程访问的 ...
- 5.post上传和压缩、插件模拟请求
gzip gzip一种压缩方式,或者是文件形式,它主要用于网络传输数据的压缩 gzip压缩好不好用 浏览器:网速一定.内容越小.请求响应的速度是不是更快 手机server:返回数据类型是json/ ...
- DP+路径 URAL 1029 Ministry
题目传送门 /* 题意:就是从上到下,找到最短路,输出路径 DP+路径:状态转移方程:dp[i][j] = min (dp[i-1][j], dp[i][j-1], dp[i][j+1]) + a[[ ...
- 组合数学(全排列)+DFS CSU 1563 Lexicography
题目传送门 /* 题意:求第K个全排列 组合数学:首先,使用next_permutation 函数会超时,思路应该转变, 摘抄网上的解法如下: 假设第一位是a,不论a是什么数,axxxxxxxx一共有 ...
- 2015ACM/ICPC亚洲区长春站 G hdu 5533 Dancing Stars on Me
Dancing Stars on Me Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Ot ...
- 生成跨语言的类型声明和接口绑定的工具(Djinni )
Djinni 是一个用来生成跨语言的类型声明和接口绑定的工具,主要用于 C++ 和 Java 以及 Objective-C 间的互通. 示例接口定义文件: # Multi-line comments ...