面向虚拟现实更新旧版 Unity* 游戏

面向虚拟现实更新旧版 Unity* 游戏

作者:Bob Duffy (Intel), IDZSupport K.,更新时间: 2017 年 4 月 26 日
翻译

许多开发人员已经在PC 和移动设备上利用Unity* 游戏引擎创建了很多卓越的任务和游戏。 现在,虚拟现实功能已经集成至 Unity 3D,我们需要了解如何更新旧版游戏,以提供出色的虚拟现实体验。本文将向开发人员介绍如何转换现有的 Unity 游戏,使其兼容 HTC Vive* 虚拟现实硬件。

目标虚拟现实类别: 高端虚拟现实
目标虚拟现实硬件: HTC Vive
目标 Unity 版本: Unity 5.0
本文将涵盖以下主题:

重新设计旧版游戏,以提供全新的虚拟现实体验
集成 SteamVR* 插件的技巧
开始使用控制器脚本
全新 C# 到旧版 JavaScript* 解决方案
从 2D 图形用户界面迁移至 3D 用户界面
设计全新的虚拟现实体验

虽然旧版 Unity 游戏并非专为虚拟现实而设计,但是由于 Unity 是一种模拟真实图形和物理的 3D 环境,很有可能您在改善虚拟现实体验方面已经取得了一定的进展。 添加控制器脚本前,您首先需要充分考虑旧版游戏和它所提供的全新的虚拟现实体验。 以下技巧可以帮助您设计适合旧版游戏的虚拟现实体验:

通过设计消除运动眩晕: 标准 Unity 游戏或应用的游戏体验非常令人难忘,但是无法欺骗您的感官, 认识这一点非常重要。 如果您创建了一款非常刺激的高速赛车游戏,然后将它移植到虚拟现实,用户的大脑将会接受非常混乱、错误的信号,最终引起用户的条件反射。 问题是当您的大脑看到虚拟现实世界中的第一人称运动时,它会向您的腿和驱干发送信号,以平衡眼前的运动。 某些用户可能很享受这种游戏体验,但对于大多数用户来说,这是一个非常糟糕的体验,尤其在用户直立时,有可能会摔倒。 如果他们坐着玩游戏,感知到的运动不会造成太大的问题,同时增强了安全性。 评估游戏的最佳体验,考虑建议坐式或站立的游戏体验,以及调整移动,避免用户在场景中遇到平衡问题。

对于站立的玩家,消除运动眩晕的一个有效方法是取消全部的运动,添加远距传动特性,使游戏玩家在空间中随意转换。 借助远距传动特性,您可以以用户的身份站立,将各个方向的移动距离限制在几英尺以内,用户可以将控制器指向游戏中的某个空间,通过远距传动到达那个空间。 例如,如果 FPS 射击玩家借助远距传动特性进行远距离移动,虽然他们只能步行前进或后退几步,但是游戏效果却更好。

我的游戏示例最初设计为第一人称空间驾驶体验。 因此,我决定提供坐式体验,而非空间定位体验, 这样做将不会产生混乱的大脑信号,避免了用户维持双腿平衡的过程中出现双腿僵硬的现象,同时用户能够在场景中自由移动。 我还决定降低多数运动的幅度,使运动缓和了许多。 作为一款空间游戏,实施效果非常不错;在空间中漂浮时,不会因为转弯或运动而感到眩晕。 在坐式体验中,您仍可以感受到运动,但是运动更为可控,不会在大脑中产生杂乱的信号,也无需调整或适应运动。 (如欲进一步迁移至虚拟现实的原始游戏版本,请在查看 本文, 这是一篇利用超极本™ 创建 Unity 游戏的教程。)

面向第一人称设计: 虚拟现实面临的另一个主要问题是第一人称体验。 如果旧版游戏不是专为第一人称视角而设计,需要考虑如何使第三人称视角变为有趣的第一人称体验,或者如何将游戏转换为第一人称视角。

我的游戏属于混合第一人称游戏,但是包含镜头跟随动作的特性。 我认为它太被动,只是间接的第一人称体验。 因此,我决定将人物与动作直接锁定,而非通过脚本间接跟随。

自然交互式用户界面或控制。 由于摄像头的位置不固定,而典型的屏幕菜单在摄像头中显示,因此,交互式用户界面和控制是另一大问题。 摄像头的位置就是用户正在查看的区域。 务必妥善解决控制、菜单和自然交互性问题。 由于多数控制台控制位于游戏手柄,而非屏幕上,因此,控制台游戏开发人员优势非常明显。 如果您设计的移动游戏使用了触摸控制、复杂键或可用鼠标的屏幕控制,您需要重新思考您的控制方案

我的游戏包含了 4 个控制选项:左转、右转、前进和发射。 移动版游戏使用了屏幕可触控控制,PC 版游戏使用了按键命令。 对于虚拟现实版本,我开始借鉴坦克的控制进行设计: 左控制器顺时针旋转,右控制器逆时针旋转等。测试前,这一切似乎比较可行。 我很快发现我的左拇指想要控制两个旋转方向, 事实证明,我之前用游戏手柄玩游戏,无法克服这种肌肉记忆。 HTC Vive 控制器是手持的,手指可以自由放置(和手柄相似),因此,我进行了重新设计。 左控制手柄负责控制方向,右触发器为汽车提供燃料,利用右拇指发射激光,和手柄中的 A 或 X 按钮用法相似。

利用 360 度: 虚拟现实游戏提供 360 度全方位的视角,如果游戏只允许玩家只向前移动,是对虚拟现实优势的一种浪费。 实际上,这是常规版游戏所面临的问题。 我设计了面向所有敌人的迷你-HUD 显示模式,您可以查看敌人是否从两侧或后面靠近您的战舰。 利用虚拟现实技术,只需向左或向右扭头便能轻松观察周围环境。 我将专门针对前进视角以外的危险进行改进,以充分利用 360 度全方位的虚拟现实体验。

针对示例游戏的虚拟现实重新设计决策包含以下几个方面:

采用坐姿玩法,以避免眩晕和双腿抽搐的症状
禁用跟踪摄像头,将摄像头锁定车辆的前部
抑制旋转,以避免平衡问题,缓和游戏的移动
将控制映射到 HTC Vive 控制器中,该控制器与手柄控制的布局类似。
创建特性,在更广阔的全景中展示视图和动作
添加 SteamVR 插件

这既不是最简单的操作,也不是最严峻的挑战, 完全取决于代码的老旧程度以及它对 SteamVR 工具套件的兼容。 我将介绍它预期的工作方式以及可能需要您执行的操作。

清理您的游戏,以安装最新版 Unity: 首先,复制原始游戏。 下载最新版 Unity。 打开该版本的旧版游戏。 如有提示,更新 API。 打开游戏并检查控制台是否存在过时的 API,建议您进行更新。

安装 SteamVR 插件: 如果现代版 Unity 能够正常运行游戏,可以下载并导入 SteamVR 插件。 转至 Unity 商店。 搜索 SteamVR 插件, 请选择唯一一个带有熟悉的 Steam 标识的插件。 单击 Import。

选择 All 以导入全部特性、模型和脚本。 所有内容在 SteamVR 文件夹中有序地排列,便于您弄清哪些脚本和资产来自插件。

测试示例场景: 转至下一步之前,确保 HTC Vive 硬件已经连接且正常运行。 在 Unity 中转至 Project 选项卡,打开 SteamVR 文件夹,选择 Scenes 文件夹,然后选择示例场景。 您将看到一个堆着箱子的场景和 SteamVR 截屏。 进入场景并带上头盔。 您应该看到全面的虚拟现实场景以及 HTC Vive 控制器。 如果您看到了上述场景和控制器,可以断定 SteamVR 插件正常运行。

如果没有 – 尝试创建新的项目: 如果您看不到控制器或 SteamVR 示例无法在头盔中加载,需要创建一个新的空白项目。 导入 SteamVR 工具套件并尝试示例场景。 如果这样仍不奏效,表示您的 Unity 版本或 Steam 硬件出现了问题。

新项目能够正常运行,但是旧项目无法正常运行: 如果全新项目运行良好,但是原始游戏无法兼容 SteamVR 插件,需要再次创建空白项目,安装 SteamVR 工具套件,测试套件是否正常运行,然后将您的游戏迁移至新项目。 为了完成上述操作,首先关闭项目。 在清理后的 Unity 项目中,复制 Assets 文件夹中的全部内容, 转至新项目中的 Asset 文件夹并粘帖。 打开 Unity 项目,开始测试虚拟现实。 这种方法被证实有效。 但是,您的游戏已被损坏, 许多资产的所有项目设置已经丢失,包括从项目组件到游戏资产(如模型、声音文件等)的链接。转至每个资产和每个组件,以确保游戏对象和声音文件正确链接。 这个过程费时费力, 我已经经历过两到三次。 也没有那么糟糕,但是非常琐碎。

更换摄像头: 进行下一步操作之前,请带上 HTC Vive 头盔并正常运行游戏,您应该能够通过转动头部来移动摄像头,还能环顾游戏场景。 但是您仍看不到 HTC Vive 控制器,将虚拟现实应用于摄像头的关键技术还未设置。 下面是实现集成的最关键步骤, 操作起来非常简单,让人难以相信。 为了在应用中添加虚拟现实特性,只需将场景中的主摄像机替换为 SteamVR 文件夹中的 Prefab 摄像头。 就这么简单! 但是,现有摄像头仍有大量的脚本或设置。 不要立即替换摄像头, 建议您以子对象的形式将 Prefab 摄像头放入现有摄像头。

然后,在现有摄像头的 Properties 面板中关闭摄像头及其全部组件。 在属性面板中,务必取消选中摄像头旁边的选框。

然后,复制粘帖摄像头组件和设置至 Prefab 内的 Camera Head 或 Camera Eye 子对象。 移动、复制并调整设置,戴上 HTC Vive 头盔后,天空盒和其他组件正常运行。

此时,您的旧版游戏已启用了虚拟现实技术。 您应该能够运行该场景,戴上虚拟现实头盔,环顾游戏四周,将看到手上的控制器。 下面介绍如何实现控制器和脚本兼容现有的游戏逻辑。

控制器脚本

如果您和我一样利用 JavaScript 开发游戏,可能会面临更大的挑战,但是不管采用哪种方法,实现控制器脚本与游戏的兼容相当简单。 如果您的游戏中包含 JavaScript,且需要控制器兼容这些脚本,请查看以下章节。 对场景中的左、右控制器进行以下操作。 将控制器(作为子资产)添加到主摄像头下的 Prefab 摄像头中。 Tracked Controller 脚本位于 Extra 文件夹内。 将它拖放到 Camera Prefab 内的控制器(左)中。 控制器(右)和控制器(左)的操作相同。

完成后,在 Inspector 中显示 Trigger Pressed 和其它项目,在游戏中使用这些项目时将进行开关检查。

使用控制器的概念和事件侦听器方法相似。 为了捕获一个事件(如触发或触摸板),需要创建一个 C# 脚本。 以下脚本可以通过许多论坛获取。 在本例中,我向您展示了如何创建事件触发器,以启动触发器、释放触发器、触摸控制器板以及从控制器板上抬起手指。

C# 脚本在启动触发器或触摸触摸板时触发事件:


using UnityEngine;
using System.Collections;

public class EasyController : MonoBehaviour {
    private SteamVR_TrackedController device;
    void Start () {
        device.TriggerClicked += Trigger
        device.TriggerUnclicked += UnTrigger ;
        device.PadTouched += PadTouch;

        device.PadUntouched += PadLift;
    }
    void Trigger(object sender, ClickedEventArgs e)    
        {
//        Place Code Here for Trigger
        }
    void UnTrigger(object sender, ClickedEventArgs e)
    {
 //        Place Code Here for Lifting Trigger
            }

    void PadTouch(object sender, ClickedEventArgs e)    
    {
//        Place Code Here for Touching Pad
     }

    void  PadLift(object sender, ClickedEventArgs e)
    {
 //        Place Code Here for UnTouching Pad
    }
}

控制器技巧: 开发游戏时,您会发现无法在虚拟现实中区分左右控制器。 建议在任意控制器上添加一个 3D 资产,如灯、球体或有助于区分左右控制器的任何组件, 以达到开发目的。 稍后,在用户界面章节介绍生成图标和标签的方法,以帮助用户了解如何使用控制器。

此外,可以在除开关以外的其他情况下使用触摸板。 本脚本会根据用户敲击触摸板的位置,支持用户控制游戏。 以下脚本支持您通过敲击触摸板左侧和右侧触发活动。

C# 脚本利用来自虚拟现实触摸板的 X 和 Y 值

using UnityEngine;
using System.Collections;
using Valve.VR;
public class myTouchpad : MonoBehaviour
{
    SteamVR_Controller.Device device;
    SteamVR_TrackedObject controller;
    void Start()
    {
        controller = gameObject.GetComponent<SteamVR_TrackedObject>();
    }
    void Update()
    {
        device = SteamVR_Controller.Input((int)controller.index);
        //If finger is on touchpad
        if (device.GetTouch(SteamVR_Controller.ButtonMask.Touchpad))
        {
            //Read the touchpad values
            touchpad = device.GetAxis(EVRButtonId.k_EButton_SteamVR_Touchpad);
            touchstate = device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad);
        if (touchpad.x < 0)
            {
                //  Add code if left side of controller is touched
            }
        if (touchpad.x > 0)
            {
                //  Add code if right side of controller is touched
            }
       }
     else
       {
            // Add code if pad is not touched
        }
    }
}

C# 和 JavaScript 问题

SteamVR 脚本是以 C# 编写的,导致 HTC Vive 控制器难以甚至无法与现有的 JavaScript 游戏逻辑交互。 利用以下方法可以轻松实现交互,且无需进行转换。 但是,强烈建议您最终将 JavaScript 移植到 C#。

为什么它们彼此缺少交流: 在 Unity 中的脚本存在编译顺序。 可以将 C# 变量迁移至 JavaScript,或者将 JavaScript 迁移至 C# 变量,前提是需要将脚本迁移至 Standard Assets 文件夹。 首先编译这个文件夹,然后应用它们。 但是,由于您需要 JavaScript 来查看 SteamVR 值,Steam 脚本必须位于 Standard Assets 文件夹,且必须第一个进行编译。 如果您移动了它们,会破坏 SteamVR 插件, 因此,无法将 C# 变量传输至 JavaScript。

但是还有其他方法。

一个简单的变通方法: 我突然想起,C# 和 JavaScript 均可以在游戏对象上接受和设置值。 例如,两种脚本类型均可获得和/或定义该场景游戏对象上的标签值。 游戏对象标签本身就是在脚本之间传输的变量。 例如,如果场景中的 LaserCannon 最初被标记为 “notfired”,触摸板事件可以在 C# 中将 LaserCannon.tag 设置为 “fired”。 现有的 JavaScript 能够查找每帧的对象标签值。 当 LaserCannon.tag = “fired”(由 C# 脚本编写)时,JavaScript 将它们挑选出来,并运行发射激光炮的函数。 这个技巧支持 C# 将事件和值传输至 JavaScript,也支持 JavaScript 传输事件和值至 C#。

利用上述 C# 示例介绍如何利用 JavaScript 共享变量。 如果我敲击了触摸板的一侧,相应粒子发射器将在 C# 中变更标识值。 打开粒子发射器、播放声音、碰撞检测和相关点的代码全部位于现有的 JavaScript 中,随附于左右粒子发射器。 因此,首先需要在 C# 中明确这些粒子发射器。 将 “rthrust” 和 “thrust” 声明为 GameObjects。 然后在 Start 部分,将对象 “lthrust” 定义为场景中的左粒子发射器,将 “rthrust” 定义为右粒子发射器。

C# 添加游戏对象至脚本

public class myTouchpad : MonoBehaviour
{
    public GameObject rthrust;
    public GameObject lthrust;
    SteamVR_Controller.Device device;
    SteamVR_TrackedObject controller;
    void Start()
    {
        controller = gameObject.GetComponent<SteamVR_TrackedObject>();
        rthrust = GameObject.Find("PartSysEngineRight");
        lthrust = GameObject.Find("PartSysEngineLeft");
    }

然后,在 If 语句内部(该语句确定触控板的左右侧是否被触碰)添加了代码,以更改标签名称 “lthrust” 和 “rthrust”。 (需要指出的是:您可能认为方向反了,但是在空间中,向右转意味着启动左助推器。)

触摸触摸板时,C# 更改对象的标签值

if (touchpad.x < 0)
            {
                lthrust.tag = "nolthrust";
                rthrust.tag = "rthrust";
            }
 if (touchpad.x > 0)
            {
                rthrust.tag = "northrust";
                lthrust.tag = "lthrust";
            }

最终,在随附于每个粒子发射器的 JavaScript 中,在 if 语句结尾处添加了一个附加条件”|| this.gameObject.tag=’rthrust’”,以检查标签是否等于 C# 脚本设置的值。

JavaScript 基于来自 C# 标签更新执行游戏逻辑

if (Input.GetKey ("left") || this.gameObject.tag=="rthrust"){
        GetComponent.<ParticleSystem>().enableEmission= true;
      GetComponent.<AudioSource>().PlayOneShot(thrustersright);
    }   

情况就是如此: C# 和 JavaScript 的交流。 同样的技术可以以相反的方向使用。 这是一个简单的变通解决方案,用于在两个语言和脚本之间启动控制器以及创建基本游戏体验。 完成任务后,建议您将 JavaScript 转换为 C#。

C# 技巧: 如果您刚接触 C#,可以采用以下技巧。 如果对某些数字执行加法、乘法或除法后可能产生小数,需要将变量声明为浮点。 还需要将执行加减乘除运算的数字设置为浮点集。

声明如下所示: public float: myVar ;
计算如下所示:myVar = (float)otherVar +1f
将 2D 图形用户界面转换为 3D 用户界面

根据创建 Unity 游戏的年代的不同,您可能使用了图形用户界面菜单、按钮或其他屏幕控制和用户界面元素。 我的旧版游戏专为平板电脑和 PC 而设计,因此包含屏幕和图形用户界面。 在启动菜单、标题图形、屏幕得分和警报中使用了图形用户界面。 头盔中禁用上述功能,但是可以在 PC 屏幕上查看。 在 Google 搜索后发现,需要将图形用户界面转换为用户界面,这是因为用户界面能够在游戏的 3D 空间内显示,支持它们在虚拟现实中可见性与互动性,但是图形用户界面不具备这些特性。

面向虚拟现实的用户界面技巧: 用户界面的启用方法非常简单,只需在 Hierarchy 面板中右键单击,添加用户界面并选择 Canvas。 在默认情况下,Canvas 设定为屏幕空间,因此全部尺寸和位置属性在 Inspector 中显示为灰色。 但是在 Properties Inspector 中的 Canvas 模块中,您可以将屏幕视图更改为世界空间。

更改后,可以在场景中的任何地方对用户界面特性进行放置与排列。 Canvas 设置完成后,可以在 canvas 中添加特定的用户界面项目,如按钮、图像或文本项目。

为了进行测试,将文本用户界面元素作为子对象添加至 Canvas 项目(请参阅下图左侧)。 在 inspector 的文本输入字段中输入 “Hello World”。 如果您看不到场景中的字,请转至文本的 Properties Inspector。 在 Paragraph 下面,将水平和垂直溢出更改为溢出。 我发现缩放比例有误,默认的字体太大,溢出设置支持您看清文字(甚至在字体过大的情况下)。 您可以利用 Inspector 中缩放特性缩小 Canvas 或文本。 尝试不同的缩放和字体,以确保字体清晰。 如果您的字体边缘是锯齿状,降低缩放并扩大字体。

控制器用户界面: 为控制器提供指令是用户界面的一个绝佳使用案例。 标记左、右控制器,为控制器添加图标,以标记控制器的作用和位置。 左侧是我的启动界面,为每台控制器添加了用户界面,帮助用户辨别左右控制器。 在主游戏场景,控制器配备了图形用户界面,以展示如何操作游戏。

最终,我发现更新游戏并没有那么难,在这一过程中,我思考了如何改进交互,为用户比初始版本更为浸入式、更直观的体验。 仅仅通过练习,我便获取了关于更新原始虚拟现实游戏的更多知识。 请观看以下视频,查看应用虚拟现实技术的游戏示例。

视频地址:https://dn-moderncode.qbox.me/game/updating-older-unity-games-for-vr.mp4

如果您有任何看法或者想和我讨论本次经历,在下方添加评论或通过 Twitter @bobduffy 与我联系。

有关编译器优化的更完整信息,请参阅优化通知。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值