真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Unity中UI或3D場景怎么實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動效果-創(chuàng)新互聯(lián)

這篇文章給大家分享的是有關(guān)Unity中UI或3D場景怎么實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動效果的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

為南川等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及南川網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、南川網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

需求

當(dāng)游戲顯示3d場景及其UI的時(shí)候。玩家左右晃動手機(jī)的時(shí)候,UI界面會隨之左右偏移。上下晃動的時(shí)候,3D場景會隨之上下偏移。手機(jī)停止晃動的時(shí)候,如若偏移的UI或場景,停頓一會后自動恢復(fù)到初始默認(rèn)位置。

分析

首先本文功能應(yīng)對的是橫屏游戲(豎屏游戲的話也差不多一樣,大家自己拓展下),假設(shè)當(dāng)我們拿起手機(jī)玩游戲,手機(jī)會有四個(gè)部位,分別為左手拿的左手邊和右手拿的右邊,以及屏幕內(nèi)容的上方和下方(下文中會用左手邊,右手邊,上方,下方來描述)。每個(gè)部位的傾斜都會造成UI或場景的偏移效果

我們可以先用一個(gè)枚舉來定義這四個(gè)部位的傾斜情況

public enum EGyroType
{
 NoRotate,//不旋轉(zhuǎn)
 ToUp,//手機(jī)下方向上傾斜
 ToDown,//手機(jī)下方向下傾斜
 ToLeft,//左手邊向下傾斜
 ToRight,//右手邊向下傾斜
}

接著我們可以使用Unity的陀螺儀接口Input.gyro的一些屬性,來判斷當(dāng)前手機(jī)的傾斜狀態(tài),Gyroscope有如下屬性:

Unity中UI或3D場景怎么實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動效果

我用到enabled和gravity兩個(gè)屬性,enabled用于打開或者關(guān)閉陀螺儀功能,而gravity返回的是一個(gè)Vector3變量,具體情況對應(yīng)的返回值,通過打印Log在android手機(jī)上顯示如下(橫屏游戲,紀(jì)錄了某種情況下的某個(gè)不特定的角度的gravity值):

當(dāng)手機(jī)橫著屏幕朝上水平放置在桌上的時(shí)候,返回值為:(0.0, 0.0, -1.0)

上下傾斜:

當(dāng)手機(jī)下方向上傾斜時(shí),某個(gè)角度(轉(zhuǎn)角小于90度)的返回值為:(0.0, 0.4, -0.9),角度再大的話屏幕的內(nèi)容會翻轉(zhuǎn)過來。

當(dāng)手機(jī)下方向下傾斜時(shí),某個(gè)角度(轉(zhuǎn)角小于90度)的返回值為:(0.0, -0.5, -0.9),轉(zhuǎn)角為90度時(shí):(0.0, -1.0, 0.0),轉(zhuǎn)角在90度到180度中時(shí):(0.0, -0.8, 0.6),180度時(shí)即屏幕正朝下為:(0.0, 0.0, 1.0),若角度再大一點(diǎn)為:(0.0, 0.3, 0.9),直至屏幕內(nèi)容翻轉(zhuǎn)過來。

我們可以發(fā)現(xiàn)

1.當(dāng) z < 0 , y > 0:當(dāng)y的值變大則為ToUp,變小則為ToDown

2.當(dāng) z < 0 , y < 0:當(dāng)y的值變大則為ToUp,變小則為ToDown

3.當(dāng) z > 0 , y < 0:當(dāng)y的值變大則為ToDown,變小則為ToUp

4.當(dāng) z > 0 , y > 0:當(dāng)y的值變大則為ToDown,變小則為ToUp

5.當(dāng) z < 0 變?yōu)?z > 0,則為ToDown,反之則為ToUp

前四條總結(jié)下來就是,當(dāng) z < 0,y的值變大則為ToUp,變小則為ToDown。當(dāng) z > 0,y的值變大則為ToDown,變小則為ToUp

左右傾斜:

當(dāng)手機(jī)左手邊向下傾斜時(shí),某個(gè)角度(轉(zhuǎn)角小于90度)的返回值為:(-0.2, 0.0, -1.0),轉(zhuǎn)角為90度時(shí):(-1.0, 0.0, 0.0),轉(zhuǎn)角在90度到180度中時(shí):(-0.6, 0.0, 0.8)

當(dāng)手機(jī)右手邊向下傾斜時(shí),某個(gè)角度(轉(zhuǎn)角小于90度)的返回值為:(0.6, 0.0, -0.8),轉(zhuǎn)角為90度時(shí):(1.0, 0.0, 0.0),轉(zhuǎn)角在90度到180度中時(shí):(0.8, 0.0, 0.5)

可以總結(jié)出

1.當(dāng) z < 0 , x < 0:當(dāng)x的值變小則為ToLeft,變大則為ToRight

2.當(dāng) z > 0 , x < 0:當(dāng)x的值變大則為ToLeft,變小則為ToRight

3.當(dāng) z < 0 , x > 0:當(dāng)x的值變大則為ToRight,變小則為ToLeft

4.當(dāng) z > 0 , x > 0:當(dāng)x的值變小則為ToRight,變大則為ToLeft

即,當(dāng) z < 0,x的值變小則為ToLeft,變大則為ToRight。當(dāng) z > 0,x的值變大則為ToLeft,變小則為ToRight

5.當(dāng) z < 0 變?yōu)?nbsp;z > 0,若 x < 0 則為ToLeft,否則則為ToRight

6.當(dāng) z > 0 變?yōu)?nbsp;z < 0,若 x < 0 則為ToRight,否則則為ToLeft

然后我們可以根據(jù)這些性質(zhì)推斷出手機(jī)的當(dāng)前狀態(tài),然后去執(zhí)行我們想要執(zhí)行的操作。

根據(jù)需求,無論是移動物體,還是轉(zhuǎn)動攝像機(jī)來達(dá)到偏移的效果,都會有一個(gè)大偏移值,偏移速度,不轉(zhuǎn)動的時(shí)候等待的一個(gè)間隔時(shí)間,這幾個(gè)參數(shù)需要設(shè)置。

具體實(shí)現(xiàn)

首先我們寫一個(gè)腳本GyroManager,掛載在場景的一個(gè)GameObject上(也可以處理成為單例,在別處調(diào)用里面的Start,Update方法),用來每幀檢測當(dāng)前的手機(jī)狀態(tài),并調(diào)用對應(yīng)狀態(tài)的注冊事件。

using System;
using UnityEngine;
 
public enum EGyroType
{
 NoRotate,//不旋轉(zhuǎn)
 ToUp,//手機(jī)下方向上傾斜
 ToDown,//手機(jī)下方向下傾斜
 ToLeft,//左手邊向下傾斜
 ToRight,//右手邊向下傾斜
}
 
public class GyroManager : MonoBehaviour
{
 Gyroscope mGyro;//陀螺儀
 Vector2 mCurrentLandscapeGyroValue, mCurrentPortraitGyroValue;//當(dāng)前的水平垂直的gravity值
 Vector2 mLastLandscapeGyroValue, mLastPortraitGyroValue;//上一次的水平垂直的gravity值
 
 public EGyroType LandscapeEGyroType, PortraitEGyroType;//手機(jī)的水平垂直狀態(tài)
 float mPrecision = 0.015f;//精度,若前后兩次gravity值在精度內(nèi),則認(rèn)為當(dāng)前沒有旋轉(zhuǎn)
 public int LandscapeGyroDifference, PortraitGyroDifference;//模擬的一個(gè)旋轉(zhuǎn)速度,gravity值差異越大,則該值越大
 
 bool mIsEnable;//是否開啟陀螺儀
 
 private void Start()
 {
 mGyro = Input.gyro;
 SetGyroEnable(true);
 }
 
 //每種狀態(tài)下需要執(zhí)行的事件
 public Action LandscapeTransToDefault;
 public Action LandscapeTransToAdd;
 public Action LandscapeTransToReduce;
 
 public Action PortraitTransToDefault;
 public Action PortraitTransToAdd;
 public Action PortraitTransToReduce;
 
 public void ResetLandscape()
 {
 LandscapeEGyroType = EGyroType.NoRotate;
 SetLandScapeValue();
 mLastLandscapeGyroValue = mCurrentLandscapeGyroValue;
 LandscapeGyroDifference = 0;
 }
 
 public void ResetPortrait()
 {
 PortraitEGyroType = EGyroType.NoRotate;
 SetPortraitValue();
 mLastPortraitGyroValue = Vector2.zero;
 PortraitGyroDifference = 0;
 }
 
 void Update()
 {
 if (mIsEnable)
 {
  GetEGyroType();
 
  //根據(jù)解析出來的手機(jī)狀態(tài),執(zhí)行對應(yīng)事件
  if (LandscapeEGyroType == EGyroType.ToLeft)
  {
  LandscapeTransToReduce?.Invoke(LandscapeGyroDifference);
  }
  else if (LandscapeEGyroType == EGyroType.ToRight)
  {
  LandscapeTransToAdd?.Invoke(LandscapeGyroDifference);
  }
  else
  {
  LandscapeTransToDefault?.Invoke();
  }
 
  if (PortraitEGyroType == EGyroType.ToDown)
  {
  PortraitTransToReduce?.Invoke(PortraitGyroDifference);
  }
  else if (PortraitEGyroType == EGyroType.ToUp)
  {
  PortraitTransToAdd?.Invoke(PortraitGyroDifference);
  }
  else
  {
  PortraitTransToDefault?.Invoke();
  }
 }
 }
 
 //開啟或關(guān)閉陀螺儀
 public void SetGyroEnable(bool isEnable)
 {
 if (mIsEnable != isEnable)
 {
  mIsEnable = isEnable;
  ResetLandscape();
  ResetPortrait();
  mGyro.enabled = isEnable;
 }
 }
 
 //解析當(dāng)前手機(jī)狀態(tài)
 public void GetEGyroType()
 {
 SetLandScapeValue();
 //Landscape
 if (IsEquals(mCurrentLandscapeGyroValue.x, mLastLandscapeGyroValue.x, true))
 {
  LandscapeEGyroType = EGyroType.NoRotate;
  LandscapeGyroDifference = 0;
 }
 else
 {
  LandscapeGyroDifference = (int)(Mathf.Abs(mCurrentLandscapeGyroValue.x - mLastLandscapeGyroValue.x) * 60);
 
  if (mCurrentLandscapeGyroValue.y < 0 && mLastLandscapeGyroValue.y < 0)
  {
  //當(dāng) z < 0,x的值變小則為ToLeft,變大則為ToRight
  if (mCurrentLandscapeGyroValue.x < mLastLandscapeGyroValue.x)
  {
   LandscapeEGyroType = EGyroType.ToLeft;
  }
  else
  {
   LandscapeEGyroType = EGyroType.ToRight;
  }
  }
  else if (mCurrentLandscapeGyroValue.y > 0 && mLastLandscapeGyroValue.y > 0)
  {
  //當(dāng) z > 0,x的值變大則為ToLeft,變小則為ToRight
  if (mCurrentLandscapeGyroValue.x < mLastLandscapeGyroValue.x)
  {
   LandscapeEGyroType = EGyroType.ToRight;
  }
  else
  {
   LandscapeEGyroType = EGyroType.ToLeft;
  }
  }
  else
  {
  if (mCurrentLandscapeGyroValue.y < mLastLandscapeGyroValue.y)
  {
   //當(dāng) z < 0 變?yōu)?nbsp;z > 0,若 x < 0 則為ToLeft,否則則為ToRight
   if (mCurrentLandscapeGyroValue.x > 0)
   {
   LandscapeEGyroType = EGyroType.ToLeft;
   }
   else
   {
   LandscapeEGyroType = EGyroType.ToRight;
   }
  }
  else
  {
   //當(dāng) z > 0 變?yōu)?nbsp;z<0,若 x< 0 則為ToRight,否則則為ToLeft
   if (mCurrentLandscapeGyroValue.x < 0)
   {
   LandscapeEGyroType = EGyroType.ToLeft;
   }
   else
   {
   LandscapeEGyroType = EGyroType.ToRight;
   }
  }
  }
 }
 mLastLandscapeGyroValue = mCurrentLandscapeGyroValue;
 
 SetPortraitValue();
 //Portrait
 if (IsEquals(mCurrentPortraitGyroValue.x, mLastPortraitGyroValue.x, false))
 {
  PortraitEGyroType = EGyroType.NoRotate;
  PortraitGyroDifference = 0;
 }
 else
 {
  PortraitGyroDifference = (int)(Mathf.Abs(mCurrentPortraitGyroValue.x - mLastPortraitGyroValue.x) * 60);
 
  if (mCurrentPortraitGyroValue.y < 0 && mLastPortraitGyroValue.y < 0)
  {
  //當(dāng) z< 0,y的值變大則為ToUp,變小則為ToDown
  if (mCurrentPortraitGyroValue.x < mLastPortraitGyroValue.x)
  {
   PortraitEGyroType = EGyroType.ToDown;
  }
  else
  {
   PortraitEGyroType = EGyroType.ToUp;
  }
  }
  else if (mCurrentPortraitGyroValue.y > 0 && mLastPortraitGyroValue.y > 0)
  {
  //當(dāng) z > 0,y的值變大則為ToDown,變小則為ToUp
  if (mCurrentPortraitGyroValue.x < mLastPortraitGyroValue.x)
  {
   PortraitEGyroType = EGyroType.ToUp;
  }
  else
  {
   PortraitEGyroType = EGyroType.ToDown;
  }
  }
  else
  {
  //當(dāng) z<0 變?yōu)?nbsp;z > 0,則為ToDown,反之則為ToUp
  if (mCurrentPortraitGyroValue.y < mLastPortraitGyroValue.y)
  {
   //>0 變 <0
   PortraitEGyroType = EGyroType.ToUp;
  }
  else
  {
   PortraitEGyroType = EGyroType.ToDown;
  }
  }
 }
 mLastPortraitGyroValue = mCurrentPortraitGyroValue;
 }
 
 //讀取gravity值
 public void SetLandScapeValue()
 {
 mCurrentLandscapeGyroValue.x = mGyro.gravity.x;
 mCurrentLandscapeGyroValue.y = mGyro.gravity.z;
 }
 
 public void SetPortraitValue()
 {
 mCurrentPortraitGyroValue.x = mGyro.gravity.y;
 mCurrentPortraitGyroValue.y = mGyro.gravity.z;
 }
 
 //前后兩次是否相等
 bool IsEquals(float a, float b, bool isLandscape)
 {
 if ((isLandscape && LandscapeEGyroType == EGyroType.NoRotate) || (!isLandscape && PortraitEGyroType == EGyroType.NoRotate))
 {
  if (Mathf.Abs(a - b) < 0.025f)
  {
  return true;
  }
 }
 if (Mathf.Abs(a - b) < mPrecision)
 {
  return true;
 }
 return false;
 }
}

接著我們寫個(gè)腳本GyroBase用于掛載在需要根據(jù)手機(jī)狀態(tài)偏移的組件上,用于設(shè)置偏移的參數(shù),以及對應(yīng)狀態(tài)下計(jì)算偏移的量

using System;
using UnityEngine;
 
public class GyroBase
{
 public float MaxValue;//大偏移值
 public float DefaultValue;//初始位置
 float mCurrentValue;//當(dāng)前偏移量
 
 public float Speed;//速度
 public float DuringTime;//等待間隔
 float mCurrentDuringTime;//當(dāng)前時(shí)間間隔
 
 public Action ValueChanged;//偏移事件
 
 public GyroManager mManager;
 
 float mBackSpeed;//回彈速度(一個(gè)減速過程)
 float BackSpeed
 {
 get
 {
  if (mBackSpeed > mMinSpeed)
  {
  mBackSpeed = Mathf.Max(mBackSpeed - Speed * mDeltaTime, mMinSpeed);
  }
  return mBackSpeed;
 }
 }
 
 float mMinSpeed;//最小速度
 float mDeltaTime;//Time.deltaTime
 
 bool mIsLandScape;//檢測手機(jī)水平轉(zhuǎn)動還是垂直轉(zhuǎn)動
 bool mIsResetBackProperty = false;
 
 //初始化賦值
 public void Init(float maxValue, float defaultValue, float speed, float duringTime, bool isLandscape, Action action)
 {
 MaxValue = maxValue;
 DefaultValue = defaultValue;
 Speed = speed;
 DuringTime = duringTime;
 mMinSpeed = Speed * 0.2f;
 mCurrentValue = DefaultValue;
 mIsLandScape = isLandscape;
 
 if (mIsLandScape)
 {
  mManager.LandscapeTransToDefault += TransToDefault;
  mManager.LandscapeTransToAdd += TransToAdd;
  mManager.LandscapeTransToReduce += TransToReduce;
 }
 else
 {
  mManager.PortraitTransToDefault += TransToDefault;
  mManager.PortraitTransToAdd += TransToAdd;
  mManager.PortraitTransToReduce += TransToReduce;
 }
 
 ValueChanged = action;
 }
 
 //事件清除
 public void Clear()
 {
 if (mIsLandScape)
 {
  mManager.LandscapeTransToDefault -= TransToDefault;
  mManager.LandscapeTransToAdd -= TransToAdd;
  mManager.LandscapeTransToReduce -= TransToReduce;
 }
 else
 {
  mManager.PortraitTransToDefault -= TransToDefault;
  mManager.PortraitTransToAdd -= TransToAdd;
  mManager.PortraitTransToReduce -= TransToReduce;
 }
 }
 
 //重設(shè)回彈參數(shù)
 void ResetBackProperty()
 {
 if (!mIsResetBackProperty)
 {
  mIsResetBackProperty = true;
  mBackSpeed = Speed * 0.8f;
  mCurrentDuringTime = 0;
 }
 }
 
 //手機(jī)沒轉(zhuǎn)動的時(shí)候,超過間隔時(shí)間則減速回彈至默認(rèn)位置
 void TransToDefault()
 {
 mIsResetBackProperty = false;
 mDeltaTime = Time.deltaTime;
 mCurrentDuringTime += mDeltaTime;
 if (mCurrentDuringTime > 1)
 {
  ValueToDefault();
  ValueChanged?.Invoke(mCurrentValue);
 }
 }
 
 //偏移增加
 void TransToAdd(int difference)
 {
 ResetBackProperty();
 ValueAddSpeed(difference);
 ValueChanged?.Invoke(mCurrentValue);
 }
 
 //偏移減小
 void TransToReduce(int difference)
 {
 ResetBackProperty();
 ValueReduceSpeed(difference);
 ValueChanged?.Invoke(mCurrentValue);
 }
 
 void ValueToDefault()
 {
 if (mCurrentValue > DefaultValue)
 {
  mCurrentValue = Mathf.Max(mCurrentValue - BackSpeed * mDeltaTime, DefaultValue);
 }
 else if (mCurrentValue < DefaultValue)
 {
  mCurrentValue = Mathf.Min(mCurrentValue + BackSpeed * mDeltaTime, DefaultValue);
 }
 }
 
 void ValueAddSpeed(int difference)
 {
 if (mCurrentValue < DefaultValue + MaxValue)
 {
  mCurrentValue = Mathf.Min(mCurrentValue + Speed * mDeltaTime * difference, DefaultValue + MaxValue);
 }
 }
 
 void ValueReduceSpeed(int difference)
 {
 if (mCurrentValue > DefaultValue - MaxValue)
 {
  mCurrentValue = Mathf.Max(mCurrentValue - Speed * mDeltaTime * difference, DefaultValue - MaxValue);
 }
 }
}

使用

例如,我們3D場景會隨手機(jī)的垂直轉(zhuǎn)動而上下偏移,我們可以通過旋轉(zhuǎn)攝像機(jī)的x軸來實(shí)現(xiàn),我們只需寫個(gè)簡單的腳本掛載在攝像機(jī)上即可

public class CameraGyro : MonoBehaviour
{
 public GyroManager mManager;
 
 Transform mTransform;
 Vector3 mCameraAngle;
 
 GyroBase mGyroBase;
 
 void Start()
 {
 mTransform = transform;
 mCameraAngle = Vector3.zero;
 
 mGyroBase = new GyroBase();
 mGyroBase.mManager = mManager;
 mGyroBase.Init(5, 0, 5, 1, false, Change);
 }
 
 void Change(float value)
 {
 mCameraAngle.x = value;
 mTransform.localEulerAngles = mCameraAngle;
 }
}

因?yàn)樽约汗こ痰腢I場景并不是所有UI都會隨手機(jī)水平翻轉(zhuǎn)而轉(zhuǎn)動,所以就不能直接通過攝像頭來解決,而需要移動需要偏移的UI部分,所以我們可以寫個(gè)組件只掛載在需要偏移的UI部分上

public class UIGyro : MonoBehaviour
{
 public GyroManager mManager;
 
 void Start()
 {
 GyroBase mGyroBase = new GyroBase();
 mGyroBase.mManager = mManager;
 mGyroBase.Init(80, transform.localPosition.x, 80, 1, true, Change);
 }
 
 void Change(float value)
 {
 transform.localPosition = new Vector3(value, transform.localPosition.y);
 }
}

這樣就大致實(shí)現(xiàn)了需要的效果了。

感謝各位的閱讀!關(guān)于“Unity中UI或3D場景怎么實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動效果”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


網(wǎng)站題目:Unity中UI或3D場景怎么實(shí)現(xiàn)跟隨手機(jī)陀螺儀的晃動效果-創(chuàng)新互聯(lián)
分享路徑:http://weahome.cn/article/copdph.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部