継承先から親クラスのイベントの発行

継承先から親クラスのイベントを発行しようとした際に

`****’ can only appear on the left hand side of += or -= when used outside of the type ` ****’

こんなエラーが出た。

どうも
event EventHandler MyEvent;
と定義をした際には実際には

private EventHandler _myEvent;

public EventHandler MyEvent {
	add(EventHandler handler) { 
		this._myEvent += handler;
	}
	remove(EventHandler handler) {
		this._myEvent -= handler;
	}
}

こんな展開がされているらしい。
ここで、_myEventはprivateなので継承先からは処理が呼べないらしい。
なので、継承元に

protected CallMyEvent() {
	this.MyEvent(this, EventArgs.Empty);
}

などを準備して、継承先から読んであげる必要があるようです。

参考)
devlog [naru design] | Unity3D:スーパークラスのeventをサブクラスから呼び出す
stackoverflow | Why can’t I invoke PropertyChanged event from an Extension Method?

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…

値を持つイベント

値を持つ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);
	}
}

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]

コルーチンについて

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

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

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

ローディング

Unityでローディングをする際のテスト。基本的にはWWWクラスで簡単に処理ができる。FlashでいうURLLoaderのような感じだけどもう少し簡易的に扱える。
今回は画像ならGUI.Boxで画像を表示し、音ならAudioSourceで音を鳴らし、それ以外であればGUI.TextFieldにてテキストを表示させるようにしてみた。
音についてはUnityはmp3を外から取ってきて鳴らすというのはサポートされていないそうで非圧縮音源かoggフォーマットのみ。

基本的な部分はすごく簡単で

/**
 * データのロード。
 */
private IEnumerator LoadData(string url) {
	this.www = new WWW(url);

	yield return this.www;

	// ダウンロード後の処理
}

こんなメソッドを用意してあげて、あとは呼び出すだけ。
ローディング状況はWWW.progressで取れる。
エラーについてはWWW.errorがnullでなければエラーが発生している。
Flashと同様に別のドメインのファイルを見にいくときにはcrossdomain.xmlの設置が必要になってくる。
Continue…

UnityでXMLを扱う

前回のjsonに引き続きXMLの読み込みのテスト。
この辺はFlashと同じような扱いでできた。
XMLをDOMとして扱うのであればこれでいいんだけど、SAXとして扱う場合はXmlReader.Create()を使うと思う…けどよく分からなかったけどこの辺が参考になるのかしら。
Continue…

UnityでJsonを扱う

UnityでJsonを扱うにはいくつかライブラリがあるようです。
生存日記 | UnityのJSONパーサ
この中でJSON ObjectLitJSONを扱ってみました。

(2014.06.28 追記 : NGUIにもJsonを扱うNGUIJsonがあった

JSONObjectのライセンスはLGPL2.1と書いてあるんですが、DLしたものには特に明記はなく、Asset Storeに並んでいるものも特に明記はしていないのでこちらが適応されると思っていいんでしょうか…
LitJSONの方はパブリックドメインなので問題なく自由に使えるようです。
Continue…

拡張メソッド

組み込みのクラスやライブラリのクラスを拡張したいときに使える拡張メソッドというのがある。
staticなクラスを作りそこにあるメソッドがまるで自身のクラスのメソッドのように扱える。
staticクラスのメソッドになるので、自身のプライベートなメソッドやプロパティにはアクセスができない。

例えば
A だと
###
#A#
###
のように自身の文字列を囲みの文字に変えるよう機能を拡張する場合は

static class StaticStringExtensions {
	/**
	 * 「#」で文字を囲む。
	 */
	public static string BorderSharp(this string s) {
		string border = "";

		for (int i = 0; i < s.Length + 2; ++i) {
			border += "#";
		}

		string blockStr = "";
		blockStr = border + "\n";
		blockStr += "#" + s + "#" + "\n";
		blockStr += border + "\n";

		return blockStr;
	}
}

使い方は

static class StaticStringExtensions {
using UnityEngine;

// テストクラス
public class StringTest : MonoBehaviour {
	public void Start() {
		Debug.Log("ABCDEFG".BorderSharp());
		Debug.Log(StaticStringExtensions.BorderSharp("HIJKLMN"));

		Debug.Log("OPQRSTU".BorderLine());
	}
}

自身の作ったクラスなんかであればpartialというキーワードを付けたクラスを作るとそのクラスを拡張できる。Objective-Cでいうところのカテゴリの様な感じでしょか?