據說水哥買了 Valve Index 設備,既然這個設備這么貴,不開發點有(zhi)趣(zhang)游戲就感覺對不起這個設備,本文將來開始著手開發一個可玩性不大,觀賞性極強的保齡球打磚塊游戲,這僅僅只是一個入門級的游戲,代碼量和制作步驟都超級少,適合入門
在開始之前,請參閱水哥提供的環境搭建以及部分必備知識博客
- Unity OpenVR 虛擬現實入門一:安裝配置 Unity + OpenVR 環境
- Unity OpenVR 虛擬現實入門二:一個最簡單的虛擬現實游戲/程式
在閱讀本文之前,我期望你有部分 Unity3D 開發的知識,本文不會提及多少 Unity3D 入門的知識,如果有看不懂的地方,還請自行翻 Unity3D 入門知識
此游戲的玩法就是用雙手拿起保齡球,將一堵墻砸掉,將磚塊推下地板,效果視頻如下

寫代碼就和搬磚一樣,一開始咱先使用 Unity OpenVR 虛擬現實入門二:一個最簡單的虛擬現實游戲/程式 的方法搭建出來一個放在 SteamVR SDK 里面的 Sample 的內容,開始進行砌墻

以上墻里面的各個磚塊記得加上剛體(Rigidbody)同時設定質量為 0.2 不然咱可打不掉磚塊

接下來咱來創建保齡球子彈,按照約定創建 Prefabs 檔案夾,在里面創建一個叫 Bullet 的圓球

如上圖,同樣給此子彈加上剛體,設定比較大的質量,如上圖給了質量是 10 這樣才好將磚塊打到地板下,請不要將地板加上剛體哦,默認的剛體是加上重力的,剛進入除錯發現地板掉了,這可不是在做恐怖游戲哈
下面咱來寫一點代碼,用來在扣扳機的時候,創建保齡球子彈
如何在 SteamVR 游戲中,獲取當前扳機的狀態?其實按照 Unity3D OpenVR SteamVR Input Action 動作 博客的建議,咱是不開發獲取當前扳機狀態的代碼,咱需要開發的是定義某個動作,如 InteracetUI 這個動作,獲取此動作的值來決定邏輯,這樣做的好處是方便用戶進行配置,以及支持其他不同的互動設備,如某個設備沒有扳機,但是此設備有另一個按鈕,這個按鈕也可以實作此效果,那么就可以讓用戶系結新的按鍵
咱現在還在 VR 應用或游戲開發的蠻荒時代,很多互動都在摸索階段,為了更好適配未來的新硬體和互動,通過定義動作名而不是系結具體的硬體設備上的做法的適配性更強
咱來創建一個叫 ShootWithRotation 的 C# 腳本檔案,按照國際慣例,放在 Scripts 檔案夾里面
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
using Valve.VR.InteractionSystem;
public class PlayerDemoScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
咱添加一個欄位,按照 Unity3D OpenVR SteamVR Input Action 動作 博客的內容,咱需要一個 bool 值獲取當前的扳機是否按下,在 SteamVR 里面,布爾使用 SteamVR_Action_Boolean 型別表示,通過 state 屬性獲取值,代碼如下
public SteamVR_Action_Boolean Shooting;
獲取扳機是否按下的代碼如下
if (Shooting.state)
{
Shoot();
}
通過 state 即可獲取當前的扳機是否按下,以上代碼的 Shoot 方法就是實際的射擊代碼,這部分代碼咱在下文才寫,回到 Shooting 欄位的定義,因為我主業是 WPF 開發,按照我的編碼習慣,欄位是不會公開的,而且使用下劃線開頭,但這和 Unity3D 這邊的編碼規范沖突,于是我就將欄位當成屬性好了,第一個字符大寫
咱上面代碼定義的 Shooting 欄位,想要獲取互動的本身就需要在 Unity3D 里面進行系結互動,此系結互動的方法可參閱 Unity OpenVR 虛擬現實入門六:通過搖桿控制玩家移動 這一篇的內容,大概的做法就是先將腳本附加到某個游戲物件里面,如咱將這個腳本附加到 Player 物件上面,接下來點擊 Shooting 的下拉,選擇互動

咱選擇 InteracetUI 這個動作,默認在 SteamVR 里面就是扣扳機這個互動,當然,用戶也可以自己設定到其他按鍵里面

此時我推薦大家如果之前沒有做過 SteamVR 的互動,那請嘗試在 VisualStudio 里面附加 Unity3D 除錯,在 Update 方法里面獲取 Shooting 欄位的值了解這部分的互動

如上圖,此時咱將 Shooting 欄位和 InteracetUI 這個動作系結
上圖里面的 Bullet 欄位以及 Shoot Speed 欄位等,咱將進行定義,代碼如下
public GameObject Bullet;
public SteamVR_Action_Boolean Shooting;
public float Speed = 5;
public float ShootSpeed = 2;
以上代碼的 Bullet 就是保齡球子彈的模版,用來創建保齡球子彈,而 ShootSpeed 是射擊頻率,在 VR 應用中,如果在 Update 里面不通過判斷頻率,就進行創建子彈,那么將會因為超級高的重繪而讓子彈創建速度超級快,本文這里的代碼判斷頻率只是用了直觀快速的方法
通過下面代碼可以用來限制發送子彈的速度
public GameObject Bullet;
public SteamVR_Action_Boolean Shooting;
public float Speed = 5;
public float ShootSpeed = 2;
private float _shootTime = 0;
private float _shootTimerInterval = 0;
void Start()
{
_shootTimerInterval = 1 / ShootSpeed;
}
void Update()
{
_shootTime += Time.deltaTime;
if(_shootTime> _shootTimerInterval)
{
_shootTime -= _shootTimerInterval;
if (Shooting.state)
{
Shoot();
}
}
}
下面就是 Shoot 代碼的撰寫了,我撰寫了幾個版本,經過了水哥的測驗,也就是本文如下沒有注釋掉代碼的版本的互動是最好的(雖然可玩性也特別渣)因此咱下面將來寫這個版本的邏輯
通過 GameObject.Instantiate 方法創建子彈,接著將子彈放在旁邊即可
private void Shoot()
{
var sphere = GameObject.Instantiate(Bullet);
sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));
}
因為咱的 Player 和地板沒有添加傳送的功能,因此在設定 Player 在原點時,剛好將子彈放在 (0,0.25,0.1) 的地方即可,為什么 y 是 0.25 是因為剛好球大小就是 0.5 而坐標中點是球心,通過球的一半即可剛好放在地板上,而 z 方向設定 0.1 是可以讓球剛好在前面
此時在 Unity 系結 Bullet 欄位到咱上文設定的 Prefbabs 里面的 Bullet 即可,跑起來,通過剛體的邏輯,可以使用雙手拿起球,開始玩起來
接下來是一個被干掉的互動方式,此互動方式是扣扳機進行射擊,射擊方向就是前方
實作方式是在創建子彈時,將子彈的旋轉設定和當前 HMD (頭戴式顯示幕 Head-mounted display)的方向相同,然后設定速度方向為物體前方,代碼如下
private void Shoot()
{
var sphere = GameObject.Instantiate(Bullet);
sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));
// 向著用戶看到方向
sphere.transform.rotation = Player.instance.hmdTransform.transform.rotation;
var rigidbody = sphere.GetComponent<rigidbody>();
rigidbody.velocity = sphere.transform.forward * Speed;
}
以下是 ShootWithRotation 的全部代碼
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
using Valve.VR.InteractionSystem;
public class ShootWithRotation : MonoBehaviour
{
public GameObject Bullet;
public SteamVR_Action_Boolean Shooting;
public float Speed = 5;
public float ShootSpeed = 2;
private float _shootTime = 0;
private float _shootTimerInterval = 0;
// Start is called before the first frame update
void Start()
{
_shootTimerInterval = 1 / ShootSpeed;
}
// Update is called once per frame
void Update()
{
_shootTime += Time.deltaTime;
if(_shootTime> _shootTimerInterval)
{
_shootTime -= _shootTimerInterval;
if (Shooting.state)
{
Shoot();
}
}
}
private void Shoot()
{
var sphere = GameObject.Instantiate(Bullet);
//sphere.transform.Translate(Player.instance.hmdTransform.position);
sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));
// 向著用戶看到方向
sphere.transform.rotation = Player.instance.hmdTransform.transform.rotation;
var rigidbody = sphere.GetComponent<rigidbody>();
//rigidbody.velocity = sphere.transform.forward * Speed;
//// 旋轉發射
//var rotation = Player.transform.eulerAngles.y;
//var vx = 1 * Mathf.Cos(rotation);
//var vy = -1 * Mathf.Sin(rotation);
//rigidbody.velocity = new Vector3(vx, 0, vy) * Speed;
//Destroy(sphere, 5);
}
}
當前后續水哥還開發出通過抓握的互動方式,這個互動方式看起來更好玩,實作方法是給子彈加上一個叫 Interactable 的腳本,這個腳本是帶在 SteamVR SDK 里面的,添加這個腳本時需要給定他的 activateActionSetOnAttach 欄位 \actions\default 互動

再給子彈添加一個 Throwable 腳本,讓這個球可以被扔掉
當前的游戲就可以抓起來球然后扔出去
這個游戲開發難度不高,只是有很多知識需要了解,而且有點費德熙,我在除錯了幾個小時,看著螢屏上工具人水哥測驗的畫面,特別想吐
系列博客請看
- Unity OpenVR 虛擬現實入門一:安裝配置 Unity + OpenVR 環境
- Unity OpenVR 虛擬現實入門二:一個最簡單的虛擬現實游戲/程式
- Unity OpenVR 虛擬現實入門三:最簡單的五指互動
- Unity OpenVR 虛擬現實入門四:通過腳本控制手與控制器
- Unity OpenVR 虛擬現實入門五:通過傳送控制玩家移動
- Unity OpenVR 虛擬現實入門六:通過搖桿控制玩家移動
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/285776.html
標籤:其他
上一篇:提高Unity編譯dll的速度
