MeshMergerの魔力

Untiyで作業しているとき、同一マテリアルのオブジェクトをまとめるのにMeshMergerが使えます。

これは、複数のメッシュを実行時に1つにまとめてくれるスクリプトで、
オブジェクトが大量にあってDrawCallsが凄いことになっている場合に使えます。

Unify - MeshMerger
http://www.unifycommunity.com/wiki/index.php?title=MeshMerger

ビフォー :DrawCalls 351

アフター:DrawCalls 17

いやー、劇的ですね!
一概にDrawCallsを減らせばいいというものでも無いと思いますが、これだけ減ると気持ちがいいです。

UnityでDatabase.comにOAuth2.0する

Salesforce.comのDatabase.comにOauth2.0でログインする方法。

①はハマりどころ。
セキュリティーキーは、Database.comメニューの
My Personal Information→Reset My Security Tokenでボタンをクリックするとメールで送られてくる。

②、③は
App Setup→Develop→Remote Accessでアプリを登録して取得

void OnGUI ()
{
	if (GUILayout.Button ("Login")) {
		StartCoroutine (DoLogin ());
	}
}
	
	
private  string OAUTH_ENDPOINT = "/services/oauth2/token";
private  string REST_ENDPOINT = "/services/data";
	
IEnumerator DoLogin ()
{
	string url = "https://" + "na1.database.com" + OAUTH_ENDPOINT;
	
	WWWForm wf = new WWWForm ();
	string secKey = "<you api security key>";
	string username = "<your login account for database.com>";
	string password = "<your password for database.com>";
	string client_id = "<your Consumer Key>";
	string client_secret = "<your Consumer Secret>";

	wf.AddField ("grant_type", "password");
	wf.AddField ("username", username);
	wf.AddField ("password", password+secKey); //パスワード+API セキュリティーキー  → ①
	wf.AddField ("client_id", client_id); //→②
	wf.AddField ("client_secret", client_secret); //→③
	
	WWW www = new WWW (url, wf);

/*
	//XMLで取得する場合
	Hashtable h = new Hashtable ();
	h ["Accept"] = "application/xml";
	WWW www = new WWW (url, wf.data, h);
*/

	yield return www;
		
	Debug.Log (www.error);
	Debug.Log (www.text); //www.text にJSONでaccess_tokenなどが返ってくる
}


簡単にクラウドでデータベース使うならDatabase.comはすごい便利なんじゃないかと推測中。

UnityでInput.GetButtonをエミュレートできるようにする

PlatformControllerなどをつかうと、Input.GetButton("Jump")みたいなのがいっぱい使われています。
で、GUIのボタンを押したらジャンプとかしようと思って、Input.SetButtonDownとかやりたいのですが、そんなものはありません。

ということで探していると、フォーラムにInputBrokerとか作ればいいんじゃね?っていうエントリがあったので作って見ました。

#pragma strict

	private static  var buttons : ArrayList = new ArrayList();
	private static  var upButtons : ArrayList = new ArrayList();
	private static  var downButtons : ArrayList = new ArrayList();
	
	private static var lastFrame:int =-1;

	private static function Clean () :void
	{
		if ( lastFrame >0 && Time.frameCount > lastFrame + 1) {
			upButtons.Clear ();
			downButtons.Clear ();
			lastFrame = -1;
		}
	}
	
	function Update(){
		Clean();
	}

	 static function GetButton (s:String) : boolean
	{
		
		return buttons.Contains (s) || Input.GetButton (s);
	}

	 static function GetButtonDown (s:String) : boolean
	{
		return downButtons.Contains (s) || Input.GetButtonDown (s);
	}

	 static function GetButtonUp (s:String) : boolean
	{
		return upButtons.Contains (s) || Input.GetButtonUp (s);
	}

	 static function SetButtonDown ( s:String ) : void
	{
		lastFrame = Time.frameCount;
		downButtons.Add (s);
		buttons.Add (s);
	}

	 static function SetButtonUp ( s:String ) :void
	{
		lastFrame = Time.frameCount;
		buttons.Remove (s);
		upButtons.Add (s);
	}

このスクリプトをInputBroker.jsとかの名前で保存(Standard Assets配下に置くのがいいかな?)します。
で、シーンに空のオブジェクトを作ってそこにアタッチ。
あとは、Input.GetButtonやInput.GetButtonDownを、InputBroker.GetButton, InputBroker.GetButtonDownに置換すれば完成。

これで、任意のタイミングでInputBroker.SetButton("Jump")とかすると、ジャンプのボタンを押したことになります。


もっといい方法がある?のかな?

AndroidでInstagramからフィードを取得

Instagram APIを触ってみるということで、Androidのサンプルアプリを作りました。OAuth2.0になって便利ですが、httpsの認証がオレオレ認証局で、それの対応が面倒でした。

コードはこちら。
https://github.com/shinobushiva/InstagramFeedView

Unity3.4 + Androidでスクリーンキャプチャ

Untiy3.4 + Androidの環境では
Application.CaptureScreenshot("screenshot.png");
スクリーンショットを取ると、
保存されたPNGファイルが壊れるという現象が起こります。


これは、既知のバグであり3.5 beta1では修正されているようですが、
急ぎで必要だったためJPGで保存する回避策を試してみました。


JPGへのエンコードにはUnityのフォーラムで提供されているJPGEncoderを使います。
http://forum.unity3d.com/threads/31737-Convert-PNG-to-JPG-without-writing-to-disk


これを使ってスクリーンショットを取るJPGScreenShot.csスクリプトを作成しました。

using UnityEngine;
using System.Collections;
using System.IO;

public class JPGScreenShot : MonoBehaviour
{

	// Use this for initialization
	void Start ()
	{
		Debug.Log ("Taking JPGScreenShot");
		StartCoroutine (ScreenShot ());
	}

	IEnumerator ScreenShot ()
	{
		// エンコーダに渡すテクスチャの作成
		Texture2D tex = new Texture2D (Screen.width, Screen.height, TextureFormat.RGB24, false);
		// バッファをテクスチャに書きこむ
		tex.ReadPixels (new Rect (0, 0, Screen.width, Screen.height), 0, 0);
		tex.Apply ();
		
		// split the process up--ReadPixels() and the GetPixels() call inside of the encoder are both pretty heavy
		yield return new WaitForSeconds (0.1f);
		
		// エンコーダ作成
		JPGEncoder encoder = new JPGEncoder (tex, 75.0f);//
		// エンコード開始
		encoder.doEncoding();
		
		// エンコード終了まで待機
		while (!encoder.isDone) {
			yield return new WaitForSeconds (1f);
		}
		
		// ファイル書き出し
		Debug.Log ("Write to : " + Application.persistentDataPath + "/screenshot.jpg");
		File.WriteAllBytes (Application.persistentDataPath + "/screenshot.jpg", encoder.GetBytes ());
		
	}
}


呼び出しは、こんな感じで。

    //Javascriptから
    (new GameObject()).AddComponent("JPGScreenShot");
    //C#スクリプトから
    (new GameObject()).AddComponent(tyepof(JPGScreenShot));


きっとすぐに3.5が出るのであんまり使う機会はないかも。。。
取り敢えずメモ。

追記:
これを使うには、JPGEncoder.csが必要です。
ダウンロードはこちらから
http://bit.ly/jpgencoder

UnityからAndroidのインテントを呼び出す

UnityからAndroidのメソッド(なんかおかしな言い方だが気にしない、、、)を呼び出すには、
AndroidJavaObject#Callが使えるのですが、
戻り値がプリミティブじゃない場合の呼び出し方で悩んだので記録しておきます。


Unity - Scripting API: AndroidJavaObject.Call


戻り値無しなら

AndroidJavaObject#Call("method name", args[]);


戻り値int型ならジェネリクスを使って

AndroidJavaObject#Call<int>("method name", args[]);

と言う感じで、ドキュメントにあります。


で、戻り値がプリミティブじゃないときは書いてなかったので、試行錯誤しました。

AndroidJavaObject.Call<AndroidJavaObject>("method name", args[]);

と言うふうに、AndroidJavaObjectを指定してやればいいようです。


解れば当然なのですが、、、


ということで、UnityからAndroidのSENDインテントを呼び出してみるコードはこんな感じ。

// Find the UnityPlayer and get the static current activity
AndroidJavaClass cUnityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject oCurrentActivity = cUnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity");
		
// Get defenitions of Intent and it's constructor.
AndroidJavaObject oIntent = new AndroidJavaObject ("android.content.Intent");
// Call some methods
oIntent.Call<AndroidJavaObject> ("setAction", "android.intent.action.SEND");
oIntent.Call<AndroidJavaObject> ("setType", "text/plain");
oIntent.Call<AndroidJavaObject> ("putExtra", "android.intent.extra.TITLE", "Hello");
// Start the activity!
oCurrentActivity.Call ("startActivity", oIntent);

//Dispose them. Not sure if I need to do it or not...
oIntent.Dispose ();
oCurrentActivity.Dispose ();

Unityだけで完結できて、結構短いコードでもいけるので良い感じ。

UnityマスターブックARをリリースしました

Unityマスターブックの表紙で遊べるARゲームを作って見ました。
https://market.android.com/details?id=jp.ac.sojou.cis.izumi.unity.masterbook.ar&feature=search_result

本の表紙を認識して、クロックが出現します。


ARライブラリはQCARを使っています。
https://ar.qualcomm.at/qdevnet/


ARがこんなに手軽に使える時代になってしまったとは、、、