很
抱歉的是,之前说的LEAP/UI框架设计可能只有两篇 因为个人时间实在是不允许 这个问题如果展开去写的话 那么说写本书都是不为过的 且因为内容修改很是杂乱 所以我第一篇文章用来介绍LEAP预置UI的结构第二篇用来讲How to design&build~
鉴于直接涉及交互问题 因此这篇文章的受众显得很尴尬 但是相信 认真按照我之前博客学习的同学都能够理解其中的意思
关于leap这个东西 我在第一篇文章中就提到过 ——just a toy.
所以只是用来开发的练手,根本别指望交互效果能够很好
根据我的经验来讲 手势识别的交互UI根据交互方式大概分为三种
1,触发式操作
2,手势操作(下一期)
3,映射性操作(下一期)
所以 我从最基本的触发操作ui开始入手
预警:这篇文章very very long~~
入门:
从leap coreAsset当中找到
widght这个文件夹
那先找个demo运行一下吧
SENCES
下的运行一下咯~
好 我们就由这个开始 unity UI和leap交互的前导
首先 我们来熟悉 官方预设的四种UI样式 分别是:
dial\滚轮菜单
scrolltext\可滑动的字体
slider\滑动条
toggle button\按钮
当我们把这四种prefab拖入场景加以调整
再加上控制器 就算已经完整地展示了 所有的 官方预制形式
那么我们就来一个一个说吧
1.最简单的scrolltext\可滑动的字体
这个组件的主要控制过程在这里
scrollhandle
我们可以看到他的结构相当简单 boxcollider检测触发 文本上下边界 和显示框上下边界 当text的上边界高于显示框的时候会以一个速度贴合回来 并且因为使用localposition 这个组件的工作不会因为坐标的颠倒而出错
protected virtual void ResetPivots()
{
m_pivot = transform.localPosition;
if (m_target != null)
m_targetPivot = transform.parent.InverseTransformPoint(m_target.transform.position);
}
针对 TEXT组件的修改 我们可以直接在inspectors中修改文字等等操作 而直接生成一个类似阅读器之类的应用
在脚本中我们可以看到来龙去脉
首先是这个类LeapPhysicsBase:
相信有一定基础的小伙伴都知道 既然 设置了触发器 那么肯定会有 检测函数
protected virtual void OnTriggerEnter(Collider collider)
{
//检测是否是手
if (m_target == null && IsHand(collider) && State != LeapPhysicsState.Disabled)
{
State = LeapPhysicsState.Interacting;
m_target = collider.gameObject;
ResetPivots();
}
}
protected virtual void OnTriggerExit(Collider collider)
{
if (collider.gameObject == m_target)
{
State = LeapPhysicsState.Reflecting;
m_target = null;
}
}
以上两个函数清楚的写了触发执行的过程 那既然是检测不只是要判断是否出发 还要对造成出发的对象进行判断 是否为手于是调用了以下这个函数
private bool IsHand(Collider collider)
{
return collider.transform.parent && collider.transform.parent.parent && collider.transform.parent.parent.GetComponent<HandModel>();
}
以上三个部分共同工作,就生成了最基本的触发事件
而整个组建的状态更改 控制 识别都放在一个FixedUpdate();里面
protected virtual void FixedUpdate()
{
if (m_target == null && State == LeapPhysicsState.Interacting)
{
State = LeapPhysicsState.Reflecting;
}
switch (State)
{
case LeapPhysicsState.Interacting://交互
ApplyInteractions();
break;
case LeapPhysicsState.Reflecting://反映
ApplyPhysics();
break;
case LeapPhysicsState.Disabled://无
break;
default:
break;
}
ApplyConstraints();
}
代码清晰易懂 对组件的3种状态做了规整的编写 代码结构十分清晰
public enum LeapPhysicsState
{
Interacting, // Responsible for moving the widgets with the fingers
Reflecting, // Responsible for reflecting widget information and simulating the physics
Disabled // State in which the widget is disabled
}
在不同的状态下 对应不同的执行过程 非常规整、 值得一提的是 leap官方的代码风格很适合我们去仔细钻研 其中不乏一些亮点 对于我们来说很值得借鉴 对于没有形成良好代码风格的新手来说十分值得学习
protected virtual void Awake()
{
if (GetComponent<Collider>() == null)
{
Debug.LogWarning("This Widget lacks a collider. Will not function as expected.");
}//碰撞其检测与error/warning输出
}
在这个基类的脚本中 我们基本了解了这个组件的运行机理下面就来看第二个脚本ScrollBase
这个脚本中有几个重要的常数
1,弹簧力(SnapSpringForce);
2,阻力(drag);
3,交互比例(InteractionScale);
这几个参数决定着你出发这个组件并滑动之后 多久能停下来 惯性运行的时间 等等效果
其中甚至运用到了一些公式运算
m_dampingForce = Mathf.Sqrt(4.0f * SnapSpringForce);
(阻尼/力)
类似这种运算 但最重要的还是定义了文本组件的上下界和显示框的上下界
我们可以清晰地看到 在这个组件的下方 文明本下界要长的多
从文本的属性来看 我们也可以清楚地看到纵横比也可以修改文字
而从脚本层面我们可以看到更多的这种继承关系
这是基类中的
protected virtual void