【EasyAR學習】縮放和拖動模型

        開發AR手機端軟件時,雙手縮放、拖動模型是最多見的功能,也是一種最基本的交互手段。
        在 Unity 中想要獲取用戶的鍵盤或鼠標的事件的話,就必須使用 Input 類來獲取。通常來講 Input 類的方法須要寫在 Update() 方法中。
        查看Unity的API手冊,能夠看到經常使用的Input類方法:
        一、與鼠標有關的Input類方法:
        (1)Input.GetMouseButton(0)表示「鼠標左鍵按下」;
        Input.GetMouseButton(1)表示「鼠標右鍵按下」;
       Input.GetMouseButton(2)表示「鼠標中鍵按下」。
        二、與觸碰有關的Input類方法:
        (1)Input.touchCount表示「觸碰數量」;
        (2)Input.GetTouch(0) 表示「當第一隻手指觸碰時」;
                【Input.GetTouch(1)表示第二隻手觸碰;Input.GetTouch(2)表示第三隻手觸碰;……以此類推】
        (3)TouchPhase 表示「觸碰狀態」。有如下5中狀態:
                ①Began :按下;
                ②Moved :移動;
                ③Stationary :按住但沒移動;
                ④Ended :離開;
                ⑤Canceled :用於觸碰超過5點以上或貼至臉上時取消追蹤。
        (4)Input.GetTouch(0).position 表示「取得第一隻手指觸碰時的座標」。

  接下來,就在【EasyAR---顯示模型】的基礎上,實現縮放、拖動模型。android

1、縮放模型windows

        在模型Cube上掛載一個C#腳原本實現該功能,命名爲「Gesture.cs」,腳本的路徑爲「Assets/Test1/Scripts/」。腳本代碼以下:
ide

using System.Collections;
using UnityEngine;

public class Gesture : MonoBehaviour {

    private Touch oldTouch1;  //上次觸摸點1(手指1)
    private Touch oldTouch2;  //上次觸摸點2(手指2)

    void Update()
    {
        //沒有觸摸,就是觸摸點爲0
        if (Input.touchCount <= 0)
        {
            return;
        }

        //多點觸摸, 放大縮小
        Touch newTouch1 = Input.GetTouch(0);
        Touch newTouch2 = Input.GetTouch(1);

        //第2點剛開始接觸屏幕, 只記錄,不作處理
        if (newTouch2.phase == TouchPhase.Began)
        {
            oldTouch2 = newTouch2;
            oldTouch1 = newTouch1;
            return;
        }

        //計算舊的兩點距離和新的兩點間距離,變大要放大模型,變小要縮放模型
        float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);//Vector2表示2D的向量和點。
        float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);

        //兩個距離之差,爲正表示放大手勢, 爲負表示縮小手勢
        float offset = newDistance - oldDistance;

        //放大因子,一個像素按 0.01倍來算(100可調整)
        float scaleFactor = offset / 100f;

        Vector3 localScale = transform.localScale;////Vector3表示3D的向量和點,Transform.localScale表示自身縮放.
        Vector3 scale = new Vector3(localScale.x + scaleFactor,
            localScale.y + scaleFactor,
            localScale.z + scaleFactor);

        //在什麼狀況下進行縮放,最小縮放到0.05倍
        if (scale.x >= 0.05f && scale.y >= 0.05f && scale.z >= 0.05f)
        {
            transform.localScale = scale;
        }

        //記住最新的觸摸點,下次使用
        oldTouch1 = newTouch1;
        oldTouch2 = newTouch2;
    }
}
2、拖動模型

        一樣在模型Cube上掛載一個C#腳原本實現該功能,命名爲「Drag.cs」,腳本的路徑爲「Assets/Test1/Scripts/」。腳本代碼以下:ui

using System.Collections;
using UnityEngine;

public class Drag : MonoBehaviour {
    //定義私有變量
    private Vector3 _vec3TargetScreenSpace;// 目標物體的屏幕空間座標

    private Vector3 _vec3TargetWorldSpace;// 目標物體的世界空間座標

    private Transform _trans;// 目標物體的空間變換組件

    private Vector3 _vec3MouseScreenSpace;// 鼠標的屏幕空間座標

    private Vector3 _vec3Offset;// 偏移

    void Awake()
    {
        _trans = transform;
    }

    IEnumerator OnMouseDown() //迭代器接口
    {
        // 把目標物體的世界空間座標轉換到它自身的屏幕空間座標
        _vec3TargetScreenSpace = Camera.main.WorldToScreenPoint(_trans.position);

        // 存儲鼠標的屏幕空間座標(Z值使用目標物體的屏幕空間座標)
        _vec3MouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _vec3TargetScreenSpace.z);

        // 計算目標物體與鼠標物體在世界空間中的偏移量
        _vec3Offset = _trans.position - Camera.main.ScreenToWorldPoint(_vec3MouseScreenSpace);

        // 鼠標左鍵按下
        while (Input.GetMouseButton(0))
        {
            // 存儲鼠標的屏幕空間座標(Z值使用目標物體的屏幕空間座標)
            _vec3MouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _vec3TargetScreenSpace.z);

            // 把鼠標的屏幕空間座標轉換到世界空間座標(Z值使用目標物體的屏幕空間座標),加上偏移量,以此做爲目標物體的世界空間座標
            _vec3TargetWorldSpace = Camera.main.ScreenToWorldPoint(_vec3MouseScreenSpace) + _vec3Offset;

            // 更新目標物體的世界空間座標
            _trans.position = _vec3TargetWorldSpace;

            // 等待固定更新
            yield return new WaitForFixedUpdate();
        }
    }
}

3、打包成apk文件spa

        點擊「File→Build Settings」,彈出以下界面,點擊「Add Open Scenes」將場景添加進來,而後選擇Android平臺,先點擊「Switch Platform」切換平臺,再點擊「Player Settings」進行播放器設置。
3d


設置以下:
①「Company Name」 與咱們申請key時的公司或團隊名相同(好比我申請時填的是:nuanyang), 
②「ProductName」 也要和咱們申請key時填的應用名相同(本次的項目演示爲:Test1)。
③「Other Settings」選項裏面,將「Auto Graphics API」後面複選框的√去掉,「Graphics APIs」 選擇「OpenGLES2」;
④「Other Settings」選項裏,「Identification」下的「Package Name」和「Minimum API Level」也要修改。
code

⑤在「Publishing Settings」選項下的「Keystore password」中填寫申請的key。orm

  



        而後點擊「Build」,選擇已經安裝的Android SDK文件夾「android-sdk-windows」,進行打包。在手機上安裝並運行已經打包好了的Test.apk,運行效果以下。
blog


        運行出現的問題:運行後,發現能夠實現放大和縮小功能,沒法拖動物體。上網查了一下資料,發現是Box collider碰撞器的範圍沒有設置,只有一個點。接口

        解決辦法:點擊Edit Collider,把碰撞器的範圍設置成以下圖所示,就好了。

             

        再次打包並運行,就能夠實現拖動模型的功能了。