@作者 : SYFStrive
质量达到99的文章分享给大家💪
@作者 : SYFStrive
@博客首页 : HomePage
🥧: Unity版本2019💪
📜: VR虚拟现实
📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗
📌:觉得文章不错可以点点关注 👉:VR开发专栏🔗
💃:程序员每天坚持锻炼💪
🔗:点击直接阅读文章👉 VR开发专栏(🔥)
个人介绍
我叫XXX,今年上大二,主学游戏开发虚幻引擎、Unity引擎,在校期间开发了很多小Demo我严格要求自己,自觉、遵纪、守时。本人坦诚且有责任心,有独立进取的品性,勤于动手、善于动脑,适应新环境能力很强。能够在最短时间内完成从学生到职业工作人员的转型,尽自己最大的努力融入新的工作生活。
新学期目标
①:学好新学期课程,好好学习天天向上💪
②:参加VR虚拟现实比赛
③:继续提升学历~争取考公务员💪
④:程序员坚持每天锻炼💪
⑤:
项目准备与介绍
-
前期准备如下:
①:SteamVR下载步骤 : 下载Steam链接 → 下载SteamVR1.2.2
②:VRTK3.2.1下载 :下载链接 -
项目介绍
☺:课程使用HTC Vive设备开发,使用 SteamVR1.2.2 和 VRTK3.2.1 版本开发。
☺:将游乐项目在VR里体验,使用新版VRTK实现了射线与UI的交互、新版VRTK的使用。
设备模样
设备图:
实现效果如下
导入素材
资源:
SteamVR:
VRTK:
夸克网盘下载 ☑:下载链接
提取码:PCks
导入+ 创建相关文件夹如下图:
开始页UI简单搭建
效果如下:
开发步骤
1、使用预制体 Galaxy:
2、调整 Galaxy 和 SteamVR摄像机
如下图所示:
3、使用SteamVR摄像机
4、VR模拟UI界面搭建效果图如下:
- 摄像机使用世界坐标:
- 创建UI调整
5、VRTK 3.2.1v的相关使用
- 创建VRTK(添加VRTK_SDK Manager) 👉 创建空GameObject (添加VRTK_SDK Setup组件)
如👇:
6、手臂发射射线
要与UI交互需要添加 3个组件:
把renderer添加到PointerRenderer如下:
添加右手炳到RightController
效果如下:
7、UI交互
效果如 👇:
bug(射线移进Canvas就会碰撞检测)
解决如下:
射线与UI碰撞的原理如下:
检测自带的碰撞体与刚体如下:
效果如下:
8、射线触发UI播放对于的视频
9、创建LodingPageUI
效果如下:
10、完成过山车场景
VR设画面如下:
10.1、车到达终点播放声音
如下图:
11、托马斯场景泪水过山车
VR场景如下:
开发相关脚本
StartPage 脚本
实现的功能:开始结束按钮的相关逻辑
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class StartPage : MonoBehaviour {
//结束按钮
private Button startBut;
//退出按钮
private Button exitBut;
private void Awake()
{
//获取相关组件
startBut = transform.Find("StartBut").GetComponent<Button>();
exitBut = transform.Find("EquitBut").GetComponent<Button>();
}
private void Start()
{
//开始按钮绑定相关事件
startBut.onClick.AddListener(() =>
{
SceneManager.LoadScene("Scene2");
});
//结束按钮绑定相关事件
exitBut.onClick.AddListener(() =>
{
Application.Quit();
});
}
}
ItemManager、EventManager 脚本
实现的功能:创建动态图片、左右点击按钮相关代码
ItemManager
using UnityEngine;
using DG.Tweening;
public class ItemManager : MonoBehaviour {
//单例
public static ItemManager instance;
//获取图片材质球
public Material[] materials;
//图片预制体
public GameObject prefabe;
//旋转的角度
private float angle;
//旋转方向
public int risitionDirection;
private void Awake () {
//单例
instance = this;
//旋转的方向
risitionDirection = 0;
//计算图片与图片的角度
angle = 360f / materials.Length;
for (int i = 0; i < materials.Length; i++)
{
//创建图片预制体
GameObject itemObj=Instantiate(prefabe, transform);
//设置角度
itemObj.transform.localEulerAngles=new Vector3(0, i*angle, 0);
//设置其图片
itemObj.GetComponentInChildren<MeshRenderer>().material = materials[i];
//播放该图的Audio
itemObj.GetComponentInChildren<AudioManager>().SetVideoName(materials[i].name);
//判断射线只能触发当前的页面
itemObj.GetComponentInChildren<AudioManager>().Index = i;
}
}
//右旋转
public void RightRisition()
{
risitionDirection++;
if (risitionDirection>= materials.Length)
{
risitionDirection = 0;
}
transform.DORotate(new Vector3(0, -risitionDirection * angle, 0), 0.3f);
}
//左旋转
public void LeftRisition()
{
risitionDirection--;
if (risitionDirection < 0)
{
risitionDirection = materials.Length;
}
transform.DORotate(new Vector3(0, -risitionDirection * angle, 0), 0.3f);
}
}
EventManager
using UnityEngine;
using UnityEngine.UI;
public class EventManager : MonoBehaviour {
//场景名字
private string[] sceneNameSText;
//名字文本
public Text sceneNameStext;
private void Start()
{
//右按钮
transform.Find("Right").GetComponent<Button>().onClick.AddListener(() =>
{
ItemManager.instance.RightRisition();
});
//左按钮
transform.Find("Left").GetComponent<Button>().onClick.AddListener(() =>
{
ItemManager.instance.LeftRisition();
});
//中间事件
transform.Find("Center").GetComponent<Button>().onClick.AddListener(() =>
{
Loading.Instance.LoadScene();
});
//获取Resources文件夹里面的Text文本
ReadSceneName();
}
private void Update()
{
//同步文本
sceneNameStext.text = sceneNameSText[ItemManager.instance.risitionDirection];
}
/// <summary>
/// 获取resourcesText
/// </summary>
private void ReadSceneName()
{
TextAsset textAsset = Resources.Load<TextAsset>("unityVR");
sceneNameSText=textAsset.text.Split('\n');
}
}
效果如下:
AudioManager脚本
实现的功能:实现射线碰撞到UI触发相关视频
using UnityEngine;
using UnityEngine.Video;
using VRTK;
using System.IO;
public class AudioManager : MonoBehaviour {
//获取VideoPlayer组件
private VideoPlayer video;
public int Index;
private void Awake()
{
//获取VideoPlayer组件
video = GetComponent<VideoPlayer>();
//获取VRTK_ControllerEvents
GameObject.Find("Right").GetComponent<VRTK_ControllerEvents>();
}
private void Update()
{
//判断射线只能触发当前的页面
if (Index == ItemManager.instance.risitionDirection)
{
GetComponent<MeshCollider>().enabled = true;
GetComponent<MeshRenderer>().material.color = Color.white;
}
else
{
GetComponent<MeshCollider>().enabled = false;
GetComponent<MeshRenderer>().material.color = Color.gray;
}
}
/// <summary>
/// 初始化视屏名字
/// </summary>
public void SetVideoName(string videoName)
{
video.url = GetVideoPath(videoName);
}
/// <summary>
/// 获取视频路径、播放路径
/// </summary>
private string GetVideoPath(string videoName)
{
return Application.dataPath+"/StreamingAssets/"+ videoName+".mp4";
}
//满足触发条件执行
private void OnTriggerEnter(Collider other)
{
//代表文件不存在
if (File.Exists(video.url) == false) return;
video.Play();
}
private void OnTriggerExit(Collider other)
{
video.Pause();
}
}
效果如下:
Loading 脚本
实现的功能:实现加载相关逻辑
using System.Collections;
using UnityEngine;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Loading : MonoBehaviour
{
//单例
public static Loading Instance;
//加载页UI
private Image loading;
//异步加载场景AsyncOperation
private AsyncOperation asyncOn;
//是否加载完成
private bool isLoad = false;
private void Awake()
{
//单例
Instance = this;
//找到对应的组件
loading = transform.Find("Loading").GetComponent<Image>();
transform.localScale = Vector3.zero;
}
//加载场景
public void LoadScene()
{
//DOTween相关使用
transform.DOScale(Vector3.one, 0.3f).OnComplete(() =>
{
//开启携程
StartCoroutine("LoadingS");
});
}
IEnumerator LoadingS()
{
//startValue
int displayProgress = -1;
//endValue
int toProgress = 100;
while (displayProgress < toProgress)
{
displayProgress++;
//同步UI进度条
ShowProgress(displayProgress);
if (isLoad == false)
{
//场景中有两个初始场景所以从第二个开始算
asyncOn = SceneManager.LoadSceneAsync(2 + ItemManager.instance.risitionDirection);
//加载完成不让跳转
asyncOn.allowSceneActivation = false;
isLoad = true;
}
yield return new WaitForEndOfFrame();
}
if (displayProgress == 100)
{
//跳转
asyncOn.allowSceneActivation = true;
StopCoroutine("LoadingS");
}
}
private void ShowProgress(int progress)
{
loading.fillAmount = progress * 0.01f;
}
}
效果如下:
AntorController 脚本
实现的功能:实现火车到达终点播放声音
using UnityEngine;
using UnityEngine.SceneManagement;
public class AntorController : MonoBehaviour
{
public AudioSource audioS;
private Animation anim;
/// <summary>
/// 动画片段的时间
/// </summary>
private float clipTime;
/// <summary>
/// 是否播放欢呼音效
/// </summary>
private bool isPlay = false;
/// <summary>
/// 动画是否播放完
/// </summary>
private bool isEnd = false;
/// <summary>
/// 计时器
/// </summary>
private float timer = 0f;
private void Awake()
{
//获取相关组件
anim = GetComponent<Animation>();
clipTime = anim.clip.length;
}
private void Update()
{
clipTime -= Time.deltaTime;
if (clipTime <= 10 && isPlay == false)
{
//到达终点播放声音
audioS.Play();
isPlay = true;
}
if (clipTime <= 0 && isEnd == false)
{
UnityEngine.XR.InputTracking.disablePositionalTracking = false;
//调整场景
SceneManager.LoadScene("StartScene");
//结束游戏
isEnd = true;
}
}
}
最后
本文到这里就结束了,大佬们的支持是我持续更新的最大动力,希望这篇文章能帮到大家💪相关专栏连接🔗
下篇文章再见ヾ( ̄▽ ̄)ByeBye文章来源:https://www.toymoban.com/news/detail-777746.html
文章来源地址https://www.toymoban.com/news/detail-777746.html
到了这里,关于School StartsFirstProject~UnityVR(HTCVive设备开发)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!