UniRx

最近になって、Reactive Extensions通称Rxというのが気になってたのですがUnityにもUniRxというのがあるので試してみた。
C#で実装されている機構なんだけどこの機能はLINQとの関連が深いのでまずはLINQをある程度理解していないといけない。
そもそもC#でデータの問い合わせをするにはLINQ以前は

IEnumerable<Character> q =
	from c in Characters
	where c.hp >= 100
	select c;

こんな感じでプログラムとは分離されたSQL的な書き方をしていたらしい。
それがLINQを使うと

IEnumerable<Character> q = this.Customers
				.Where(c => c.City == "London")
				.Select(c => c);

こんな感じで、見やすいメソッドになる。
データベースに限らずデータの集合(XMLやJSON)なども同じ機構で扱えるようにしたのがLINQ to XMLやらLINQ to JSONというものらしい。
C#のIEnumerable<T>の型に対してLINQが適応できて、例えばListのようなデータに対して偶数(Where)のものを3つ(Take)取得するとすると。

List<int> list = new List<int>(){1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
IEnumerable<int> numsEnumerable = list.Where(_ => _ % 2 == 0).Take(3);
foreach (int num in numsEnumerable) {
	Debug.Log(num); // 2, 4, 6
}

こんな感じになる。
データの最大値を取得したり、平均を算出したりなどデータ群に対して抽出や操作ができる。
参考)
地平線に行く | LINQの拡張メソッド一覧と、ほぼ全部のサンプルを作ってみました。

C#の強みはLINQと言われているくらいなんだけど、どうもUnityではiOSに書き出した際に落ちることがあるらしい。詳細はこちら
Qiita | やっぱりUnityでもC#なんだからLINQが使いたい!

LINQはデータ群を扱う為のものですが、「イベントもタイムライン上で順番に並べるとそれも一つの配列と見なせ、LINQのような機構をつかってイベントをフィルタリングやデータを操作できますよね。」っていう変態的な考えを誰かが考えた!それがReactive Extensions。
JavaScriptですがこちらの記事がわかりやすい。
LIG Inc | 「RxJS」初心者入門 – JavaScriptの非同期処理の常識を変えるライブラリ

最初にMicrosoft DevLabsに2009年に登場したようでまだ新しい技術ですね。これがだんだんとjsやphpなどでも広がっていき言語を超えた機構として広まっているみたいです。

LINQもまったく使ったことがなかったので、LINQも含め幾つかのサンプルを作ってUniRxを試してみた。
(1つ落ちるサンプルがあるけど、なにか間違っているのかな…?)
あとは開発者さんのところで開催された勉強会の資料なんかも読むと良さそうです。

第一回UniRx勉強会を開催しました+スライドまとめ

LINQのSelectManyは理解に時間がかかったけど、こちらを参考に勉強した。
[C#・LINQ]九九だけじゃない!アプリ開発にもゲーム開発にも使える、SelectMany!
Rxの場合はSelectManyはストリームの流れを変えるようなときに使われるって感じでしょうか。

Continue…

Androidに書き出したアプリのログを確認する方法

android_device_monitor

Unityで書き出したものをAndroid端末で見る際にログが見たいなと思い調べてみました。
Android端末にかき出すためにAndroidのSDKを入れたと思うんですがそのSDKのtoolsの中にmonitorというアプリがあるのでこちらを立ち上げればAndroidのすべてのログが確認できます。

参考)

アニメーションのマスク

layer_mask

アニメーションで歩いているキャラに手を上げさせたい場合、別途手を上げて歩いているアニメーションを作るといろいろと大変になってくるのでマスクするにはどうしたらいいのかなと思ったらMecanimにLayerという概念があった。
ちょっとテキトーなキャラを作って動かしてみたところできた。

Animator上でLayerを追加するとLayerの設定に、weightというのがあってこいつが他のレイヤーとの動きの重みとなっている。Maskというのは3Dオブジェクトのどの部分を指すかというオブジェクトでAssetsにCreate => Avatar Maskで作成できる。Humanoidの場合はパーツを選べばいいし、独自の3Dパーツであれば指定したAvatarからボーンの構造を選んで指定できる。Layerの設定に今回であれば右腕だけをマスクしたAvatar Maskを設定してweightを変えれば歩きながら右腕をあげる動きの完成。Blendingはマスクしたパーツの動きを上書きするかどうか(Override)、もしくは重ねるか(Additive)が選べる。Syncを選択すると選択したレイヤーと同じステートマシーンの構造が作られるので手をあげるでも、歩いている時走っているときなどで変えたい時にいいのかな。

参考)Unity | アニメーションレイヤー

Unityのサンプルプロジェクト

Unityをインストールするときにサンプルプロジェクトを入れるかどうか聞かれるので、インストールしてみたけどどこにあるのか分からなかった。
そしたらここにあった。(Mac)

/ユーザー/共有/Unity/Standard Assets Example Project

動的にボタンにデータを持った機能を加える

※)15.06.06 一番下に追記あり

動的にボタンを作成したときに、それぞれのボタンに対して情報を分けた処理をさせたい。
ラムダ式でパラメータ渡そうと思ったけどうまく行かない。

using UnityEngine;
using UnityEngine.UI;
using System;

public class Test : MonoBehaviour {
	// ボタンのプレハブ
	public GameObject buttonPrefab;

	// Start.
	void Start () {
		for (int i = 0; i < 10; ++i) {
			GameObject buttonGO = (GameObject)Instantiate(this.buttonPrefab);
			buttonGO.transform.SetParent(this.transform, false);

			Button button = buttonGO.GetComponent<Button>();
			button.onClick.AddListener(() => {
				this.DoSomething(i);
			});
		}			
	}

	// なにか処理する
	void DoSomething(int num) {
		print(num);
	}
}

Continue…

触れるUIと触れないUI

3D上のタッチと、uGUI上の演出がかぶったときに3D上のタッチが効かなくなるケースがある。
サンプルだとキューブとテキストの部分)
そんな時はCanvas上のGraphic RaycaterをオフにすればOK。
別でボタンなどのパーツが必要なときは別途Canvasを作ってそっちのGraphic RaycasterをONにしておけばタッチが効くパーツとタッチの必要のないパーツがCanvasで分けられる。

>>サンプルプロジェクトダウンロード

UnityEventについて

Unity4.6からuGUIが追加された際に、UnityEventというイベントシステムも追加されました。
uGUIと同時に追加されたので、uGUIで扱うイベントシステム系かと思ってしまいますがあらゆる場面で利用ができます。
以前、イベントについてどのようなやり方がいいか試してみたんですが、その際に作ったものにUnityEventでのやり方を追加してみました。

>>サンプルプロジェクトダウンロード

Continue…

UnityゲームUI実践ガイド 開発者が知っておきたいGUI構築の新スタンダード

Unity4.6/5で追加された新たなuGUIの解説本
UnityゲームUI実践ガイド 開発者が知っておきたいGUI構築の新スタンダード
が発売されました。
いままではNGUIがスタンダードでしたが、これからはUnity標準のuGUIですべて実現できるレベルのものになっているようです。
RépubliqueシリーズのUIなどを担当されていた池和田さんが書かれているので実践的な内容になっていそうですね。
本にするかKindleにするか迷いますが僕もそろそろuGUIを勉強しようとおもいます。

インスペクタでのAnimationCurveの利用

インスペクタ上でAnimationCurveを使ったデータの利用。
グラフをいじって、Evaluate(float time)にて、timeに対する値が取得できる。

using UnityEngine;
using System.Collections;

/// <summary>
/// AnimationCurveのテスト。
/// </summary>
public class CurveTest : MonoBehaviour {
	/// <summary>
	/// AnimationCurve.
	/// </summary>
	[SerializeField]
	AnimationCurve curve;

	/// <summary>
	/// 経過時間。
	/// </summary>
	float passedTime = 0f;

	/// <summary>
	/// Update.
	/// </summary>
	void Update () {
		passedTime += Time.deltaTime;
		int sec = (int)passedTime;
		float per = passedTime - sec;

		Vector3 pos = this.transform.position;
		pos.x = this.curve.Evaluate(per);
		this.transform.position = pos;
	}
}