Google driveを使用したUnityゲームの公開(WebPlayer)

Googleドライブのインストール方法は省略。検索すればいくらでも出てくる。

Googleドライブフォルダを開き、公開したいフォルダを作成/開く、公開したいWebPlayerのhtmlとunity3dファイルを置く。
・タスクバーのGoogleドライブアイコンをクリックし、「ウェブ上のGoogleドライブにアクセス」を選択。ブラウザ上でのドライブ操作画面に移る。
・公開したいフォルダを選択、右クリックの「共有」から奥に進んでいって「インターネット上での誰でも検索、閲覧可」の状態まで持ってく。
・対象のhtmlファイルを選択すると「詳細」タブにホスティングULTが出ているので、それをクリックしてゲーム画面まで行けたらそのURLをコピペする。
・貼り付けはiframeを使用。srcの後に取得できたULRを入れる。あとの数値は適当に。

f:id:DYMN:20141213174308p:plain

参考:http://www.techofy.org/2014/03/host-images-on-google-drive.html

右クリックのコンテキストが鬱陶しい場合はhtmlファイルを編集する
http://docs-jp.unity3d.com/Documentation/Manual/WebPlayerBehaviorTags.html

編集画面に移ってもWebPlayerの画面が残っているのですごく鬱陶しい。

経由地を通ってオブジェクトを移動させたい(iTween/path)

iTweenを使用した際、指定した点を経由する形でオブジェクトを移動させたい場合。

たとえば点Aにあるオブジェクトが点Bに到達した後点Cに行きたいとして
iTween.MoveTo(B)
iTween.MoveTo(C)
とかやった場合、MoveToBを実行した直後にMoveToCが実行され、事実上まっすぐ点Cに向かうことになる。

のでこの場合、"path"オプションを使用する。

Vector3形式の配列にA,B,Cのpositionを設定し、pathの引数に与える。


movePath[0] = ObjectB.transform.position;
movePath[1] = ObjectC.transform.position;

とした後に

iTween.MoveTo(tgtUnit, iTween.Hash("path", movePath, "orienttopath", true, "speed", itwSpd, "easetype", itwET));

とすると指定した点を経由しての移動ができる。
ただし配列の要素数が1つだけの場合はどうも動かないっぽいので、経由数が可変の場合は
movePath[0] = ObjectA.transform.position;
movePath[1] = ObjectB.transform.position;
movePath[2] = ObjectC.transform.position;
のように0の位置に原点ぶち込んどいた方が安全かもしれない。

オプションの"orienttopath"をtrueにすると移動中、オブジェクトが進行方向を向き続ける。

http://answers.unity3d.com/questions/384132/itween-moveto-rotation.html

SendMessageはDisableなスクリプトも呼び出してしまう

あるオブジェクトに複数コンポーネントスクリプト)がアタッチされており、各コンポーネントに同じ名前の関数がある場合。
オブジェクトに対しSendMessageでその関数を起動するとDisableであるコンポーネントの関数も呼び出される。

美しい解決方法がないか検討してみたが、現状関数名を変えるか、その関数の先等に「if(this.enabled == false) return;」を入れるかぐらいしか対処法がないっぽい。
Privateも呼び出せるっていうしSendMessageはちと強すぎる気がするな。すぐにReturnする処理にSendMessageするのも処理速度的にもったいないし……
かといって投げっぱなしでいい処理だとGetComponentは少し煩雑すぎることも多い。さて何かいい方法はないものか。

http://forum.unity3d.com/threads/non-enabled-scripts-are-receiving-sendmessage.55438/

異なるコンポーネントをループで一度にON/OFFする

通常、コンポーネントのON/OFFは[取得したコンポーネント].enable = true/falseで行える。
配列にコンポーネントを保存すればループで一度にスイッチできる。
が、当然異なるコンポーネントには使用できない。

似たような処理を行うが、種類が異なるコンポーネントを一度にON/OFFしたいことがあるかもしれない。……あるよね?
たとえば「炎を発射する魔法のコンポーネント」「周囲を氷付けにする魔法のコンポーネント」みたいな感じで。

その際は一度各コンポーネントを取得し、MonoBehaivour型の配列に格納することでループでまとめてスイッチすることが可能。

	uam = thisObj.AddComponent<UnitActionMove>();
	uaa = thisObj.AddComponent<UnitActionAttack>();
	uas = thisObj.AddComponent<UnitActionSkill>();

	MonoBehaviour[] monoComponents;
	monoComponents = new MonoBehaviour[NUM_BUTTON];

	monoComponents[0] = (MonoBehaviour)uam;
	monoComponents[1] = (MonoBehaviour)uaa;
	monoComponents[2] = (MonoBehaviour)uas;

	for(int ii = 0; ii < NUM_BUTTON; ii++)
	{
		monoComponents[ii].enabled = false;
	}

上の例だとUnitActionMove以下3種の異なるコンポーネントをmonoComponents配列への操作によって一度にON/OFFすることが可能になっている。

NGUI ボタンに引数を添える

ボタンに引数を添えて押した時の処理を呼び出す方法。
EventDelegateを使用する。Delegateって継承だっけ。
とりあえず細かい部分は棚上げしてのやり方。

※1 UiButtonType = ENUMで定義している独自型。
※2 uam = ボタン押した時に呼び出したい関数が入っているコンポーネントスクリプト
※3 uiBtn[0] = ボタンオブジェクトに付いているUIButtonコンポーネント

投手側

	string stringMessage = "varvar";
	UiButtonType btnType = UiButtonType.MOVE;

	EventDelegate eveDelg = new EventDelegate(uam, "ButtonClickAction");

	eveDelg.parameters[0].value = btnType;
	eveDelg.parameters[1].value = "StringMessage";

	uiBtn[0].onClick.Add(eveDelg);

捕手側

	public void ButtonClickAction(UiButtonType arg1, string arg2)

parameters[x]が引数の順番を制御してるっぽい。型の確認ができないのがちと不安ではある。
EventDelegate.targetとかEventDelegate.ParameterのSetValueとか使えそうな関数もあるけど姑息に用を足すだけなら上記の文だけでなんとかなるっぽい。

参考:http://www.tasharen.com/ngui/docs/class_event_delegate_1_1_parameter.html

RayCastでLayerMaskが動かない場合

RayCastを使用する際、LayerMaskを指定することで特定レイヤーのみ検知/特定レイヤーを除いての検知が可能だが、どうもその際の構文は距離を明示している必要があるもよう。

			if(Physics.Raycast(ray, out hit, 1000.0f, panelLayer))
//			if(Physics.Raycast(ray, out hit, panelLayer))
//			if(Physics.Raycast(ray.origin, ray.direction, out hit, 1000.0f, panelLayer))

真ん中のRayCastだとLayerMaskが意味を成さず、全てのLayerとヒットする。

NGUI ボタン操作時に実行される関数をスクリプトで決定する方法

NGUIでボタンが押された時に呼び出される処理はインスペクタ内「UIButton(Script)/On Click」「UIEvent Trigger(Script)」の各イベントに対応したNotifyに関数を記述したスクリプトをアタッチしたゲームオブジェクト(な、長い……)をセットし、ドロップダウンから対応関数を選択することで決定する。
参考ページ:http://naichilab.blogspot.com/2014/03/unitynguingui.html

とはいえボタンが増えてきたり、似たような処理のボタンを複数作る場合、ひとつひとつ手作業で設定していくのはめんどいしミスしそうだし美しくない。

のでスクリプトから設定する方法。

	// 生成するボタンのプレハブ.
	public GameObject uiButtonPrefab;
	// プレハブをインスタンス化したゲームオブジェクト.
	private GameObject btnObj;

	void Start ()
	{
		// プレハブから実際にボタンを生成(インスタンス化)し、そのゲームオブジェクトを取得する.
		btnObj = (GameObject)Instantiate(uiButtonPrefab);

		Vector3 tVec = new Vector3(50.0f, 25.0f, 50.0f);
		btnObj.transform.localScale = tVec;

		// クリック/ダブルクリックを取得したいのでプレハブにはEventTriggerをアタッチしてある.
		// EventTriggerコンポーネントを取得する.
		UIEventTrigger uiEveTrg = btnObj.GetComponent<UIEventTrigger>();
		// ボタン操作時に呼び出したい関数が記述されているスクリプトを取り出す。同じオブジェクトにアタッチされているSelectedUnitProcessというコンポーネントを取得する.
		SelectedUnitProcess sup = thisObj.GetComponent<SelectedUnitProcess>();

		// EventDelegateからアクションに対応した関数を設定する。*.Addだと既存リストへの追加、*.Setだと置き換えになる……らしい.
		// 引数は「*.[対応したアクション], [呼び出したい関数名].
		// 関数だけだと同じスクリプトから、「コンポーネント.関数名」だと指定したコンポーネント(スクリプト)内の関数が呼び出される.
		EventDelegate.Set(uiEveTrg.onClick, sup.Test_OnClickOrTap );
	}

参考ページ:http://narudesign.com/devlog/unity-ngui-eventdelegate/