Quantcast
Channel: 英特尔开发人员专区文章
Viewing all articles
Browse latest Browse all 154

在采用 TouchScript 的 Unity* 3D 中实施手势序列

$
0
0

Download PDF

By Lynn Thompson

当配置触摸目标控制一个场景中的其他元素时,应最大限度地减少控制元素所占的屏幕空间。 这样,您可以将更多超极本™ 设备的可视屏幕区域用于显示视觉活动,更少用于用户交互。 实现它的一种方法是,让触摸目标能够处理多手势组合,从而无需在屏幕上设置更多触摸目标。 比如,使用连续点击图形用户界面 (GUI) widget 来触发炮楼旋转并开火,而非使用专门的 GUI widget 开火并使用另一个 widget 旋转炮楼(或 Unity* 3D 场景中的其他资产)。

本文将介绍如何配置使用触摸目标的场景来控制第一人称控制器 (FPC)。 首先,为基本的 FPC 位置和旋转配置触摸目标;然后,将其扩大为附加功能。 附件功能可通过现有的 GUI widget 来实现,且不需要增加几何。 生成的场景将展示 Windows* 8 上运行的 Unity 3D 能够处理不同序列中使用的多手势。

配置 Unity* 3D 场景

我首先导入一个 FBX 地形资产(包括拔高的地势和树木)来设置场景,该资产是我从 Autodesk 3ds Max* 导入的。 然后,我将 FPC 放到地形中心。

我将场景主摄像头(FPC 的子对象)的景深设置为 -1。 我创建了一个专用 GUI widget 摄像头,包括一个正射投影,宽为 1,高为 0.5,以及 Don’t Clear (不清除)标记。 然后,我创建了一个 GUIWidget 层,并将其设置为 GUI widget 摄像头的裁剪蒙版。

接下来,我从专用的正投射摄像头的视角为 FPC 在场景中的操作设置了基本的 GUI widget。 在左侧,我为每根手指设置了一个范围。 左侧的小范围可将 FPC 向左侧移动,左侧的环形范围可将其向前移动,左侧中间的范围可将其向右移动,左侧的索引范围可将 FPC 向后移动。 左拇指范围可让 FPC 跳跃,并以顺时针 30 度的方向发射球形弹。

在右侧 GUI widget 中,我创建了一个立方体(通过正射投影成为正方形)。 我使用拖拽 (pan) 手势来配置此立方体,并将其绑定到 MouseLook.cs 脚本中。 此 widget 的功能与超极本触摸板的功能相似。

我将这些 GUI widget 放在主摄像头视图之外,并将它们的层设置为 GUIWidget。 图 1 展示了运行时的场景,其中使用了 GUI widget 发射球形弹并控制 FPC 的位置。


图 1. 带有地形并发射了球形弹的 FPC 场景

场景中,球形弹从 FPC 发射出,穿过树木。 为了补救,我需要为每棵树配置一个 mesh 或盒式对撞机。 这种场景的另一个问题是,如果我使用触摸板让 FPC 向下看并按环形手指将 FPC 向前移动时,前行速度将变慢。 为了解决这一问题,我限制了按下“向前移动”按钮时的“向下看”角度。

多次点触

基本场景包括 FPC 以指定角度从中心向外投弹。 默认从中心向外发射的角度是当俯视 FPC 时顺时针 30 度。

我为场景配置了多次点触,其能够在少于指定时间微分内启动,改变球形弹发射的角度,然后发射球形弹。 我可以通过控制左拇指跳跃脚本中的浮点变量配置该行为,使其根据序列中点击数量(number of tap)的增加来快速扩大角度。 这些浮点变量可以控制发射角度,并追踪自上一颗球形弹发射后的时间:

	private float timeSinceFire = 0.0f;
	private float firingAngle = 30.0f;

然后,我在左拇指跳跃脚本中配置了 Update 循环来减少跳跃范围手势少于 1/2 秒间隔时的发射角度。 如果点触间隔大于 1/2 秒,或发射角度已经减少到 0 度,则发射角度将重置为 30 度。 代码如下:

		timeSinceFire += Time.deltaTime;

			if(timeSinceFire <= 0.5f)
			{
				firingAngle += -1.0f;

			}
			else
			{
				firingAngle = 30.0f;
			}

			timeSinceFire = 0.0f;

			if(firingAngle <= 0)
			{
				firingAngle = 30;
			}


			projectileSpawnRotation = Quaternion.AngleAxis(firingAngle,CH.transform.up);

该代码还可制作扫射效果,连续点击可发射球形弹并同时缩减其发射角度(见图 2)。 该效果允许用户定制或在仿真或游戏中的特定状况下使用。


图 2.连续点击可旋转已发射球形弹的方向。

缩放与拖拽

我在图 1 的右下角配置了方块,其作用相当于键盘上的触摸板。 在方块上进行拖拽操作不会移动方块,而会通过传送 FPS 的 MouseLook 脚本向上、下、左和右旋转情景的主摄像头。 同样,方块接收到的缩放手势(与其他平台上的缩放功能类似)不会缩放方块,只会改变主摄像头的视场 (FOV),支持用户缩放主摄像头当前捕获的画面(参见图 3)。 我将配置一个拖拽手势,该手势可在缩放手势将 FOV 返回默认的 60 度后不久启动。

我通过设置 Boolean 变量 — 拖拽 — 以及浮点变量来控制上次缩放手势操作至今的时间:

	private float timeSinceScale;
	private float timeSincePan;
	private bool panned;

我将缩放手势启动时的 timeSinceScale 变量设置为 0.0f,并将拖拽手势启动时的拖拽变量设置为“真”。 场景主摄像头的 FOV 在 Update 循环中按照如下方式在触摸板正方体中添加的脚本中进行调整:

		timeSinceScale += Time.deltaTime;
		timeSincePan += Time.deltaTime;

		if(panned && timeSinceScale >= 0.5f && timeSincePan >= 0.5f)
		{
			fieldOfView += 5.0f;
			panned = false;
		}

		if(panned && timeSinceScale <= 0.5f)
		{
			fieldOfView = 60.0f;
			panned = false;
		}

		Camera.main.fieldOfView = fieldOfView;

以下是 onScale 和 onPan 函数。 请注意 timeSincePan 浮点变量,该变量可在触摸板用于摄像头时阻止 FOV 持续增加:

	private void onPanStateChanged(object sender, GestureStateChangeEventArgs e)
    {
        switch (e.State)
        {
            case Gesture.GestureState.Began:
            case Gesture.GestureState.Changed:
                var target = sender as PanGesture;
                Debug.DrawRay(transform.position, target.WorldTransformPlane.normal);
                Debug.DrawRay(transform.position, target.WorldDeltaPosition.normalized);

                var local = new Vector3(transform.InverseTransformDirection(target.WorldDeltaPosition).x, transform.InverseTransformDirection(target.WorldDeltaPosition).y, 0);
                targetPan += transform.InverseTransformDirection(transform.TransformDirection(local));

                //if (transform.InverseTransformDirection(transform.parent.TransformDirection(targetPan - startPos)).y < 0) targetPan = startPos;
                timeSincePan = 0.0f;
				panned = true;
				break;

        }

    }

	private void onScaleStateChanged(object sender, GestureStateChangeEventArgs e)
    {
        switch (e.State)
        {
            case Gesture.GestureState.Began:
            case Gesture.GestureState.Changed:
                var gesture = (ScaleGesture)sender;

                if (Math.Abs(gesture.LocalDeltaScale) > 0.01 )
                {
					fieldOfView *= gesture.LocalDeltaScale;

					if(fieldOfView >= 170){fieldOfView = 170;}
					if(fieldOfView <= 1){fieldOfView = 1;}

					timeSinceScale = 0.0f;


                }
                break;
        }
    }


图 3. 场景的主摄像头通过适当的 GUI 触摸板模拟器“放大”远距离的特征

按下并释放,然后快速翻看

当左侧的小范围接收到按下并释放的手势,然后在 1/2 秒内使用 Flick Gesture (快速翻看手势)时,以下手势序列将会提高 FPC 的水平速度。

为了添加该功能,首先,我添加了一个浮点变量来追踪范围接收到 Release Gesture (释放手势)后的时间,并添加了一个 Boolean 变量来追踪范围接收 Flicked Gesture(快速翻看手势)的情况:

	private float timeSinceRelease;
	private bool flicked;

作为场景的初始设置,我在左侧小范围脚本中添加了访问 FPC InputController 的脚本,以允许左侧小范围能够调用将 FPC 移动到左侧的操作。 控制 FPC 横向速度的变量不是位于 InputController,而是位于 FPC 的 CharacterMotor。 允许将左侧小范围的脚本加入 CharacterMotor 的配置如下:

		CH = GameObject.Find("First Person Controller");
		CHFPSInputController = (FPSInputController)CH.GetComponent("FPSInputController");
		CHCharacterMotor = (CharacterMotor)CH.GetComponent ("CharacterMotor");

脚本的 onFlick 函数仅可将快速翻看的 Boolean 变量设置为 True。

脚本的 Update 函数(每帧调用一次)可按照如下方式改变 FPC 的横向运动速度:

		if(flicked && timeSinceRelease <= 0.5f)
		{
			CHCharacterMotor.movement.maxSidewaysSpeed += 2.0f;
			flicked = false;
		}

		timeSinceRelease += Time.deltaTime;
	}

该代码可支持用户通过按下并释放左侧小范围,然后在 1/2 秒内快速翻看左侧小范围来提高 FPC 的横向运动速度。 您可以通过任意方式配置降低横向速度的能力,包括按下并释放左侧索引范围,然后使用 Flick Gesture(快速翻看手势)。 请注意,CHCharacterMotor.movement 方法不仅包括 maxSidewaysSpeed,还包括重力、maxForwardsSpeed、maxBackwardsSpeed 和其他参数。 接收它们并于这些参数一起使用的许多 TouchScript 手势和几何可为开发 Unity 3D 场景的触摸界面提供许多选项和策略。 当为这些类型的应用开发触摸界面时,尝试将众多选项缩减为可提供最有效且最符合人体工程学的用户体验的少数选项。

手势序列的问题

我在本文的示例中配置的手势序列大量使用了 Time.deltaTime 函数。 我将该微分与确定某个操作的微分之前和之后的手势结合使用。 我在配置这些示例时遇到的两个主要问题是:时间微分的大小和使用的手势。

时间微分

我在本文中使用的时间微分是 1/2 秒。 当我使用 1/10 秒这一更短的时间时,手势序列无法识别。 虽然我感觉点触的速度足以让手势序列识别出,但是预期的场景操作并未出现。 这可能是硬件和软件延迟的结果。 因此,当开发手势序列时,应记住目标硬件平台的性能特征。

手势

在配置该示例时,最初我准备加入缩放和拖拽手势,然后加入点触和快速翻看手势。 确保缩放和拖拽手势按照预期使用后,我加入了点触手势,这可以让缩放和拖拽手势停止使用。 虽然我可以在拖拽手势之后配置一个缩放序列,但是这种手势序列不符合用户使用习惯。 最有效的序列应在 widget 中包含另一个几何目标,在缩放和拖拽手势后接收点触和快速翻看手势。

我在本示例中使用了 1/2 秒的时间微分作为操作使用(或不使用)的断点。 虽然它为用户界面 (UI) 增加了一定的复杂性,您可以配置该示例使用多个时间微分。 使用按下并释放手势,然后在 1/2 秒内使用快速翻看手势可以导致水平速度增加;使用按下并释放手势,然后再 1/2 秒至 1 秒之间使用快速翻看手势可以降低水平速度。 以这种方式使用时间微分不仅能够为 UI 提供灵活性,还可用于在场景内部安置“复活节彩蛋”。

结论

我为本文配置的手势序列场景在运行 Windows 8 的超极本设备上使用了采用 TouchScript 的 Unity 3D。 实施的序列旨在减少用户与应用交互所需的触目屏幕面积。 用于用户交互的屏幕界面的面积越少,能够用于视觉内容的面积越多。

当我无法获得一个手势序列按照预期的方式执行时,我能够构建一个可行的替代方案。 此性能调优的一部分是调整 Time.deltaTime 微分,从而获取一个手势序列按照预期在可用的硬件上执行。 同样地,我在本文中构建的 Unity 3D 场景显示,在超极本设备上运行的 Windows 8 能够用于开发使用手势序列的应用。

相关内容

关于作者

Lynn Thompson 是一位 IT 专业人员,在商业和工业计算环境领域拥有二十多年的经验。 最初,他曾在一家电力公司的控制系统更新项目中,使用 CAD 修改并创建控制系统图。 在此期间,Lynn 获得了内布拉斯加大学林肯校区(University of Nebraska, Lincoln)电气工程专业的理学士学位。 在互联网繁荣时期,他继续在一家 IT 整合企业担任系统管理员。 这份工作主要处理多种平台上的操作系统、数据库和应用管理。 在互联网泡沫破灭之后,他为服装、石油和天然气以及国防领域的企业的多种项目提供 IT 咨询服务。 现在,Lynn 又回到原点,担任电力公司的工程师。 后来,Lynn 获得内布拉斯加大学林肯校区 (University of Nebraska, Lincoln) 工程管理专业的工程硕士学位。

 

英特尔、Intel 标识、超极本和 VTune 是英特尔公司在美国和其他国家的商标。
*其他的名称和品牌是其他所有者的资产。
版权所有© 2014 年英特尔公司。 所有权保留。


Viewing all articles
Browse latest Browse all 154

Trending Articles