用 Unity 開發 Google Glass 應用簡易基礎教學

小樽拿到Google Glass已經超過一年,也做了些開發,也發現了許多問題,基本上可以理解為何Google原先定下2014要普及化的豪語至今悄悄的沒有下文,不過分析留待有機會再說吧

glass14

小樽之前由於計畫案的關係,設計過一款基於智慧型眼鏡的,以文化保存與發展為目標的遊戲化 (Gamification) 的適地性服務 (LBS) APP,概念的簡易原型影片如下

當然由於時間和經費有限,在結案時並沒有辦法作到這麼炫,但是基於這項設計所需要的一些基礎技術,包含 Google Glass + iBeacon 實現室內定位與互動的技術,在小樽網羅的團隊強大夥伴們共同努力下,事實際有被完成的唷,而且這個遊戲的手機板原形也有真的作出來,雖然計畫已經結束所以已經沒有額外的費用可以繼續把原型更完整化,但是不用擔心,小樽個人一定會想辦法把最終版的程式開發完,希望研究成果能真的能造服環境,好~碎碎念就到此,基於這個計畫開發過程中,團隊有研究是否能將Unity發佈的Android apk移植給Glass用,如果可以將省去很多原型開發的力氣-至少對於遊戲畫面如何Render和GUI的製作可以省去非常多力氣,但是有 Glass 的人就已經很少了,更別提同時會製作Unity又有眼鏡的團隊,所以網路上當然找不到資料啦~官網也不會有囉,但是小樽運氣很好,找到一位非常強大的台大資工強者成鑫大大,他原本就會寫glass的原生程式,有提供可能的一些線索,小樽就到Unity中找對應可能銜接作輸入的指令,很幸運的在一個晚上找到了可以讓Glass觸控版輸入到Unity中的方法,並且也成功將發佈的apk安裝到Glass中測試無誤,謙虛的成鑫大大覺得這沒有甚麼了不起大家都作的到,但是對小樽來說已經太猛了~而基於我們都沒有覺得需要藏私甚麼-越多人會就有機會讓更多人一起開發作出更多好東西,也有機會認識更多強者朋友,於是由小樽彙整寫出此篇教學,讓之後有需要的朋友們可以參考

首先,Google Glass受限於輸入的模式以語音和側邊觸控板為主,官方語音系統目前只接受英文,並且有干擾各種問題,用側面觸控版控制是比較可行的方案,但是觸控手勢的指令並不直接對應Android行動裝置系統的確認/返回/前後滑及HOME,後來發現需要以比照觸控面板的輸入模式,自己判斷手勢滑動的”觸控點數”和”位移座標”在Unity中寫入上述事件,因此在本範例中,我們將glass觸控版偵測到的觸碰行為,以作標的形式透過GUI顯示在畫面中,首先我們打開一個新的Unity專案,並在攝影機上寫入一個c#的Script內容如下,比較關鍵的地方小樽以經有寫註解:

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour {


	GUIStyle style;
	string text;
	// Use this for initialization
	void Start () {
		initialStyle();
	}

	// Update is called once per frame
	void Update () {
		if(AndroidInput.touchCountSecondary > 0){ //如果有偵測到觸控點
			text = "x:"+
			AndroidInput.GetSecondaryTouch(0).position.x+"ny:"+ //顯示X作標
			AndroidInput.GetSecondaryTouch(0).position.y; //顯示Y作標
		}else{
			text = "no touch";
		}
	}

	void OnGUI(){
		GUI.Label(new Rect(0,0,Screen.width,Screen.height),text,style);
	}

	private void initialStyle(){
		style = new GUIStyle();
		style.fontSize = 60;
		style.normal.textColor = Color.white;
		style.alignment = TextAnchor.MiddleCenter;
	}

}

其中偵測到處控點那邊,意思是如果有一個或以上的手指觸碰行為發生則執行顯示作標的顯示,因此如果想寫多點處控行為可以自己改寫,其他程式碼小樽就不解釋了,如果完全看不懂可以配合Help查閱喔

寫完以後要進行發佈,發佈的時候有幾個要注意的關鍵步驟,請來到Android發佈設定作調整

首先因為Glass是橫向的顯示,預設的顯示配置請選擇橫向 (如下),否則發佈到Glass你會看到只有中間1/3的畫面

glassUnity1

其次關於app name的部份,Bundle Identifier請確認與你原本設定的company Name和Product Name有一致,雖然說有時候沒有對應也沒關係,但是建議還是一致比較保險,最下面的API最低版本請選Android 4.4 (因為對應當前Glass的Android版本)

glassUnity2

由於我們要發佈進Glass還需要透過Android的IDE作一些修正,所以請勾選發佈成Google Android Project的形式,之後便會發佈出一個專案資料夾

glassUnity3

到上面為止是在Unity中要完成的步驟,接下來我們需要透過Android的編譯器來修改apk的進入點來符合Glass的需求,關於安裝Android Studio或使用Eclipse+Android SDK的部份看個人喜好都可以,完全沒有使用過的朋友可能要先去Google一下基本安裝和環境設定,小樽這裡就不贅述

下小樽是透過Eclipse來完成後面動作,我們要從一個已經存在的Android專案來開啟新專案如下

glassUnity4

下一步以後選擇我們剛剛從Unity發佈出來的專案,另外請確認你的SDK裡面已經有安裝4.4.2的Glass Development Kit Preview 這項,如下圖,否則你沒辦法發佈程式到眼鏡裡喔

glassUnity5_SDK

將從專案的屬性設定中將Android library改為”Glass Development Kit Preview” 4.4.2

glassUnity6

在專案的 AndroidManifest.xml 中,原始的code排版跟沒排一樣很難閱讀,可以用快速鍵 ctrl+shift+f 自動整理,接下來步驟(或參閱文章最後的整篇原始碼):

去掉android:debuggable=”false”

加入

(1)

<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT"/>

(2)

android:theme="@android:style/Theme.DeviceDefault"

(3)

<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />

(4)

<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="@xml/voiceinput_trigger" />

完成上述步驟後,建立一個叫voiceinput_trigger的xml檔,內容複製下方貼上

<?xml version="1.0" encoding="utf-8"?>
<trigger keyword="@string/voice_trigger">


    <!--other voice input -->
<!--
    <input prompt="@string/gesturedemo_voice_prompt" />
-->

<!-- what a need in my app, if not access,it will disable this app -->
<!--
    <constraints camera="true" network="true" microphone="true" />
    <constraints network="true" microphone="true" />
-->

</trigger>

將這個 voiceinput_trigger.xml 放入res/xml 裡(如果沒有這個資料夾自己建一個)

在res/values/strings.xml加入進入點,app name請填入你自己的app name

<string name="voice_trigger">app name</string>

 

完成後選擇要發佈的裝置~請接上你的Glass,如果SDK有正確安裝應該是會找到如下

glassUnity7

按下確定~大功告成,程式就會Compiler到你的Glass中,可以用點選或語音(當然是英文)的方式啟動你寫好的APP囉,如果你使用本教學中的觸控案例,你會看到當手碰到測版的時候畫面顯示作標的變化值,剩下的就交由各位自行發展啦~

在次感謝成鑫大大耐心的教學 😀

===

補充: 成鑫大大建議把整個AndroidManifest.xml開放給大家看比較清楚 內容如下 特別注意 App name請用自己的唷~

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Company.GoogleGlassInputSample"
    android:installLocation="preferExternal"
    android:theme="@android:style/Theme.NoTitleBar"
    android:versionCode="1"
    android:versionName="1.0" >

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <application
        android:icon="@drawable/app_icon"
        android:label="@string/app_name" >
        <activity
            android:name="com.Company.GoogleGlassInputSample.UnityPlayerNativeActivity"
            android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:theme="@android:style/Theme.DeviceDefault"
            android:screenOrientation="landscape" >
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>

            <meta-data
                android:name="unityplayer.UnityActivity"
                android:value="true" />
            <meta-data
                android:name="unityplayer.ForwardNativeEventsToDalvik"
                android:value="false" />

            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voiceinput_trigger" />
        </activity>
    </application>
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT"/>
    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="20" />

    <uses-feature android:glEsVersion="0x00020000" />

</manifest>