一、项目重述
项目重述如下:
- 在移动端设计一个可参与的创作平台,结合计算机视觉相关技术,获取物理空间中的迷宫设计图;
- 将移动端获得的迷宫数据转换为三维虚拟场景,并在VR端呈现;
- 开发基于Unity 3D的双人体验系统,并实现用户在虚拟迷宫中的漫游和交互;
- 要求实现“VR + VR”形式: 两名用户佩戴 VR头盔进行漫游并协作;
- 要求采用的VR交互技术:人体运动跟踪、控制用户在虚拟场景中漫游、手势交互等。
三、项目核心技术与亮点
- 系统完整地达到了实验的所有要求,具有完整的用户体验,涉及多种技术栈,达到了多通道交互的效果,基本上达到了自然和谐的人机交互体验
- 基于原生Android与OpenCV,高精度识别物理空间中的迷宫布局;手绘迷宫识别错误率趋近0%,实际应用环境迷宫识别错误率约5%;
- VR端场景较为恰当,组件多样;既可以单人体验,也可以多人交互,动作捕捉较为灵敏准确,使用方式灵活可靠。
- 利用Spring Boot和Vue的架构、基于HTTP的统一通讯手段,建立起了强数据一致性的服务控制端,可以实时更改迷宫布局,增加了游玩的趣味性。
四、系统架构概述
4.1 设备与开发环境
- 使用交互设备:Android智能手机(Android 6.0 及以上)、爱奇艺小阅s VR眼镜盒子、Kinect、笔记本电脑(Windows 10 及以上);
- 开发平台:Unity2021.3、Android studio 2021、Visual Studio 2020、IntelliJ IDEA 2021;
- 开发过程中使用的SDK:OpenCV for Android SDK、GoogleVRForUnity_1.200.1、 Kinect for windows SDK v2.0;
4.2 系统架构
4.2.1 系统架构简述
- 移动端:输入一张图片,经过算法的处理,输出迷宫的结构,用简短的数据结构来描述迷宫数据,最终完成向服务器的数据传输。
- VR端:此部分放在VR眼镜盒子里供用户体验,需要根据服务器数据,向用户展示三维空间景象。
- 服务器端:服务器端负责连接Kinect、识别用户动作、并且发送到VR端,控制端负责实时更新迷宫的状态,并且把最新的布局反映到VR端。
4.2.2 系统架构图
主要功能模块图示:
五、项目需求与可行性分析
5.1 移动端需求与可行性分析
5.1.1 用户界面设计
在界面设计中,我们希望设计的界面符合课上讲述的各类 GUI 设计原则的要求:
- 桌面隐喻:桌面隐喻是一种用于设计图形用户界面的技术,它将计算机界面模拟成一个现实生活中的办公桌面。在这个桌面上,用户可以看到和操作各种图标、文件夹和工具栏等,就像在现实中使用一件物品一样。
- 直接操作:直接操作是一种用户与计算机交互的方式,它允许用户直接通过物理手势或触控来操作界面元素,而不是通过命令或鼠标指针等间接的方式。这种方式可以让用户更快速、直接地完成任务,并且更容易理解系统的反馈。
- 所见即所得:所见即所得是一种界面设计的原则,它允许用户在编辑器中看到最终的输出结果。
5.1.2 图像获取方式
在实验中,我们需要获取场景中已经标记好的迷宫,需要通过拍照实现。除此以外,我们还希望可以上传图片的方式进行处理,从而应对实验环境中没有已标记迷宫的问题。
5.1.3 图像处理流程
我们希望能使用OpenCV完成图像的处理,识别图像中的迷宫,并生成格式化的迷宫数据。OpenCV是一个用于计算机视觉和机器学习的库,可以用来进行文件扫描和图像处理。下面是使用OpenCV进行处理的主要流程:
- 导入必要的SDK并获取文件列表;
- 对图像进行预处理;
- 对处理后的图像进行分析;
- 图像透视变换与直线识别;
- 模糊处理;
- 结果输出。
5.1.4 数据约定与数据传输
由于需要将迷宫识别的结果发送给服务器,我们在开发前约定了传输的数据格式:通过40位长的01字符串,按照行优先的顺序对应到迷宫的每一条边上,以此表示迷宫的结构。
5.2 VR与服务器端需求与可行性分析
5.2.1 控制平台设计及三维虚拟场景呈现
- 创作平台的设计需要简单易用,同时还要保证其能够获取物理空间中的设计图,这需要使用相应的技术实现图像识别和数据采集。
- 将物理空间中的设计图转换为三维虚拟场景需要使用三维建模技术,同时需要确保转换后的虚拟场景与原图的精度和比例一致,否则可能会影响用户的使用体验。
- 在VR端呈现虚拟场景需要使用VR技术,包括虚拟现实设备、渲染引擎、交互技术等,同时需要注意性能和体验的平衡,以确保用户可以流畅地体验虚拟场景。
5.2.2 双人体验系统设计及虚拟迷宫转换
- 双人体验系统需要支持两名用户的佩戴VR头盔进行漫游和协作,这需要使用实时通信实现用户间的数据传输和场景同步。
- 将二维迷宫转换为三维虚拟迷宫需要使用三维建模技术和数据转换技术,同时需要注意迷宫的设计精度和用户可操作性,以确保用户可以顺畅地进行漫游和交互。
- 实现用户在虚拟迷宫中的漫游和交互需要使用虚拟现实技术,包括头部追踪、手部追踪、碰撞检测、物理模拟等,同时需要注意用户体验和场景性能的平衡,确保用户可以愉悦地探索虚拟迷宫。
5.2.3 使用的开发工具和设备选择及兼容性问题
- 使用爱奇艺小阅悦s VR 眼镜盒子、Kinect、Unity、手机进行开发需要考虑它们之间的兼容性问题,同时还需要选择合适的开发工具和库,以确保开发过程的高效性和可靠性。
- 可能还需要考虑到不同设备和平台之间的兼容性问题,主要包括Unity和VR在不同平台上的兼容性。这需要在开发过程中进行充分测试和优化。
六、系统工作流程概述
在进一步介绍系统的具体开发方案之前,我们认为读者对系统的工作流程有进一步的了解,可以更清晰地阅读和理解之后的内容。出于此,本部分将对系统的工作流程做进一步的解释。
6.1 移动端二维地图识别
在移动端设计可以对二维地图识别的软件,首先可以使用手机摄像头对物理空间中的地图进行拍摄采样,通过图像进行预处理、图像进行分析、图像透视变换与直线识别、模糊处理等一系列处理过程,准确识别物理环境中迷宫的结构。
此后,将迷宫显示在用户可直接操作的GUI上供用户手动修改不完善的部分,最终按照约定组织数据并提交。
用户界面的展示如下:
6.2 服务器端接流,设置地图信息
服务器端首先接收来自移动端收集的迷宫布局数据,将封装的信息解码后获得地图信息,并按照该信息,在web界面上的4*4的地图区域还原出物理空间中的二维地图。设置完成之后首先向手机VR端发送转发地图信息,便于VR端在第一时间构建出三维迷宫地图的墙壁。接着管理员可以在服务器端的web界面上设置金币、TNT炸弹、宝箱的位置信息,设置完成之后发送给VR端。服务器与VR端之间使用Socket通信。当有多人进行游戏的时候,服务器会将设置的信息平等的发送给两个VR端,保证信息的统一性,同时也增加了游戏的竞争性、可玩性,多个用户竞争同一个宝箱。
6.3 VR端接流,进行游戏,返回游戏信息
VR端首先接收一个来自服务器端的封装后的地图信息,将该信息解码后,依据该信息利用Unity3D技术构建出三维迷宫的基本墙体,用户此时便可以观察到迷宫的样貌,也可以进行走动,体验动作识别的灵敏度等。准备完成之后VR端开始接受来自服务器端设置的地图信息,比如:金币、TNT、宝箱等。根据这些道具的位置信息,VR端在三维迷宫之中增加这些道具。当用户赢得金币,或者触碰到炸弹之后,获得相应的奖惩,VR端要取消设置在该位置上的金币或炸弹,并将迷宫中的游戏信息:用户位置、用户数量、地图上的道具信息等返回给服务器端。
6.4 服务器端接收VR端返回信息
服务器端随时接收VR端返回的游戏的信息,包括有游戏玩家的数量、游戏玩家的位置信息、当前游戏世界中金币的数量以及位置信息、TNT炸弹的数量以及位置信息、最终宝箱的数量以及位置信息。服务器要将这些信息展示在服务器的web页面上。并且服务器可以随时添加或删除金币等游戏道具的信息。
七、系统具体实现与成果展示
7.1 移动端具体实现
7.1.1 界面设计
7.1.1.1 界面展示
为了更好的解释界面的设计原理,先展示最终的界面,分别是初始的状态以及工作下的状态:
7.1.1.2功能介绍
简要介绍一下各部分:
- 上半部分是当前通过点击或者图像识别得到的迷宫
- 中间的三个紫色按钮用于对当前的迷宫进行一些快捷操作,分别对应:全部选择,选择迷宫的边缘以及全部取消选择
- 再下一行是一个输入框,用于输入服务器的ip地址。由于服务器的ip地址是动态ip地址,因此我们只协商了传输的数据格式、使用的协议以及方法api,而ip地址根据服务器动态地址手动输入。输入ip地址后,其后的“提交”按钮用于发出get请求,向服务器传递数据。
- 再下面一部分的左侧按钮,下面的两个用于打开相机拍摄图片或者在图库中选择图片,最顶部的“处理图片”按钮,用于将已经加载的图片进行处理,并以对应的格式加载到上部分的二维迷宫中。
- 右侧的图片,在“处理图片”之前,展示了拍照获得的或通过上传得到的图像,在“处理图片”之后,展示了处理的结果。
7.1.1.3 设计准则与原理
在进行设计的过程中,尽可能的应用了课上所学习的GUI设计理论,具体阐述如下。
桌面隐喻:
- 迷宫的设计展示了桌面隐喻的原理,用不同的颜色展示了迷宫当前位置为“墙”或者“空地”,易于使用者理解。
直接操纵:
- 迷宫可以通过点击实现添加墙壁,再点击即可“删除”当前墙壁,体现了“直接操纵”的原理。
所见即所得:
- 对迷宫的操作可以直接显示,体现了“所见即所得”的技术原理。
- 右下角图片在加载之后显示上传图片,在处理之后显示处理过后的图片,体现了“所见即所得”的思想。
7.1.2 手动确定迷宫格式
7.1.2.1设计目的
出于一下三个目的,在进行图片识别处理之前,我首先设计了可以点击处理,即手动确定迷宫组成的部分。
- 图片识别不一定准确,识别过后也需要手动的调整。
- 在没有图像来源的时候,我们也希望可以通过手动输入的方式,告知系统迷宫的结构。
- 便于项目原型的开发和测试。
7.1.2.2 构建方式
根据实验的要求,如“3.2.1”中的展示的图片,迷宫由4 * 4的正方形组成,边缘以Button的形式组成,以行优先的模式处理,每行有四个或者五个按钮,即 4 + 5 + 4 + 5 + 4 + 5 + 4 + 5 + 4 = 40 个按钮,组成了整个迷宫。每个按钮彼此独立,表示迷宫中的“一堵墙”是否存在。
迷宫的存储由一个二维数组完成,以行优先的结构存储,共有九行。数组中的每一位只能取0或者1,表示当前位置的“墙壁”是否“存在”。
通过点击按钮,可以改变按钮的颜色,同时更新数组中对应位置的数值,即改变一个墙壁的状态。
7.1.2.3 迷宫快速操作按键
在实际开发与测试的过程中,我们发现有一些手动的操作是重复的,比如,我们常常希望可以为迷宫添加四周的边缘,以保证迷宫内的用户有沉浸式的体验。而每次通过点击输入迷宫的四周,是一个令人感到厌倦的工作。
因此,在迷宫的下方,添加了三个按钮,用于直接完成三个常用的操作,分别是:
- 全部选择:选择迷宫中的全部“墙体”。
- 选择边缘:选择外围的“墙体”,而不处理外围之外的“墙体”。
- 全部取消选择:取消选择所有“墙体”。
开发及测试中的过程与体验证明,这三个按钮的设计是十分有必要的。
7.1.3 图像获取
作为系统的输入,图像获取流程是十分关键的一部分。根据上文的需求分析,我们希望可以通过上传图片或拍照的两种方式完成图像的输入操作。
7.1.3.1 通过拍照获得图片
其主要步骤如下:
- 在布局文件中添加一个 ImageView 控件,用于显示选择的图片。
- 请在清单文件中添加 <uses-feature> 代码,获得拍照权限。
- Android 向相机委托操作的方法是调用一个 Intent,用于描述要执行的操作。此过程涉及三个部分:Intent 本身,用于启动外部 Activity 的调用,以及用于在焦点返回到 Activity 时处理图片数据的一些代码。
- Android 相机应用会保存一张完整尺寸的照片,但是由于照片的体积较大,完整的图像不允许直接加载到程序中,处理的方式是先将图像保存在本地,并通过回调加载到imagview中。
7.1.3.2在相册上传图片
这部分的处理流程相对较为简单:
- 首先,同样需要使用 Intent 请求相册的工作。
- 通过选择照片的回调加载图片。
7.1.4图像处理
图像的处理以及在其中识别出迷宫是项目的关键部分,在这部分中,我们期望可以在输入的图片中提取出最大矩形的信息,并通过透视变换转换为正方形,还需要一些额外的图像处理的步骤,以便于下一部分中迷宫的识别。
7.1.4.1 处理步骤
- 导入OpenCV库:在接下来的代码中,需要使用OpenCV库的相关函数,需要先导入OpenCV库。在安卓项目中,需要在build.gradle文件中添加OpenCV库的依赖。
- 加载图像:可以使用OpenCV的imread()函数从图库或相机中加载图像。
- 预处理图像:对于原始图像,可能需要进行一些处理来增强图像特征。这个过程包括将图像转换为灰度图像、应用高斯滤波、应用边缘检测等技术。
- 边缘检测:使用Canny算法进行边缘检测。这将得到一幅二值化图像,其中白色像素表示边缘,黑色像素表示非边缘。
- 轮廓检测:使用findContours()函数查找图像中的所有轮廓。该函数会返回一个轮廓列表,每个轮廓由一系列点组成。
- 矩形检测:对于每个轮廓,使用approxPolyDP()函数对其进行多边形逼近。如果逼近后的多边形是矩形,则将其保存在矩形列表中。
- 找到最大矩形:遍历矩形列表,找到最大的矩形。我的处理方式是对识别到的所有矩形面积进行排序,以便于找到最大的矩形,即对应迷宫的外围。
- 透视变换:使用Imgproc.getPerspectiveTransform()函数计算变换矩阵。该函数需要输入源图像中矩形的四个顶点和目标图像中矩形的四个顶点。然后,使用Imgproc.warpPerspective()函数将图像进行透视变换,变换后的图像会被变换成一个正方形。
- 显示结果:最后,使用ImageView或者SurfaceView将处理后的图像显示出来。
7.1.4.2 结果展示
原始图像:
处理结果:
7.1.5 迷宫识别
完成了上述的图像处理之后,我们得到了一个正方向的迷宫,其中黑色的部分标识了迷宫的“墙体”,接下来的工作是识别出迷宫中的直线,并对应地映射到迷宫的每个墙壁上,最终更改设置好的迷宫。
7.1.5.1 具体步骤
识别过程主要分为以下几个步骤:
- 识别图像中的直线:再次使用HoughLinesP进行直线检测,识别出正方形迷宫中的所有直线。
- 模糊处理:根据迷宫的实际结构,直线只应当出现在固定的位置,识别出的直线位置往往有所偏差,为了接下来的处理,我们将一个固定位置附近的所有直线,投影到其固定的位置上。如:修正直线,遍历所有的直线节点,(0, 20)区间内的修正为 0、(80, 120)区间内的修正为100、(180, 220)区间的修正为 200、(280, 320)区间的修正为 300。
- 检测直线:对于映射后的固定位置进行检测,如果当前直线的两端能映射到一个“墙体”的两端上,则认定为当前墙体“存在”。
- 修改迷宫:根据识别出的信息,对迷宫墙体数组以及按钮状态进行修改。
7.1.5.2 结果展示
输入迷宫图像:
处理结果:
7.1.6 数据提交
经过组内协商,我们使用HTTP协议中的 GET 请求进行数据的发送,数组组织在URL中,以一个40位的字符串发送。
7.2 VR端开发具体实现
7.2.1 总体预览图
7.2.2 动捕数据处理
首先,我们设定了一个计数器,每接收到10次数据执行一次更新,这么做的目的是为了更新玩家坐标的操作不能太频繁,实验证明能够稍微提高一些VR的性能,尤其是在设备硬件条件不是很好的情况下。
然后我们写了一个统一分割函数:parseOneComponentPosition()。这个函数是项目的早期阶段写的,里面是对于各个部位做了一下字符串到index的映射,以后调用的时候就比较方便。
实际上在之后的开发过程中,对我们有用的数据也就是头部和手部数据。分割之后,我们把这个头部数据作为人体坐标的依据(头部一般不会抖动,比较稳定),并且存到一个public static的变量中。
7.2.3 实体组件的逻辑
实体组件主要有地板、墙壁、宝箱、金币、TNT炸药桶这四个部分。其中,地板作为整个地图的托举部分,上面承担了一些额外的通讯功能(把一些C# Scripts 绑定在了上面)。例如TCPClient,还有movement脚本。这些脚本是作为全局状态存储器或者行动控制器运行的,主要作用是控制全局状态。
墙壁,TNT炸药桶,金币,宝箱都是作为prefab事先存到项目里面。
墙壁是不具有rigidbody的刚体组件,不受重力影响,但碰撞时会妨碍玩家移动。
金币是不受重力影响的刚体组件,会每秒旋转,以吸引玩家过来拾取。当玩家离金币距离为 3 以内,并且右手举过头顶的时候,金币就会被拾取。金币被捡到之后+10分。
TNT如果距离玩家为2以内就会爆炸,并且-20分。可以看到,它有一个爆炸效果的成员变量。如果靠近,就会爆炸并且消失。
7.2.4 人物行走
对于一条数据,由工具集系统可知:一条信息可能包含多个玩家的位置信息。所以如果是单人游戏,我们直接舍弃其他人物的信息,保留第一个玩家的动作捕捉数据。如果是双人游戏,则需要明确自己究竟是第几个玩家,并且根据玩家号对应的数据来更新自己或者他人的位置。
那么,如何才能确定一个唯一的玩家号呢?我们在服务端设定了一个这样的服务:
它返回的报文格式如下:
也就是说,我们所有的数据最终都在服务端,并且VR在开机的时候就向服务端发送一个HTTP报文,以请求自己的玩家号和初始迷宫布局信息。
关于地图的墙壁编号和地块编号,我们是这样规约解释的:
这样就能用一个字符来唯一描述一个组件的位置。
7.2.5 墙壁和物品的实时更新
我们使用springboot+vue搭建了服务端的平台。这里仅仅展示一下效果。如图,可以直接修改并且实时反映到所有的VR端。这一效果达成的方法是:VR端每1秒发送一个HTTP请求到服务端,然后根据其回复来更新VR地图。在服务端前端热更新地图之后,会传到后端并且更改相应的文件。这个文件就是一切数据的最终依据来源。
7.2.6 计分系统
我们在游戏中引入了积分系统,金币+10分,TNT-20分,最终宝箱+100分,规定时间内赢得分数较高的玩家界定为胜利。
游戏结束界面如下:
7.3 服务端开发具体实现
7.3.1 接收移动端地图识别端的信息并处理
服务器端与前端使用socket进行通信,接收到数据转化为JSON的格式,读取之后储存到walls的文件当中,后续所有关于迷宫墙壁的操作都是根据对walls文件的操作。
7.3.2 web界面展示地图信息
前端使用Get方法从后端调用walls的信息,读取之后对应到web界面的地图中,对应的墙壁块变为黑色,从而实现了物理空间地图信息到web界面平面信息的转化。
7.3.3 web界面上更改地图信息,设置游戏道具等操作
7.3.3.1 更改地图墙壁信息
通过点击对应的墙壁的位置,实现对墙壁的增加或删除。
此时我将全部的内部墙壁都取消了。
7.3.3.2 增加金币、TNT炸弹、最终宝箱等道具
管理员操作:先点击右侧的增加各种类型道具的按钮,然后再点击左边地图中每个方格中间的位置,从而实现出对道具的增加,设置完成之后对应位置会出现有相应的图标,所有道具设置完成之后,点击提交便可以提交到两个VR端。
{
设置完成之后点击右侧提交按钮,若提交成功则会出现相应提示
7.3.3.3 自动刷新/暂停刷新
点击自动刷新之后,前端web界面每隔5s接收一次后端发过来的数据,并将其显示在对应的位置上,其目的是为了实现实时更新VR端用户的位置,是否获取了金币等游戏信息。便于管理员进行上帝视角的查看。暂停刷新之后,管理员可以实时对游戏内道具的信息进行修改。
7.3.4 向VR端发送管理员设置好的地图信息以及游戏道具
服务器与VR端使用Socket进行通信,当建立好连接之后,服务器立即发送一个json数据包,该数据包中只包含walls墙壁信息与player_id用户id两个信息,便于VR端在第一时间构建出三维迷宫地图的墙壁。之后每隔5s管理员每点击一次提交便会向VR端发送一个完整的json数据包,包含有道具数量以及位置信息,墙壁信息,用户id等数据。使得VR端能够在虚拟三维迷宫中构建出各种各样的道具。
7.3.5 接收VR端发送的游戏进行中的各种游戏信息并展示
VR端会实时发送游戏中的信息,包括用户位置、用户数量、地图上的道具信息等,服务器接收之后展示在web界面,便于管理员了解游戏的情况。并作出对应的操作以增加游戏的趣味性。
八、总结
本实验目的是通过对物理空间的二维地图识别,依据此信息构建出虚拟三维迷宫,并通过设置一系列的奖惩道具,使用户在VR眼镜的帮助下,实现用户在虚拟迷宫中的漫游和交互。
主要完成以下五个方面:
- 移动端识别物理空间迷宫布局,并推流到服务器端;
- 服务器端接流,并在网页上设置地图信息;
- VR端的移动从服务器拉流,并向服务器端发送游戏进行中的一系列信息;
- 服务器端接流,并显示在网页上;
8.1 系统设计亮点
8.1.1 高精度的物理迷宫识别
我们所开发的系统在物理环境迷宫识别的任务中表现相当出色。通过图像进行预处理、图像进行分析、图像透视变换与直线识别、模糊处理等一系列严谨的算法设计,实现了“手绘迷宫识别错误率趋近0%,实际应用环境迷宫识别错误率约5%”的出色识别结果。
8.1.2 实时控制,实时更改地图信息
在服务器端,管理员可以在上帝视角随时更改游戏世界中的道具数量或位置,当用户很长一段时间找不到金币时,可以在用户的周围设置一枚金币,让用户有种柳暗花明的感觉,增加对游戏的兴趣,同时引导用户前往最终宝箱。或者在用户前往最终宝箱的必经之路上放置一枚TNT,用户需要及时进行躲避,才能不被惩罚,大大增加了游戏的可玩性,刺激性。
8.1.3 多人游玩,良好的竞争体验
该游戏系统支持多人同时进行游玩,用户可以选择协作去找最终宝箱,也可以去竞争同一个宝箱,不管怎样都给了用户可选择的权利。多人游玩也给了用户与其他用户交互的机会,,增加了游戏的可玩性。
8.1.4 丰富的道具以及奖惩机制
该游戏系统设置了丰富的道具体系,具体的道具类型有:金币、TNT炸弹、最终宝箱。其中道具的规则:用户走到金币位置之后,Kinect检测到用户触摸金币的信息之后,该用户将获得奖励分。TNT炸弹同理,当用户触碰到TNT炸弹之后,将获得惩罚,积分减少。最终宝箱,设置数量只有一个,当某个用户找到最终的宝箱之后,该用户取得胜利,游戏结束。VR端还需要将游戏世界中的信息发送给服务器端,比如当用户找到一枚金币之后,该位置上便不会再有金币了,金币的数量减一。
8.1.5 道具位置的随机性,游戏局势随机改变的趣味性
服务器端在设置好金币、TNT炸弹等道具的位置信息之后,只会返回给VR大体的位置,并不会返回具体的位置。VR端在接收了服务器的信息之后,根据在大体位置的范围内,随机选择一个具体位置进行道具的放置,极大的增加了游戏的随机性,游戏局势可能随机发生变化,增加了游戏的刺激感、提高了游戏的可玩性。文章来源:https://www.toymoban.com/news/detail-519528.html
8.2 系统测试
除了出色地完成整个系统的设计与开发工作,为了验证系统在“人机交互”等方面的合理与完善,我们还对系统进行了一系列单元测试、集成测试、系统测试以及用户测试等,测试的具体执行方案以及测试结果请见《用户评估报告》。文章来源地址https://www.toymoban.com/news/detail-519528.html
到了这里,关于基于Unity的VR迷宫游戏项目技术分享的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!