LINQ

C#ではLINQという機能がありますがよく知らなかったので試してみました。
基本的にはSQLを文字列ではなく言語の持つ機能として作られたものがLINQ(統合言語クエリ)というもののようです。
Unityでは直接DBを扱う事というよりはコレクションを操作して別のコレクションを作るときに使えます。
例えばGameObjectのコレクションの中からposition.x > 0のものだけを選ぶ場合。

		List<GameObject> gameObjects = new List<GameObject>();

		for (int i = 0; i < 10; ++i) {
			GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
			go.name = "GameObject" + i.ToString();
			gameObjects.Add(go);
			go.transform.position = new Vector3(Random.Range(0, 10), Random.Range(0, 10), Random.Range(0, 10));
		}

		foreach (GameObject go in gameObjects.Where(go => go.transform.position.x > 0)) {
			go.renderer.material.color = Color.red;
		}

Continue…

Some objects were not cleaned up when closing the scene.

「Some objects were not cleaned up when closing the scene. (Did you spawn new GameObjects from OnDestroy?)」
というエラーが出て、再生を止めたのにインスタンスがシーンに残ってしまった。
どうやら再生を停止する際にもOnDestroy()が呼ばれそこでエラーが出てしまいDestroyされず残っているようでした。
今回の原因はシングルトンで扱っていたクラスにOnDestroy()でアクセスしていたため、先にシングルトンとして生成されていたオブジェクトが削除されたためにエラーが出ていたようでした。

値を持つイベント

値を持つEventArgsを作りたく、値も型に依存しないものにしたかったので調べたらこんなやり方があった。

[ EventValue Class ]

using System;

/// <summary>
/// 値を持つEventHandler。
/// </summary>
public class EventValue<T> : EventArgs {
	/// <summary>
	/// 値。
	/// </summary>
	public T value;

	/// <summary>
	/// コンストラクタ。
	/// </summary>
	public EventValue(T value) {
		this.value = value;
	}
}

使う側(EventValueにColorを保持)

using UnityEngine;
using System.Collections;

/// <summary>
/// EventValueのテスト。
/// </summary>
public class EventTest : MonoBehaviour {
	/// <summary>
	/// EventValueを使用したdelegateの定義。
	/// </summary>
	public delegate void EventColorHandler(object sender, EventValue<Color> evt);

	/// <summary>
	/// EventColorHandlerのイベント。
	/// </summary>
	public event EventColorHandler OnChangeColor;

	/// <summary>
	/// Start.
	/// </summary>
	void Start () {
		this.OnChangeColor += this.OnChangeColorTest;
		this.OnChangeColor(this, new EventValue<Color>(Color.red));
	}

	/// <summary>
	/// イベントを受け取る。
	/// </summary>
	void OnChangeColorTest(object sender, EventValue<Color> evt) {
		print(evt.value);
	}
}

テクスチャのOffsetの設定

背景を表現する場合テクスチャをずらして表現する事がある。その際にSpriteを使ってしまうとテクスチャがいくつかまとまったシートになっているためOffsetなどは使えない。なのでQuadを使ってマテリアルを割り当てる。使うテクスチャは
[ Texture Type ] => Texture
[ Wrap Mode ] => Repeat
にしておき、その上でスクリプトの方で renderer.material.mainTextureOffsetを操作するとテクスチャをずらす事ができる。

void Update () {
	this.renderer.material.mainTextureOffset = new Vector2(Time.time, Time.time);
}

こちらでも詳しい説明が載ってます。

base.Awake(), base.Start()などの呼び方

MonoBehaviour <= SuperClass <= SubClass この継承関係の場合、SubClassからSuperClassのAwake()を呼ぶため [unitycsharp] void Awake() { base.Awake(); } [/unitycsharp] これだとエラーになる。 SuperClassのAwakeをvirtualとし、SubClassのほうでoverrideを指定するとうまく呼べる。 [unitycsharp] public class SuperClass : MonoBehaviour { public virtual void Awake() { print("Super.Awake()"); } } public class SubClass : SuperClass { public override void Awake() { print("SubClass.Awake()"); } } SubClass sub = new SubClass(); sub.Awake(); [/unitycsharp]

UIButtonやUITweenerでのイベントの発行元

UIButtonのonClickやUITweenerのonFinishedのイベントの発行元の取得は

public UIButton button;
public UITweener tween;

void Start() {
	EventDelegate.Add(this.button.onClick, this.OnClick);
	EventDelegate.Add(this.tween.onFinished, this.OnTweenFinished);
}

void OnClick() {
	print(UIButton.current);
}

void OnTweenFinished() {
	print(UITween.current);
}

にて取得できる。

コルーチンについて

あまり理解せずにコルーチンを使用していたので、もう少しちゃんと理解しようと見直してみた。
そもそもコルーチンとは。。。
以下Wikipediaより。

コルーチン(英: co-routine)とはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。接頭辞 co は協調を意味するが、複数のコルーチンが中断・継続により協調動作を行うことによる。
サブルーチンと異なり、状態管理を意識せずに行えるため、協調的処理、イテレータ、無限リスト、パイプなど、継続状況を持つプログラムが容易に記述できる。
コルーチンはサブルーチンを一般化したものと考えられる。コルーチンをサポートする言語には Modula-2、Simula、Icon、Lua、C#、Limbo などがある。マルチスレッドで原理的には同じことができるため、現在はそちらが使われるケースが多い。

ということで、処理を中断し再び呼び出すと続きから再開できるということのようです。
Continue…

NGUIJson

NGUIにもjsonを扱うクラスがあった。

string json = www.text;
Hashtable hash = (Hashtable)NGUIJson.jsonDecode(json);
ArrayList data = (Hashtable)hash["data"];
string id = (string)hash["id"];

こんな感じで使える。

2Dの際のスクリーンの座標

2Dの際にはカメラのモードが正投影(Orthographic)になる。その際にSizeという値があるけどそのサイズはスクリーンの縦のサイズの半分の高さを意味している。
Camera.orthographicSize
なので、1136pxの縦幅に対してdot by dotにしたいときにはSizeを568にする。
ただ物理演算をさせたいときには、Unityの1unitは1mとなっているので、dot by dotにしてしまうと100m単位のオブジェクトなどになってしまうのでdot by dotとして扱わない場合もある。
その際には

// 画面幅
Screen.width * Camera.main.orthographicSize / (Screen.height / 2)

// 画面高さ
Screen.height * Camera.main.orthographicSize / (Screen.height / 2)

こんな感じで画面の幅と高さを取得できる。
Spriteの設定のPixels To Unitsもものの大きさに合わせて設定する。