Google

2011年10月31日月曜日

プレハブの弱点


今回もUnity3dのプレハブ話です。

これはあちこちで万能っぽく言われてますが、結構制限もあるので注意が必要です。
簡単に言うと、プレハブ本体とインスタンスでの違いが顕著です。
まず共通としてあるのは、プレハブ化した後に子をくっつけることができない事。
というと語弊があるので詳細を言うと、、、

プレハブ本体:
もともとProjectツリー側では実行時の親子は関係ないのでできません。
プレハブ化する前に親子付けしていた他のオブジェクトの関係は見えません。
ここで追加削除したコンポーネントは何事も無くインスタンスへ反映させることができます。

インスタンス側:
ヒエラルキー上で無理やり親子関係を変更すると、インスタンスがPrefabではなくなります。
プレハブでなくても別に構わないのですが、せっかくまとめて変更を適用できるといった利点が勿体ないですね。
Ctrl+Zも効きますが、確定してしまえばそのオブジェクトは二度と仲間には戻れません。
位置や回転なら特に問題はありません。(むしろできないと困る)
Component周りの変更も問題なく反映されます。

一番困ると思われるのはこんなケースじゃないでしょうか。
 ・木のプレハブを作成してマップに100本配置
 ・配置完了後に子オブジェクトとして木の実を追加したいと言われる。
 ・木の実はマテリアルでは実現できない仕様だった

無理やり元のプレハブへぐりっとやっても解決しないのでご注意を。
つまりは、コンポーネント周りでの変更ぐらいしかダイナミックな変更ができないってことです。
計画的に配置しないといけないってことですね。

2011年10月27日木曜日

Unity 3.4.2f2にバージョンアップ

今日、Unityのマイナーバージョンアップがありました。

3.4.1f5
から
3.4.2f2
です。

詳細とダウンロードはこちら。
http://unity3d.com/unity/whats-new/unity-3.4.2

今回はほんの少しで、スマホ周りのクラッシュやAppleガイドライン絡みのようです。
ざっとみた感じ特にバージョンアップしても問題なさげ。
安心してアップデートしてください。

しかしスマホの作業をしてるとよく落ちるのが困りもの。
ひどいと1日に数回は再起動とかざら。

次回3.5で大きな改変が待っているようなので、安定化するといいですね。

2011年10月26日水曜日

エンジニア視点のプレハブ

Unityのプレハブ機能、ゲーム開発界隈で結構有名です。
雛形からコピーが作れるのと、生成済の仲間に対してまとめて変更部分を適用できる機能等があるため、製作時の効率化を図れるってのがウリ。
クラスからインスタンスを生成するのが生業のエンジニアから見れば、プレハブが凄いと言われてもそこまで大したことでは無いような気もするのですがそれは置いといて。
GUIからの操作が簡易になるという点では良い機能です。

一番簡単な作り方はこちら。

Prefab化したいGameObjectをヒエラルキーから選択
そのままぐぐっとProjectへ、、、、
はい完了!こっから逆にドラッグすればインスタンス化です。
一旦ProjectにPrefab作るとかいう手段もありますが、これが単純です。
実行前の作業であるため、スクリプトを使用したプレハブ化はできません。
プレハブからインスタンスを生成するのはスクリプトからもできます。
また、プレハブ自身のクラスも存在しません。

こういった便利なツールにおいて、コードだけで書き上げることは困難ですね。
GUIの便利さとトレードオフになってしまうでしょう。

実はこのプレハブ、開発作業時にエンジニアとかUI担当とかで考慮しなければならないことがあるのですが、それはまた次回。

2011年10月25日火曜日

refで渡す引数が見当たらず

横道にそれますが、気になっていた点をひとつ。

今更ですがUnity公式リファレンスのリンクはここです。

http://unity3d.com/support/documentation/ScriptReference/

で、使用可能なクラスや構造体等の一覧は1つ下がってここ。

http://unity3d.com/support/documentation/ScriptReference/20_class_hierarchy.html

これらを見て気になっていたこととは、

「引数が全て実体渡しになっている、、、、」

です。

もともとC#には実体型と参照型があるため、生成時にそれらの違いが出ます。
組み込み型的なint等は当然実体ですが、構造体やクラスは参照です。

これが問題となるのは関数への引渡しの時。
型の振る舞いが決まるのは生成時だけとは限りません。
C/C++屋なら常識ですが、馬鹿でかいオブジェクトを単純に渡せば、関数の中で新たにメモリが生成され、生成時の負荷でも無駄コストになってしまい、場合によっては思った通りの動作になりません。
C++等の詳細仕様を見れば型そのものの概念と、引数になる際の振る舞いは厳密に分けられており、その動きは明確です。

C#では関数の引数として扱う際は基本実体渡しです。
アドレスのみを渡すならrefを、戻すならoutを付随させなければなりません。
これも言語仕様として決められているようです。
フォーラムでたまにそのへんの質問が出ているのを見ますが、回答者すらよくわかってないのか、クラスは生成時に参照なんだから決まってるだろ的なリプライがあったりして本当に困るところ。

しかしUnityのリファレンスには参照が有りません、、、。
例えば以下のコード。

Vector3 vec = transform.localScale;
print(Vector3.Scale(vec, new Vector3(2, 2, 2)));

自分のスケールを取り出して2倍にしてそれを表示という内容です。
このScaleはクラスメソッドで、以下がそのリファレンス。

http://unity3d.com/support/documentation/ScriptReference/Vector3.Scale.html

やっぱりrefはどこにもない、、、。
実際、上の2行目のvecをref vecとかするとエラーが出ます。
じゃあUnityはそんなに無駄な事をしてるのかというと、全てがそうかはまだ疑問。

勝手にref扱いしてるものがないかどうかは現在検証中。

2011年10月24日月曜日

子GameObjectに順次アクセス

以前の回では、他のGameObjectにアクセスする方法を色々書きました。
その関係でちょっと追記というか補足。

ゲームを作っていくと、GameObjectはバラバラに存在するというケースはさほど多く有りません。
実際は階層構造になっていて、それをまとめる大きなものが何個かあるはずです。
別にでかいケースだけではなく、簡単な場合でもよくあります。
例えば、動きまわるキャラを作ったとして、そいつが武器や装備を持ってパワーアップするとします。
銃を撃つときにその銃が光ったり反動を表現したりリロードしたりとか、いろいろあるはず。
それが自分じゃなくていっぱい居る敵だとしたら、GUIから指定するにも結構たいへんです。

そう考えると、必ず入れ子のGameObjectがあって、自分の子にアクセスするというケースが出てくるでしょう。
そんな時にはどうするかというと、、、、。

以前書いたGUIからの指定やFind、これはもう説明しました。
今回はTransformを使った入れ子へのアクセスです。
これがサンプル。

Transformはparentメンバを持っているのですが、さらに子供も持つという二重アクセス構造。
それを利用し取り出すことができます。
foreachができるのは、IEnumerableを実装しているため。
イテレータとして順次取り出せるので、後はタグ付なり名称付なり、取り決めを自分で行うことで、判断させることが可能です。

しかしforeachを毎回させれば遅くなるのは当然。
動的に生成破棄するゲームであっても、こういう事をしなくていいように、予めメンバ変数に設定しておいてその分のコストを減らすようにするのが普通かと。

2011年10月21日金曜日

GameObjectに複数のMonoBehaviour

GetComponentの使い方でもう一つ。

以前、GameObjectには複数のスクリプトを追加可能と書きました。
じゃあそれがなんの役に立つかという一例を紹介します。
例えばファクトリーやマネージャクラスなど、全体に絡むクラスが何個がある場合を想定しましょう。
ゲーム内部で目に見えなくても仕事をする必要があるクラスですね。
実際、現場ではこういったクラスの方が重要です。

この時にあの書き方が生きてきます。

これらを一個ずつ丁寧に別々のGameObjectに追加するのもいいですが、せっかくまとめられるのならばそうしたいところです。
ということでサンプルがこちら。

上記のコードは2つ分くっついてますが、上記の2つをそれぞれC#で生成し、一つのGameObjectに紐付けしてください。
やってることは単純、Test1及びTest2で互いの関数をコールしているだけです。
結果は書くまでもないほど簡単ですな。

ここでのポイントですが、自分以外のスクリプトを取り出すのに、自分自身に対してGetComponentしている部分です。
いちいちpublicにしてGUIで紐付けしたり、Findしたりという手間が省けますね。

これなら一つのGameObjectをスクリプトホルダーとして機能させられます。
構造的も簡潔になるので言うことなし。

また、スクリプトを取得する際、GetComponent<クラス名>()でテンプレート変換している点も注目。
ソースコード上でもすっきりと書けます。

2011年10月20日木曜日

他のMonoBehaviour派生クラスへアクセス

オブジェクトの探し方ができたところでプロパティの続き。
以前の回で書いたGetComponent()を使うとスクリプトにもアクセスできます。

そこで今回は自作スクリプトのメソッドを呼び出してみましょう。
要はMonoBehaviour派生クラス同士のメンバアクセスです。
これは開発を始めると常に行うことになるはずで、今回は実行時に生成破棄等の変更がない場合の方法を書いてみます。

では以前使用したC#スクリプト2個を再利用して実験です。
以下が再利用クラス。

  • BaseScript
  • InheritScript

これに仮想関数Func()を追加し、派生側でオーバーライドしときます。
ついでに以前のStart()を外します。
以下のコードは2つ分がくっついてるので、分けて実装してください。
 

余談ですが、StartやUpdate等はあくまでUnityFWが制御するものなので、自前での呼び出しは自己責任で。
逆にクラスに書かなければ何も起きません。

さらに呼び出しテスト用C#スクリプトを1つ作成します。
こちらはTargetScriptとしました。

このクラスの役目はbaseObjとinheritanceのFunc関数を呼び出すだけです。
が、それでは説明にならないのでコードを簡単に解説。

まず、自作スクリプトがProjectビューの中にあるのなら、上記のようにそのままスクリプトクラスの変数を宣言可能です。
自作スクリプトは基本的にMonoBehaviour継承。
MonoBehaviour派生クラスは、GUIの操作によってGameObjectに紐付けされます。
従って、スクリプトにアクセスする場合は、GameObjectを検索等で見つけ出し、紐付けされたスクリプトインスタンスを取り出して関数呼び出し、という形になります。
なお、GetComponent("")の形式はComponent型を返すので、上記コードではダウンキャストして型変換を行なっています。


で、作成したら、UnityGUI上でメニューから「GameObject」→「Create Empty」を選び、3つオブジェクトを作成してください。
それぞれ以下のように命名と紐付けをしましょう。
  • GameObjet1 (BaseScriptに紐付け)
  • GameObjet2 (inheritanceScriptに紐付け)
  • GameObjet3 (TargetScriptに紐付け)
こんな状態にしましょう
しかし上記の紐付け状態だと、コンソールに赤い文字でエラーが出てしまいます。
すぐにはでなくても実行時にはエラーになります。
これはTargetScriptのメンバ変数x2の中身が無いのにメソッド呼び出しをしようとしているために出ている訳です。
そこでGameObject3を選択し、前回の記事で書いたドラッグ&ドロップで以下の紐付けをしてください。
  • baseObj (GameObject1)
  • inheritance (GameObject2)
これで実行前にメンバが確定され、エラーが消えます。
さて、実行するとどうなるでしょうか。


はい、アクセスできていました。
継承構造にも注目しておいてください。
基底クラスを紐付けした方はちゃんと基底クラスのメソッドが呼ばれています。

2011年10月19日水曜日

別のGameObjectにアクセス

Component詳細の前にGameObject検索に横道。
今までの例では、スクリプトに割り当てられたGameObjectを触っていました。
そして紐付けはUnityのGUIからドラッグ&ドロップだったため、実行前に決められていました。

じゃあ実行時に別のGameObjectを、、、という場合はどうでしょう。
複数方法がありますが、代表的なものがこちら。
  • 実行時にFindで検索
  • publicメンバにして実行前に紐付け
前者は速度的には厳しいですが、動的な生成破棄をするなら必須です。
後者はオブジェクト指向的に問題なのと、GUI操作必須ですが高速です。

まずは前者から。
GameObjectのstatic関数、Findで検索が可能です。
宣言はこんなかんじ。

static function Find (name : String) : GameObject

ヒエラルキー上で表示されている名前を入れると検索し、該当すればインスタンスが戻るという仕組みです。
しかしこの名前、GameObjectの最基底クラスであるObjectのnameメンバなのですが、シーン上でユニークな訳ではありません。
実際、シーン上には同じ名前のGameObjectがいっぱい作成できてしまいますし。
プレハブでもそうですが、名称を自力で固有に変更しなければ欲しいインスタンスにアクセスできないのでご注意を。

以下は具体例です。 (公式から抜粋)
このようにヒエラルキー構造を指定して検索を掛けることも可能です。
スラッシュから始まる検索の結果は、「ルートに存在するオブジェクトである可能性がある」と公式には書いてありますが、実際にはルートにあっても階層下にあっても検索できてしまいます。
/Monster/Armのように階層が深くユニークなら実質問題ないようです。

他にも手はあって、タグを利用した名前付けで検索することも可能です。

static function FindWithTag (tag : String) : GameObject

これもまたユニークというわけではないので自力で設定しましょう。
なお、遅いと言いましたが、Update()で書いたりすると恐ろしく遅くなります。
Awake等で検索し、自前メンバに保持しておくのが一般的です。


長くなりましたが続いて後者。
上記のコードでGameObjectのhandがpublicになっています。
オブジェクト指向の世界で、何も考えずにメンバをpublicにすることは通常ありません。
が、こうしておくと、Unityのインスペクタにそのメンバが表示されるようになります。
以前この値をGUIから変更可能と書きましたが、クラスメンバの場合はここから静的にインスタンスを指定することが可能です。
要は、Findでやることを実行前に確定させるだけの事。
反則感はありますが、これも推奨のようです。

そしてそのやり方は簡単。
publicなクラスメンバを持ったスクリプトをGameObjectに紐付けます。
そのGameObjectを選択すると、インスペクタのスクリプト欄にそのメンバが出ます。
ヒエラルキーからドラッグ&ドロップで終了。

未設定ならNoneに、入ってれば名称がでます。上書きもおk

なお、マテリアル等ならプロジェクトビューからでも紐付けできます。

2011年10月17日月曜日

GetComponentでプロパティ

前回はTransformを取得して位置移動を行いました。
位置以外にも様々なComponent派生クラスを保持可能になっています。
また、Componentは必要に応じて脱着できるため、存在していない場合それらのメンバ変数はnullとなります。
(TransFormだけは外すことができませんが)

プロパティの形で保持しているこれらを別の方法で取得することも可能です。
以下の例を見てみましょう。
これも今まで同様にC#コードとして生成したものです。

Transformインスタンスが4個取得されていますが、これはどれも同一のインスタンスが取得されることになります。

一番上はMonoBehaviourのメンバ変数ですが、これはアタッチされたGameObjectのTransformが自動的にバインドされます。
2番目はアタッチされたGameObjectのインスタンスであるgameObjectメンバ変数(頭文字の大小に注意)から同様に取り出してます。
つまりはこれも1番目と同様です。

3番目はGetComponent関数を使用して取得しています。
<>の間にはTypeが入りますが、Unityで準備されたComponent派生クラスなら""成しで指定するものと考えてください。
実行速度的にはプロパティ呼び出しの方が上なのは当たり前ですが、1回2回の呼び出しなら差は微々たるものです。

で、4番目ですがこれはエラーとなります。
JavaScriptでは""(ダブルクォーテーション)抜きで指定できていましたが、この方法では呼び出せません。
3番目はテンプレートとして型変換まで行なってくれるのですが、この方法では単にComponent型のインスタンスポインタが戻ってくるため、Transform型へのキャストでエラーとなる訳です。

ではどうするかというと、以下のようにしてください。
VBライクなas 型名か、Cライクな(型名)どちらでもお好みでどうぞ。
ただ、上記コードでは両方あると二重定義エラーとなるのでご注意を。

実はGetComponent()ではインスタンス的にはきっちりTransformが帰ってきていますが、Componentクラス型のままなので、派生クラスであるTransform型にダウンキャストしなければなりません。
それが上記の記述方法です。
本来ダウンキャストは望ましく有りませんが、型が完全に確定している場合は問題ありません。 
前回の位置変更サンプルの取得方法をこれにしても動作します。

この呼び方は一見無駄に見えますが、実はこの呼び方にも意味があります。
それはまた次回以降で。

2011年10月14日金曜日

UnityのComponent操作

Unityでゲームらしいことをする場合、コード側では何をすればいいか、という話をしてみます。
本やブログで色々説明はありますが、自分なりの表現で噛み砕いて見ました。

普通、ゲーム製作者やユーザ観点では、キャラがいて弾撃って移動して、ボスがいて、当たったらどうこう、、、とかいう話になると思います。
しかしそれは仕様とか画面上の話。
システム的な観点で抽象的に言えば、オブジェクトの「プロパティ」が変化するということです。
ざっと言えば以下のような感じ。

 ・生成、消滅
 ・位置移動、回転
 ・3Dアニメーション
 ・テクスチャの変化
 ・etc...

Unityにおける画面上のオブジェはGameObjectです。
以前、GameObjectをスクリプトで操るにはMonoBehaviour派生クラスを作成という話をしました。
が、このMonoBehaviourそのものが機能盛りだくさんという訳ではありません。
以下のリファレンスを見てみましょう。

MonoBehaviour Class Reference
  http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.html

大半の関数はイベントハンドラで、他の動作面では空っぽに近い感じすらあります。
実はこのクラスを成り立たせてるのは、Component派生メンバ変数群。
重要な機能はほぼ移譲する形で構成されています。
例えばGameObjectは入れ子に出来ますが、それさえも自力ではやっていません。
Transformクラスがコンポジットパターンとして実装することで実現してます。

つまりは、オブジェクトの変化を制御したいなら、基本はGameObjectが保持しているComponent派生クラスをいじる、ということになるわけです。
まずは簡単な位置移動をやってみましょう。

GameObjectをひとつ生成し、C#スクリプトを割り当て、インスペクタウィンドウで位置を0,0,0にしてください。

解りづらいですが、0,0,0の位置にGameObjectが存在しています。

位置の管理はTransformクラスが担当し、この中には位置と回転等が入ってます。
ここからVector3というx,y,z情報を持つ構造体を抜き出し、それを変更すると位置が変わります。
以下がサンプルコード。

では解説。

Start関数の開始直後、Vector3変数posをtransform.positionからとっていますね。
(transformはTransformのインスタンスでMonoBehaviourのメンバです)
GameObjectの位置なのに、MonoBeheviourのメンバを取り出すって、、、、と思うかもしれません。
が、実はアタッチされたGameObjectのTransformメンバが自動的に反映されるため、いきなりこういう書き方でいいという訳です。

そしてx:10 y:20 z:30の位置を指定し、positionに戻しています。
できればメンバを直接変更したいところですが、C#ではpositionの内部メンバは個別変更ができません。
取り出して変更して戻すのが基本です。
これを実行すれば以下のようになっているはずです。

位置が変化しました。見た目は変わりませんが。

このように、移譲している関係から、移動に関するメソッドがMonoBehaviourに存在するわけではありません。
メンバを直にいじって変化させるのが基本的な方法です。

2011年10月13日木曜日

Unityのエディタを選ぶ

エンジニアはエディタの好みが別れる人種。
Unityでも快適に実装したいけど、標準でついてくるものはどうにもちょっと具合が悪うございます。
以下は個人的な感想。

MonoDevelop
  機能が多いが重い。メニューの文字化けを直したりとか面倒。
UniSciTE
軽いが機能が少なめ。今一つ使いづらい。

MacだとUnitronが軽めなのですが、それもそこそこな感じ。
窓の秀丸エディタは関連付けが失敗してしまうし。
で、結果落ち着いたのはNotePad++。

NotePad++
http://sourceforge.jp/projects/notepad-plus/

Macな方には残念ですがWindows用です。
実行した感じは以下の様になります。


プラグインも使えるし、細かい色分け等もできるので使い勝手は良さげです。
なにより軽めなのがとてもありがたいですね。

まず上記のアドレスに行くとこんな画面になります。


丸枠をクリックしてください。
次の画面でも丸枠部分をクリック。
あとは自動でダウンロードが始まります。

インスコが完了したら、以下の手順で登録しましょう。

メニューから「Edit」→[Preferences..」で設定ウィンドウ表示。
「Generate」タブで「External Script Editor」をクリックし、BrowseボタンでNotePad++のインスコ先を選択。

これでUnityでも快適にコーディングできます。
なおC#の場合、コメントに日本語が入るソースでは、文字コードをUTF-8(BOM付き)にしないとトラブルが多発します。
jsと混在した日にはさらに大変になるでしょう。
Unityからのバグ通知時の行数すらおかしくなります。

NotePad++のメニューから「フォーマット」→「UTF8エンコード」で指定してください。

2011年10月12日水曜日

MonoBehaviour継承

Unityでは事実上基底クラスがMonoBehaviourみたいなことになっているので、実戦環境では多段継承で実装していくケースもあるかと思われます。
じゃあ自分で作ったメンバはいいけど、MonoBehaviourのメンバはどうやればいいか?を実験してみましょう。

まずはC#スクリプトを2つ作成してください。
メニューから「Assets」→「Create」→「C# Script」です。


基底クラスとなるBaseScript、そこから派生するinheritanceScriptです。

UnityのinheritanceScriptリファレンスを見ても、StartやUpdateが仮想関数だとは書いてません。
JsやBooと共用なので書きづらい部分もあるのでしょうが。
基本FWのソースコードは見れないのでまずは実験です。

出来上がったらメニューの「GameObject」→「Create Empty」で空っぽのオブジェクトを作成してください。
inheritanceScriptだけをそいつにドラッグし、ヒモ付します。


くっついたのを確認したらおもむろに実行してみましょう。


このSSのようになったら成功です。
基底クラスのStartと派生クラスのStartが呼び出されていることが解りました。
なお、他のメンバも同様に仮想関数として扱えます。

2011年10月11日火曜日

MacBookのAC異常

休日にMacBookProで作業中、ふとあることに気づきました。

「あれ、ACアダプタのランプが、、、、、付いてない」

ちなみにMacBookの電源は以下の写真のようなやつ。
Macの電源はこんなかんじ

機種はMacBookPro 13inch 2011でLion化済。

コネクタ部分にはLEDがついてて、未ならオレンジに、満充電なら緑になります。
が、このランプが付く気配がない、、、。
OSのインジケータもバッテリ駆動の状態のまんま。(残量は58%)

こ、これはアダプタ買い直し?
と思ってAppleストアをみたら7,800円。ちょっと高いんじゃ、、、、。

いやいや、まだ故障とは限らないかも、、、と思ってぐぐったら結構困ってる人が多いようで。
で、以下のような公式情報を発見しました。

Intel-based Macs:SMC (システム管理コントローラ) のリセット

なんでも、応答してないアプリ殺してスリープして解除して再起動して終了だそうでw
凄い手順ですねこれ。
一応この手続きを踏んでもダメだったので、本体AC共に30分ほど放置。
そして改めてコンセント入れたらなんと復活!しました。

うーん、なんか微妙。

2011年10月7日金曜日

Unityのインスペクタ

Unityならではの機能として、インスペクタでの変数修正というものがあります。
これはユーザが定義した変数をUI上で調整が可能というもの。
では実際にやってみましょう。



以前のSampleBehaviourScriptにメンバを1個付けてみました。
本来メンバを単純にpublicにするというのはオブジェクト指向ではご法度です。
が、これがUnityでは意味を持ってきます。

これを以前のように空っぽのGameObjectを作成し、ソースを割り当ててみましょう。


すると上の画像の右下、スクリプトの名称の下に新しい項目ができています。
値はコードの初期値として設定した10が入ってますね。

ここからが重要。
この10の部分をクリックすると、なんとそのまま値が変更できてしまいます。
intなら整数に、stringなら文字列を、boolなら真偽を、そのまま変更できます。

この方法の素晴らしい点はただひとつ。
いちいちコードに戻らずとも、移動速度や見え方、その他がこの場で変えられるということ。
つまり、今までエンジニアがコード上でいちいち微調整していたものが、ゲームデザイナやCG屋等、他のメンバに微調整をお願いできるという利点になるわけです。
手戻りに関する点では非常に素晴らしい機能でしょう。

しかし便利なことには必ずデメリットが付いて回ります。
なんとこの修正機能、ソースコードの中身を直接変更するわけではありません。
幾らGUIからいじっても、ソース上の値は先ほどの10.0fのまんまです。
そうなると問題となるのが、規模が大きくなったときと多人数開発の時。

 「これ、何やっても思ったとおりに変更できないんだけど、、、」
 「あれー、いつのまにこんな値になったんだっけ」
 「やべ、前の値忘れちまった」

等々、恐ろしいケースは山ほど出てくるでしょう。
一旦ソースをヒモ付から外して再度付け直せば、値はリセットされます。
が、開発時のルールを厳密化しないと混乱は必至でしょう。

うまくつかってこその機能ではないかと。

2011年10月4日火曜日

Unity本2冊追加

和訳本追加。

Unityマスターブック―3Dゲームエンジンを使いこなす
http://booklog.jp/asin/4877832750

Unity入門 ~高機能ゲームエンジンによるマルチプラットフォーム開発~
http://booklog.jp/asin/4797365331


前者は個人的に新しい情報が少ないような。
しかし代わりにTerrain(地形)に関する情報が多めに載っていました。
後者はスマホ考察やゲームを作る上での実践的な例が多く記載されています。

ということでエンジニア向けという話なら後者の方がややお勧め、、でしょうか。

2011年10月3日月曜日

C#でモノビヘイビア

前々回の記事の続き。
C#でGameObjectの振る舞いを記述するクラスのひな形はこうなります。
名前は前々回作成したSampleScriptにしてあります。

JavaScriptの場合、いきなり地べたにStartとUpdateが書かれるのですが、こちらはクラスの様相を呈してます。
Js版のサンプルではpublic,private等のアクセスコントロールが結構いい加減なものが多いのですが、C#では当然きっちり書かないといけません。

1.Startメソッド

まずStart()から解説。
これはUpdateの前に1回だけ呼び出されることが保証されています。
実は、Unity3Dではコンストラクタ・デストラクタは推奨されていません。
書けることは書けますがタイミングや順序等に保証は一切ありません。
従って、普通に書くならこれがコンストラクタ扱いと考えて良いでしょう。

しかしさらにUnityにはAwake()という関数もあります。
これはシーンとその配下のGameObjectが初期化完了する前に呼び出され、順番の保証も有りません。
変数のみの初期化ならAwake、他のオブジェクトを取得したり情報を見たり設定するならStartと考えればおkかと。
何も考えずStartに全部書くのも簡単です。

2.Updateメソッド

続いてUpdate()。
これは実行中に毎フレーム呼ばれる関数です。
普通に使うならこの中に判断と動きを書くことになるでしょう。

が、UnityにはFixedUpdateという関数も存在します。
こちらは厳密に毎フレーム呼ばれるもので、解説書には重力等の制御用機能である「RigidBody」を使用するならこちらを使ったほうが良い、と書かれています。
常に一定の力を与えるケースに使われます。

っていうか、3Dで重力計算を期待してわざわざUnityを使うのだから、FixedUpdate一択?と思うかもしれません。
が、実際はそうでもないのです。
時間を表すTimeには前回のフレームからの経過秒数を示すdeltaTimeというメンバがあります。
負荷軽減にもフレームレート非依存コードの記述のためにも、UpdateとTime.deltaTimeはよく使うことになるはずです。
派生先における特化処理の記述等、普通のC#ライクに使用出来ます。

今回はここまで。


2011年10月2日日曜日

LionでChromeが応答なしになる件

Unityを使う傍ら、Chromeは常用しております。
会社と自宅等で複数PCとのブックマーク同期、速度、拡張機能、その他もろもろ。
しかしこいつが調子悪くなってしまいました。
環境はMacOSのLion。バージョンは14.x。

最初は同期に手間取ってるのかと思いきや、起動直後から必ずマウスが虹色の回転モード。
Option+Command+Escで見ると必ず「応答なし」。工エエェェ(´д`)ェェエエ工
窓ならCtrl+Alt+Deleteで見ても同じってことになるのかと。
Macの場合はユーティリティのアクティビティモニタで見れば、タスクマネージャライクな詳細が見れるのですが、これも同じ。

Macのタスクマネージャはこんなの
安定版を使用していたので、じゃあベータ版ならどうだろうって上書きインストールしてみたけど全然ダメ。
プロセスの1つ、Chrome HelperはCPU食いだって話も聞くし、うーん。

めんどくさいので今回はまるごと削除することにしましょ。
ってなことで「App Cleaner」を落としてきました。
バックアップ機能とかはないので、同期ができるChrome向けです。

完全にChromeが死んでる状態(出来ればOS起動直後)で、これを実行し、左上の「アプリケーション」をクリックしましょう。
すると一覧がでるので、Chromeを探し「検索」をクリック。
これでChrome本体だけでなく、悪さをする可能性があると思われる関連ディレクトリ、ファイル群を根こそぎ探してくれます。
窓ならレジストリまで検索してくれるクリーナってところですね。

これが検索で出てきた一覧。
全部綺麗さっぱり削除して、再度Chromeを入れなおして完了。
これで無事Chromeが起動してくれるようになりました。
同期とかはやり直しですが、クッキーも含め全部同期ができるChromeならではの対処方法かと。

調子がわるい方は一度お試しあれ。