林梅燕 , 廖一鵬
(1.陽(yáng)光學(xué)院 人工智能學(xué)院,福建 福州 350015; 2.福州大學(xué) 物理與信息工程學(xué)院,福建 福州 350108)
隨著計(jì)算機(jī)三維繪制技術(shù)、視景立體仿真技術(shù)、對(duì)觀察者眼球和動(dòng)作的跟蹤技術(shù)以及語(yǔ)音識(shí)別、觸覺(jué)反饋等技術(shù)的發(fā)展,虛擬現(xiàn)實(shí)技術(shù)應(yīng)運(yùn)而生.作為當(dāng)今世界的主流引擎之一,Unity 3D游戲引擎已在各種游戲平臺(tái)的制作中得到廣泛運(yùn)用,同時(shí)隨著虛擬現(xiàn)實(shí)技術(shù)的發(fā)展,VR應(yīng)用市場(chǎng)中以Unity 3D引擎制作的游戲占據(jù)了半壁江山[1—2].因此,在Unity3D游戲引擎強(qiáng)大的技術(shù)支持下,基于Unity 3D的VR游戲開(kāi)發(fā)將是未來(lái)游戲市場(chǎng)的重要組成部分[3—5].因此本文提出了一種基于無(wú)線手柄的Unity 3D的體感游戲設(shè)計(jì).但設(shè)計(jì)時(shí)提升人機(jī)交互的體驗(yàn)感,給予玩家更真實(shí)、更震撼的沉浸感最為關(guān)鍵的技術(shù)之一在于進(jìn)行人物建模以及游戲場(chǎng)景搭載時(shí)給玩家提供良好真實(shí)的游戲視覺(jué)[6].
目前,游戲視角采集模塊主要基于MPU6050運(yùn)動(dòng)處理傳感器,MPU6050內(nèi)部集成三軸加速度計(jì)和三軸陀螺儀,為Unity 3D引擎提供三軸加速度和三軸角速度的原始數(shù)據(jù)[7—8].但原始數(shù)據(jù)噪聲大,加速度計(jì)的加速度取值較為敏感,易受外部干擾,取瞬時(shí)值計(jì)算的角度誤差較大,但誤差不隨時(shí)間積累[9—10];陀螺儀通過(guò)積分運(yùn)算時(shí)會(huì)有累積誤差,累積誤差在短時(shí)間內(nèi)產(chǎn)生的積分漂移和零點(diǎn)漂移對(duì)游戲影響不大,隨著時(shí)間的增加而產(chǎn)生較大的誤差,即游戲玩得越久角度偏差越大,對(duì)玩家影響越大,但受外部干擾小,動(dòng)態(tài)測(cè)量效果好[9—10].因此將其各自優(yōu)點(diǎn)結(jié)合互補(bǔ)可以改進(jìn)測(cè)量效果.專家們提出了很多濾波算法,如卡曼濾波、經(jīng)典互補(bǔ)濾波、傳感器DMP自帶濾波.卡曼濾波算法需要考慮信號(hào)的統(tǒng)計(jì)特性,并對(duì)干擾信號(hào)精確建模,計(jì)算量大,適應(yīng)能力差[11].經(jīng)典互補(bǔ)濾波無(wú)需精確建模,計(jì)算量小,但陀螺儀存在漂移誤差,精度不高[12].誤差補(bǔ)償互補(bǔ)濾波,在補(bǔ)償環(huán)節(jié)加入校正環(huán)節(jié),以消除陀螺儀漂移常數(shù)值誤差,但對(duì)細(xì)微動(dòng)作和大幅度動(dòng)作精度不高,且各性能與經(jīng)典互補(bǔ)濾波算法相比沒(méi)有明顯提高[13].傳感器DMP自帶濾波算法,可以根據(jù)不同運(yùn)動(dòng)速度,設(shè)置不同的濾波系數(shù),能夠識(shí)別細(xì)微動(dòng)作和大幅度動(dòng)作,精度高,但沒(méi)有校正參數(shù),會(huì)出現(xiàn)漂移現(xiàn)象[14].為此,本文通過(guò)對(duì)原始數(shù)據(jù)進(jìn)行DMP自帶濾波提高數(shù)據(jù)的精度,結(jié)合誤差補(bǔ)償互補(bǔ)濾波對(duì)算法進(jìn)行優(yōu)化.對(duì)加速度器和陀螺儀的各自優(yōu)點(diǎn)進(jìn)行互補(bǔ),獲得準(zhǔn)確的姿態(tài)角度,根據(jù)這兩個(gè)傳感器不同的頻率特性,采用不同的濾波算法,濾除加速度計(jì)的高頻噪聲和陀螺儀的低頻噪聲,濾除相應(yīng)的干擾信號(hào),保留加速度計(jì)的有用低頻信號(hào)和陀螺儀的有用高頻信號(hào),再對(duì)加速度計(jì)定時(shí)采樣角度和取平均值,以此對(duì)陀螺儀得到的角度進(jìn)行校正,減小誤差.動(dòng)態(tài)跟蹤效果良好,穩(wěn)定性提高,算法簡(jiǎn)單,響應(yīng)速度快,從而獲得良好的游戲視角.
首先獲取傳感器原始數(shù)據(jù),調(diào)用DMP函數(shù),獲取DMP濾波后的四元數(shù)數(shù)據(jù),在Unity 3D引擎中,將獲得的四元數(shù)數(shù)據(jù)進(jìn)行互補(bǔ)濾波和誤差計(jì)算,獲得歐拉角(θ,γ,ψ),其中θ表示姿態(tài)與y軸產(chǎn)生的俯仰角,γ表示姿態(tài)與x軸產(chǎn)生的翻滾角,ψ表示姿態(tài)與z軸產(chǎn)生的偏航角,然后將姿態(tài)角賦值于游戲場(chǎng)景中人物對(duì)象,獲得良好的游戲視覺(jué),并將按鍵數(shù)據(jù)賦值于角色.歐拉角和按鍵數(shù)據(jù)接收完成后,處理該數(shù)據(jù),即通過(guò)歐拉角數(shù)據(jù)控制玩家角色的鏡頭轉(zhuǎn)向,按鍵數(shù)據(jù)控制人物的前進(jìn)、后退、左移、右移、攻擊及跳躍.若數(shù)據(jù)未接收完整,則返回線程繼續(xù)接收該數(shù)據(jù).游戲中的敵人擁有自動(dòng)尋找玩家并朝玩家移動(dòng)和自動(dòng)攻擊等功能.游戲結(jié)束則關(guān)閉串口,數(shù)據(jù)接收中止.
Unity 3D游戲軟件總體流程見(jiàn)圖1.
圖 1 Unity 3D游戲設(shè)計(jì)主流程圖
通過(guò)誤差計(jì)算和互補(bǔ)濾波得到的歐拉角對(duì)需要控制的人物的Rotation 3個(gè)分量進(jìn)行賦值,以控制Camera隨手柄的轉(zhuǎn)向而進(jìn)行的鏡頭轉(zhuǎn)向.歐拉角數(shù)據(jù)處理結(jié)束后,返回主程序.玩家視角轉(zhuǎn)向流程見(jiàn)圖2.
圖2 玩家視角轉(zhuǎn)向流程圖
部分程序代碼如下:
void Update()
{//每幀更新角色狀態(tài)
Debug.Log(angleRoll + ","+ angleYaw + "," + anglePitch);//控制臺(tái)顯示獲得的歐拉角數(shù)據(jù)
transform.eulerAngles = new Vector3(-angleRoll,angleYaw,0);//對(duì)游戲?qū)ο筮M(jìn)行歐拉角的賦值
}
通過(guò)編寫C#腳本,添加到敵人模型的組件上,讓敵人能夠自動(dòng)尋找及朝向玩家,并以一定速度向玩家位置移動(dòng).當(dāng)敵人與玩家的距離小于游戲中定義的矢量長(zhǎng)度2時(shí),能自動(dòng)攻擊玩家.每次攻擊結(jié)束,返回主程序.
敵人AI腳本流程見(jiàn)圖3.
圖3 敵人AI腳本流程圖
部分程序代碼如下:
GameObject go = GameObject.FindGameObjectWithTag("Player");//攝像機(jī)跟隨標(biāo)簽為Player的游戲?qū)ο?/p>
Debug.DrawLine(target.position,myTransform.position,Color.blue);//畫(huà)一條目標(biāo)和對(duì)象直接藍(lán)色的線
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,Quaternion.LookRotation(target.position - myTransform.position),rotationSpeed*Time.deltaTime);//敵人看向玩家,即正面以一定速度轉(zhuǎn)向玩家的位置
if (Vector3.Distance(target.transform.position,myTransform.position)>2)
{//當(dāng)玩家和敵人的位置大于2
myTransform.position += myTransform.forward * Time.deltaTime;//敵人向玩家的位置移動(dòng)
}
通過(guò)編寫C#腳本,添加到玩家和敵人模型的組件上.當(dāng)玩家和敵人處于游戲中定義的矢量長(zhǎng)度2以內(nèi)時(shí),敵人會(huì)自動(dòng)以多種不同的攻擊動(dòng)作攻擊玩家,玩家也可以通過(guò)手柄按鍵來(lái)攻擊敵人.每次攻擊都設(shè)定攻擊時(shí)間間隔.每次攻擊結(jié)束,返回主程序.
攻擊模塊流程見(jiàn)圖4.
圖4 攻擊模塊流程圖
部分程序代碼如下:
Attack();//攻擊
attackTimer = coolDown;//攻擊時(shí)間間隔等于冷卻時(shí)間
float distance = Vector3.Distance(target.transform.position,transform.position);//玩家和敵人的直接距離
Vector3 dir = (target.transform.position - transform.position).normalized;//將玩家和敵人的直接距離變?yōu)橄蛄?.0形式
float direction = Vector3.Dot(dir,transform.forward);//點(diǎn)乘方式計(jì)算敵人和玩家間的夾角
if (distance< 2.5f && direction>0)
{//如果夾角小于2.5并大于0,獲取敵人的最大生命值和當(dāng)前生命值
EnemyHealth eh = (EnemyHealth)target.GetComponent("EnemyHealth");
eh.AddjustCurHealth(-10);//每次攻擊減少10點(diǎn)生命
}
通過(guò)編寫C#腳本,添加到玩家和敵人模型的組件上.玩家和敵人各有100的血量,當(dāng)相距在游戲中定義的矢量長(zhǎng)度2以內(nèi)時(shí),其中一方每受到一次對(duì)方攻擊,屏幕中的血槽UI長(zhǎng)度以及血量會(huì)隨之減少10.
生命和血槽設(shè)計(jì)見(jiàn)圖5.
圖 5 生命和血槽設(shè)計(jì)
部分程序代碼如下:
healthBarLength = Screen.width/2;//生命槽長(zhǎng)度為屏幕寬度的一半
AddjustCurHealth(0);//調(diào)整當(dāng)前生命(治療或收到傷害值)
GUI.Box(new Rect(10,40,healthBarLength,20),curHealth + "/" + maxHealth);//屏幕左上角顯示矩形生命槽
curHealth += adj;//當(dāng)前生命加上被攻擊時(shí)受到的傷害
healthBarLength = (Screen.width/2) * (curHealth/(float)maxHealth);//生命槽長(zhǎng)度隨當(dāng)前生命大小改變長(zhǎng)度
本文采用的誤差補(bǔ)償互補(bǔ)濾波的姿態(tài)解算法,以互補(bǔ)濾波算法在短時(shí)間內(nèi)采用陀螺儀得到的高通濾波后的角度為最優(yōu)[15],同時(shí)對(duì)加速度計(jì)采樣的低通濾波后的角度進(jìn)行取平均值以校正陀螺儀得到的角度,并修正隨時(shí)間增加的漂移帶來(lái)的較大誤差.
互補(bǔ)濾波的姿態(tài)解算法流程見(jiàn)圖6.
圖6 互補(bǔ)濾波姿態(tài)解算流程圖
互補(bǔ)濾波的算法:
消除零點(diǎn)漂移公式為
其中 Angle_ax為x軸方向的角度,Acc_x為x軸的加速度,Kd,Kp為漂移調(diào)整系數(shù).同時(shí),通過(guò)誤差計(jì)算消除零點(diǎn)誤差:
bias-gx=bias-gx×Kx+gy-sped×Ky,gy-temp=gy-sped-bias-gx,
其中:Kx,Ky分別表示速度計(jì)角速度和陀螺儀角速度權(quán)重系數(shù);bias_gx表示加速度計(jì)的平均值;gy_sped表示加速度計(jì)的采樣值;gy_temp表示陀螺儀得到的角度.
本設(shè)計(jì)是在Visual Studio 2015的編輯環(huán)境下,運(yùn)用C#語(yǔ)言編寫Unity 3D游戲.通過(guò)實(shí)驗(yàn)驗(yàn)證幾種算法對(duì)視角的提取效果,并對(duì)實(shí)驗(yàn)結(jié)果進(jìn)行詳細(xì)的分析和對(duì)比.誤差補(bǔ)償互補(bǔ)濾波算法,采用的是四元數(shù)解算姿態(tài)獲取歐拉角的方法.通過(guò)互補(bǔ)濾波算法,再進(jìn)行誤差校正,獲取Unity 3D游戲所需的視角,通過(guò)腳本添加到控制的游戲?qū)ο?圖7).由圖7可見(jiàn),游戲的視角沒(méi)有漂移現(xiàn)象,但角度偏右,而且斜了,角色不能準(zhǔn)確獲取所需要的歐拉角;在腳本中直接調(diào)用DMP自帶濾波算法,處理后的效果見(jiàn)圖8.由圖8可見(jiàn),出現(xiàn)漂移現(xiàn)象,一直在晃動(dòng),不能正確對(duì)角色進(jìn)行操控.本文提出的算法,在調(diào)用DMP自帶濾波算法的基礎(chǔ)上,結(jié)合誤差補(bǔ)償互補(bǔ)濾波算法,通過(guò)誤差計(jì)算消除零點(diǎn)漂移現(xiàn)象.本文分別設(shè)置Kd=1 100,Kp=16 384,Kx=0.998,Ky=0.002,效果見(jiàn)圖9.由圖9可見(jiàn),消除了漂移現(xiàn)象,能夠得到正確的歐拉角以及所需的游戲視角.
圖 9 本文算法視角
表1是動(dòng)作幅度較大、正常和較小3種情況下測(cè)量的靜態(tài)俯仰角的誤差值.由表1可以看出,這3者的誤差值都較小,但還是有所區(qū)別,誤差補(bǔ)償互補(bǔ)濾波算法是在補(bǔ)償環(huán)節(jié)加入校正環(huán)節(jié),以消除陀螺儀漂移常數(shù)值誤差,但對(duì)細(xì)微和大幅度動(dòng)作精度不高,總體準(zhǔn)確率低于其他兩種算法;傳感器DMP自帶濾波算法,可以根據(jù)不同運(yùn)動(dòng)速度,設(shè)置不同的濾波系數(shù),能夠識(shí)別細(xì)微和幅度大的動(dòng)作,精度高,但沒(méi)有校正參數(shù),會(huì)出現(xiàn)漂移現(xiàn)象,所以準(zhǔn)確率有局限,無(wú)法達(dá)到最好的狀態(tài);而在本文算法中,結(jié)合DMP自帶濾波和誤差補(bǔ)償互補(bǔ)濾波算法,可以有效地提高細(xì)微和幅度大的動(dòng)作時(shí)的角度的準(zhǔn)確度,同時(shí)能夠消除陀螺儀零點(diǎn)漂移現(xiàn)象,較其他兩種算法準(zhǔn)確率更高,穩(wěn)定度更高,可以提供良好的游戲視角.
表1 靜態(tài)俯仰角測(cè)量誤差
在Unity 3D引擎中創(chuàng)建玩家、敵人以及游戲場(chǎng)景,游戲場(chǎng)景包括地形繪制、草地繪制、添加房屋、添加天空盒子、添加樹(shù)木和添加光源等,同時(shí)在場(chǎng)景中對(duì)人物和地形添加碰撞檢測(cè)與觸發(fā)檢測(cè),以防止人物直接穿過(guò)地面或者墻壁等,游戲場(chǎng)景搭建見(jiàn)圖10.通過(guò)本文算法優(yōu)化后的視角賦值給游戲場(chǎng)景中人物對(duì)象,并控制玩家角色的鏡頭轉(zhuǎn)向, 人物搭
圖10 游戲場(chǎng)景搭建
建見(jiàn)圖11,從圖11中可以看出具有良好的游戲視角.
圖11 人物搭建
Unity 3D游戲調(diào)試界面見(jiàn)圖12.該界面為Unity 3D游戲引擎的場(chǎng)景界面,包括了Scene、Project、Game、Inspector、Hierarchy、Toolbar工具欄等界面.
圖12 Unity 3D游戲調(diào)試界面
Scene界面是搭建游戲場(chǎng)景及人物的界面.Project界面中的Scripts是本設(shè)計(jì)中所編寫的C#代碼腳本,包括了串口線程接收DMP自帶濾波后數(shù)據(jù)、誤差補(bǔ)償互補(bǔ)濾波的姿態(tài)解算、敵人AI、攻擊、生命和血槽等腳本.Game界面是實(shí)時(shí)顯示玩家控制角色的視角以及所搭建的游戲場(chǎng)景.Inspector界面是顯示當(dāng)前選中的游戲?qū)ο蟮乃薪M件腳本以及其屬性的相關(guān)信息.Hierarchy界面包含了當(dāng)前場(chǎng)景的所有游戲?qū)ο?本設(shè)計(jì)中擁有玩家、敵人、光源、地面、建筑、植物等游戲場(chǎng)景對(duì)象.Toolbar工具欄分別為播放、暫停和步進(jìn),按下播放按鈕可進(jìn)入游戲界面(圖13).
圖13 游戲界面
體感游戲手柄通過(guò)藍(lán)牙控制Unity 3D游戲中的角色,做出站立、移動(dòng)、攻擊、跳躍等動(dòng)作.角色的站立見(jiàn)圖14,角色的移動(dòng)見(jiàn)圖15,角色的攻擊見(jiàn)圖16,角色的跳躍見(jiàn)圖17.
圖14 角色的站立圖
圖15 角色的移動(dòng)圖
圖16 角色的攻擊圖
圖17 角色的跳躍圖
由以上實(shí)驗(yàn)分析可知,在進(jìn)行人物建模以及游戲場(chǎng)景搭載時(shí),采用本文算法獲得的歐拉角來(lái)控制角色的轉(zhuǎn)向,具有良好的游戲視覺(jué)效果,同時(shí)采用角色腳本中的Animation代碼和動(dòng)畫(huà)實(shí)現(xiàn)動(dòng)作化,例如控制游戲人物的前進(jìn)、后退、左移、右移、攻擊及跳躍等、同時(shí)還帶有剛體碰撞、血槽UI等,整體游戲界面效果較豐富.
如何獲取良好的游戲視角是設(shè)計(jì)Unity 3D體感游戲人物建模以及游戲場(chǎng)景搭載的關(guān)鍵點(diǎn)之一,但游戲視角提取模塊存在MPU6050取值敏感、不穩(wěn)定、取值困難和瞬時(shí)角度值誤差大等問(wèn)題,針對(duì)以上問(wèn)題本文提出一種結(jié)合DMP自帶濾波算法和誤差補(bǔ)償互補(bǔ)濾波算法對(duì)游戲視角進(jìn)行優(yōu)化.采用DMP自帶濾波算法提高原始數(shù)據(jù)精度,根據(jù)加速度器和陀螺儀各自的優(yōu)勢(shì)特性進(jìn)行互補(bǔ)濾波,同時(shí)加入誤差校正改進(jìn),獲得準(zhǔn)確的姿態(tài)角度.實(shí)驗(yàn)結(jié)果表明,本文算法可以有效地提高細(xì)微和幅度大的動(dòng)作時(shí)的歐拉角獲取的準(zhǔn)確度,同時(shí)能夠消除陀螺儀零點(diǎn)漂移現(xiàn)象,穩(wěn)定度高,可以提供良好的游戲視角,適用于體感游戲背景和角色的視覺(jué)處理.但是,算法中采用2種算法結(jié)合,運(yùn)算效率不高,因此如何降低復(fù)雜度,提高運(yùn)算效率,仍需要進(jìn)一步研究解決,這也是未來(lái)的研究方向.且本文游戲設(shè)計(jì)存在不足,例如,未開(kāi)發(fā)出一個(gè)具有劇情邏輯的完整游戲,需進(jìn)行進(jìn)一步優(yōu)化,才能更好地為游戲玩家服務(wù).