![](/img/trans.png)
[英]Unity Shader graph vertex displacement not working on mesh created at runtime
[英]Calculate the displacement of device in unity
我正在統一制作3D游戲,對象應隨着android設備在Z軸上的移動/加速而前后移動。 即。 當玩家在+ ve Z軸方向上移動設備時,對象應向前移動,而當玩家在-ve Z軸方向上移動設備時,對象應向后移動。
該游戲是多人游戲,玩家將在大型足球場中移動。
我的想法是使用加速度計來計算設備的加速度,然后對加速度數據進行積分以獲得Z軸上的設備速度。 並使用速度移動設備。
使用這個方程式
V 2 = V 1 +ΔA。 ΔT
哪里
V 2 :最終速度。
V 1 :初始速度。
ΔA :初始加速度和最終加速度之差。
ΔT :初始時間和最終時間之間的差。
最初,我嘗試使用運動學方程式來計算最終速度,但后來我意識到只有在加速度恆定的情況下才可以使用它。 因此,我一個研究物理學的朋友微分了這個方程,讓我在加速度可變時使用它。
我知道在計算精確位移時會出現一些誤差,並且積分加速度后誤差會增加,但是對於我的應用程序來說,這很小的誤差是可以的。 我最初以為是使用GPS而不是加速度計,但我發現GPS精度將低於傳感器。
我也知道一段時間后誤差會非常高,因此我每10秒重置一次加速度和速度值。 我還使用低通濾波器來減少傳感器的噪聲。
public class scriptMove : MonoBehaviour
{
const float kFilteringFactor = 0.1f;
public Vector3 A1;
public Vector3 A2;
public Vector3 A2ramping; // for the low-pass filter
public Vector3 V1;
public Vector3 V2;
public int SpeedFactor=1000; //this factor is for increasing acceleration to move in unity world
void resetAll()
{
Input.gyro.enabled = true;
A2 = Vector3.zero;
V1 = Vector3.zero;
V2 = Vector3.zero;
A2ramping = Vector3.zero;
}
// Use this for initialization
void Start()
{
InvokeRepeating("resetAll", 0, 10);
}
//http://stackoverflow.com/a/1736623
Vector3 ramping(Vector3 A)
{
A2ramping = A * kFilteringFactor + A2ramping * (1.0f - kFilteringFactor);
return A - A2ramping;
}
void getAcceleration(float deltaTime)
{
Input.gyro.enabled = true;
A1 = A2;
A2 = ramping(Input.gyro.userAcceleration) * SpeedFactor;
V2 = V1 + (A2 - A1) * deltaTime;
V1 = V2;
}
//Update is called once per frame
void Update()
{
getAcceleration(Time.deltaTime);
float distance = -1f;
Vector3 newPos = transform.position;
transform.Translate(Vector3.forward * Time.deltaTime * V2.z * distance);
}
}
隨設備移動時,我的代碼無法始終按預期工作;
移動基於加速度,因此取決於您旋轉設備的速度。 這也是為什么對象在停止時不會停止的原因。 突然停止設備會產生很大的加速度,然后加速度會加到對象平移的數量上,這會使它移動的距離比預期的要大得多。
我認為使用陀螺儀的姿勢而不是userAcceleration對您來說可能更容易。 姿態返回設備旋轉的四元數。 https://docs.unity3d.com/ScriptReference/Gyroscope-attitude.html
(您必須做一些實驗,因為我不知道姿態是什么(0,0,0,0)。這可能意味着該設備是平放在桌子上的,或者是側向放置)保持在您面前,或者僅僅是應用程序首次啟動時設備的方向,我不知道Unity是如何初始化它的。)
一旦有了四元數,就應該能夠根據用戶旋轉設備在任一方向上的距離直接調整速度。 因此,如果它們旋轉+ ve Z軸,則將向前移動;如果它們移動更多,則將移動得更快;如果它們移動-ve Z軸,則會使其變慢或向后移動。
關於GPS坐標,您需要為此使用LocationService。 http://docs.unity3d.com/ScriptReference/LocationService.html您需要啟動LocationServices,等待它們初始化(這一點很重要),然后您可以使用LocationService.lastData查詢不同的部分
我正在嘗試與您做同樣的事情。 僅使用一個傳感器來獲得設備的線性加速度並非易事。 您將需要同時使用加速度計和陀螺儀(傳感器融合)來實現解決方案。 Google有一個針對Android的解決方案,根據您設備的復雜程度,其行為會有所不同。 它使用多個傳感器以及低/高通濾波器(請參閱Android TYPE_LINEAR_ACCELERATION傳感器-它顯示什么? )。 Google的Tango平板電腦應具有傳感器來解決此類問題。
如果要在Unity中獲取加速度計數據,請嘗試:
public class scriptMove : MonoBehaviour{
private float accelX;
private float accelY;
private float accelZ;
void Update(){
accelX = Input.acceleration.x;
accelY = Input.acceleration.y;
accelZ = Input.acceleration.z;
//pass values to your UI
}
}
我目前正在嘗試使用IKVM將Google解決方案移植到Unity。
該鏈接可能也很有用: Unity3D-通過GPS數據獲得平穩的速度和加速度
我不知道您是否仍然需要它,但是如果將來有人需要,我會發布我發現的內容:
當我第一次使用Unity加速度計時,我以為輸出只是設備的旋轉,從某種程度上來說,它的輸出是,但不止於此,它可以為我們提供加速度,但要獲得該值,您必須過濾重力,然后才能獲得值。
我為Android創建了一個插件,並獲得了Android的Accelerometer和Linear Accelerometer,標准的Accelerometer給我們提供了與Unity accelerometer相似的值,主要區別在於它是原始的,而unity給我們一些精致的輸出,例如,如果您的游戲是Landscape unity會自動反轉X和Y軸,而Android原始信息不會。 線性加速度計是包括標准加速度計在內的傳感器的融合,輸出是沒有重力的加速度,但速度卻很糟糕,而(Unity和Android)兩個加速度計每幀都更新一次,線性加速度計每4到5更新一次確定用戶體驗的糟糕程度。
但是選擇Android插件很棒,因為它為如何解決我從Unity Accelerometer消除重力的問題提供了可能,您可以在這里找到: https : //developer.android.com/reference/android/hardware/SensorEvent.html Sensor.TYPE_ACCELEROMETER
如果我們傾斜設備,Unity Accelerometer會為您提供一個值,例如6,而當您保持在該位置時,這不是波浪,如果您以極快或極慢的速度向后傾斜,它將得到6的值。到0(假設您移回零),我想要並用下面共享的代碼完成的操作是:當您將其旋轉時,將加速度波動並返回零,因此,加速度減速度曲線為轉動得很慢,返回的加速度幾乎為零,如果轉動得很快,響應將反映該速度。 如果這是您要尋找的結果,則只需創建此類:
using UnityEngine;
public class AccelerometerUtil
{
public float alpha = 0.8f;
public float[] gravity = new float[3];
public AccelerometerUtil()
{
Debug.Log("AccelerometerUtil Init");
Vector3 currentAcc = Input.acceleration;
gravity[0] = currentAcc.x;
gravity[1] = currentAcc.y;
gravity[2] = currentAcc.z;
}
public Vector3 LowPassFiltered()
{
/*
https://developer.android.com/reference/android/hardware/SensorEvent.html
gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
linear_acceleration[0] = event.values[0] - gravity[0];
linear_acceleration[1] = event.values[1] - gravity[1];
linear_acceleration[2] = event.values[2] - gravity[2];
*/
Vector3 currentAcc = Input.acceleration;
gravity[0] = alpha * gravity[0] + (1 - alpha) * currentAcc.x;
gravity[1] = alpha * gravity[1] + (1 - alpha) * currentAcc.y;
gravity[2] = alpha * gravity[2] + (1 - alpha) * currentAcc.z;
Vector3 linearAcceleration =
new Vector3(currentAcc.x - gravity[0],
currentAcc.y - gravity[1],
currentAcc.z - gravity[2]);
return linearAcceleration;
}
}
有了此類后,只需將其創建到您的MonoBehaviour中:
using UnityEngine;
public class PendulumAccelerometer : MonoBehaviour
{
private AccelerometerUtil accelerometerUtil;
// Use this for initialization
void Start()
{
accelerometerUtil = new AccelerometerUtil();
}
// Update is called once per frame
void Update()
{
Vector3 currentInput = accelerometerUtil.LowPassFiltered();
//TODO: Create your logic with currentInput (Linear Acceleration)
}
}
請注意,將要實現關於MonoBehaviour的TODO,由您決定如何處理該值的算法,就我而言,我發現創建圖形輸出並在寫入之前分析加速非常有用。
真的希望能有所幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.