簡體   English   中英

統一計算設備的位移

[英]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);
    }
}

問題:

隨設備移動時,我的代碼無法始終按預期工作;

  • 有時候,當我向前移動(在設備的+ ve Z軸上)時,對象也會向前移動,但是有時它根本不會移動。
  • 有時,當我仍然處於自己的位置時,對象會自行移動。
  • 有時,當我向前移動並突然停止時,對象不會停止。

我的問題:

  • 是由於設備的准確性引起的那些奇怪的行為,還是我的代碼中缺少某些東西。
  • 如果我的代碼中缺少某些內容,那是什么?
  • 我搜索了很多有關獲得設備最精確位置的方法,然后發現我可以將GPS與加速度計集成在一起,如何才能統一使用我的代碼呢?

移動基於加速度,因此取決於您旋轉設備的速度。 這也是為什么對象在停止時不會停止的原因。 突然停止設備會產生很大的加速度,然后加速度會加到對象平移的數量上,這會使它移動的距離比預期的要大得多。

我認為使用陀螺儀的姿勢而不是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM