2012年8月14日火曜日

EditorScript入門

最近忙しくて記事を書くのがサボり気味です。
今回はお酒を飲みながらEditor拡張について扱います。

Unity大きな特徴としてEditor自身を簡単に拡張できるところがあります。普段利用している際にも細かいところに手が届かず、ちょっと困ることがあると思います。
そういった場合にEditor拡張を行うことでより自由自在にUnityを活用することが出来ます。

まずEditor拡張を行う際には専用のスクリプトを用意します。Projectタブの中にEditorフォルダを用意してください。その中に入れたスクリプトがEditor拡張用のスクリプトとして認識されます。注意すべきは、Projectのなかにあればどのような階層にあったとしてもEditorフォルダの中にあるものはすべてEditor拡張用として見なされてしまうという点です。Editorフォルダの中に入っているスクリプトに関しては実際にゲームをビルドする際には含まれません。そのため、ゲームの進行に必要なスクリプトはEditorフォルダに入れないようにしましょう。

Editor拡張を行う際にはUnityEditorの名前空間を指定する必要があります。そのためC#の場合は
using UnityEditor
とスクリプトのはじめに記述します。
そのごの細かい部分に関しては以下のスクショにて



こんな感じです。
具体的に何が出来るスクリプトかというと、シーン内にあるMeshの純粋な頂点数を計算しています。
Editor拡張を行う際にはEditorWindowなどのクラスを基底クラスとして拡張していきます。そして、主にOnGUIを利用してWindowの中のボタンやテキストフィールドを用意します。その際には今回利用しているGUILayoutクラスを利用することで綺麗に並べることが可能となります。

今回は利用していませんが、Assetの管理を行う際にはファイル操作の知識があると便利です。特定の形式のデータだけを抽出してソートする等、様々な使い方があります。


また、今回このスクリプトを作成した際に気がついたのはUnityのGameWindowにあるStatsで表示されるVertsは純粋な頂点数ではないということがわかりました。
具体的にはMesh自体が持っている超点数よりも2倍近く表示されているということがわかりました。
試しにCube(8頂点) のみを画面内においたところ頂点数が16と表示されていました。
これに関しては今後調査する必要がありそうです。



2012年8月9日木曜日

パーティクルシステムShuriken

パーティクルシステムがShurikenに変わってからどうやって設定したら思い通りのパーティクルが作れるか悩んでいる人も多いみたいです。そもそも、項目が分けわからんという人も結構いるみたいですが...
意外と簡単だったりします。




上から順番に確認していきましょう。
ParticleSystemをクリックするとまずは基本となる部分が出てきます。どの要素も名前で大体判別できると思います。重要なのは、値を入力できるフィールドの右はじに下向きの三角形がついているものです。三角を押すことでわかりますが、フィールドの値をカーブやランダムな値等柔軟に入力できるようになります。これに関しては今後の部分でも非常に良く使用する部分ではあります。

・Emission
エミッションとは排出のことを指し示しています。すなわち、パーティクルの要素一つ一つがどのように発射されるかを定義する部分です。基本はTimeで値を設定するだけで良いでしょう。

・Shape
パーティクルがどのような形で排出されるかを設定することが出来ます。デフォルトはCornすなわち上に向かって開いている三角錐みたいな感じになっています。そのため、初期のパーティクルが上向きに広がるようになっています。ほかにはBoxやSphereなどの形状が設定でき、どれもその形に添って発出します。

・ 〜〜 over LifeTime系
パーティクルのライフタイムに応じて様々な値を変更することができます。

・〜〜 over Speed
上記と同様にスピードに応じて変更が出来ます。

・Collision
Colliderの衝突判定を設定すること可能です。設定したTransform情報(座標、回転)から面を作り、発生したパーティクルはそれに反射するようになります。

・SubEmitter
パーティクルの発生に伴い更に別のパーティクルを発生させることができます。Birth(発生時)、Death(消失時)、Collision(衝突時)それぞれに対して設定できます。

・TextureSheetAnimation
テクスチャを分割してアニメーションさせます。XおよびYで分割数を、Animationで全体を巡るのか一つの軸(XもしくはY)のみ巡るのか、Cyclesでスクロールする回数を設定できます。

・Renderer
パーティクルで使用するマテリアル等を設定します。パーティクルの表示方法や最大サイズ等を設定することが可能です。

こんな感じです。
正直使ってみれば意外とわかりやすいことがわかります。

2012年8月7日火曜日

FGJに参加してきました

つい昨日まで福島にいました。
もちろんFGJに参加するためです。

今回でゲームジャムは三回目でしたが、制限時間30時間はなかなかにしんどかったです。企画やコンセプトは早い段階で決まりましたが、思うように実装が進まないこともあります。
特に今回はUnityにおいて2Dゲームを作成するということでUni2Dを使用しました。
こいつは、作成した画像データからコリジョンを自動で生成してくれるというなかなかの優れもので、Unityで2Dの物理系ゲームを作成するならば見ておいても損はなさそうです。

しかし、こいつになかなかに振り回された部分もありました。
テクスチャからコリジョンを作成する際にプレハブを生成するのですが、どうやら自動でリソースを作成してしまうようでAssetServerを利用しているとコンフリクトしまくるということが発生しました。
直接的なダメージは無いものの、Updateするたびに毎回コンフリクトするのはなかなかに面倒です。また、今回はWebPlayer上での発表だったため問題なかったのですが、iOSやAndroid向けに使用するにはまだまだ重いということも聞きます。これらのことが解決されれば非常に強力なツールとして広まるのではないでしょうか。

ここでまたFGJの話に戻ります。
今回自分は3班に参加しました。主にプログラムとサウンドを扱いましたが、やはりまだまだスキルアップの余地があるなあとも思いました。また、今回初めてペアプログラミングを行ったのですが、なかなかにたのしかったです。バグを見つけるには十分な目の数があればいいとかなんとかそんな話もありますが、事実二人で一つの処理を考えれば意外としっかりとしたものができるようです。

次回のGGJではリーダーに立候補しようかなぁとも考えるこのごろです。

技術系の話はまた明日からつづきます。

2012年8月3日金曜日

マイクから音を取得して波形を描画する

今回はマイクから音を取得して波形を生成するプログラムを作成しました。その結果は


こんな感じになりました。

今回のソースは



こんな感じです。
音声の入力にはMicrophoneクラスを、波形の描画に関してはLineRendererを使用しています。PlayClip関数内のwhile文の中にあるマジックナンバーは主に波形の描画位置の調整を行っています。




2012年8月2日木曜日

最適化のお話

最適化についてまとめます。
特にiPhoneやAndroid向けに開発する場合は悩まされる部分ではあります。
Unityに限らず役に立つ部分もあるかもしれません。

まず最適化を行う上で意識すべきことはキャッシュすることです。
毎ループごとにGetComponent()しているような部分はStartであらかじめキャッシュすることで無駄な処理を省くことができます。
また、ComponentだけではなくFind()で探しているオブジェクトや、結果が変わらない計算等はキャッシュするのが基本です。

ほかにもRaycastのキャッシュも効果があります。Raycast自身を無意識で使用してしまうととんでもないネックになることがほとんどです。LayerMaskを指定して判定を行うオブジェクトを少なくすることは当然ですが、一度判定が取れたのならばその判定をキャッシュしておきRaycastHit.colliderからコライダのRaycastを使用するようにしましょう。
Physics.Raycastが全てのコライダと判定をとろうとするのに対してCollider.Raycastではコライダ自身との判定をとるだけなので圧倒的にコストが変わると考えられます。

キャッシュの他にはUpdateおよびFixedUpdateで処理する内容に注意する必要があります。特にFixedUpdateは単位時間あたりに呼び出される回数がUpdateよりも多いので、気をつけないと非常に危険です。とくに前述のRaycastと複合されてしまうと非常に大きなネックとなります。

最後にベクター系クラスのmagnitudeには気をつける必要があります。ベクトルの大きさを求める際には三平方の定理からもわかりますが、平方根の計算を行う必要があり、それには地味に負荷がかかります。単にベクトルの大小比較を行うだけであればsqrMagnitudeを使用しましょう。こちらの値は最後に平方根をとる部分が除かれているすなわち大きさの二乗の値が取れることになり、x < y ならば x^2 < y^2 となるので単純な大小比較だけであればこちらで問題ありません。

今回はプログラムを中心にまとめました。
バッチやDrawcallなどプログラム以外に深く関わっている部分に関しては後日まとめます。

2012年7月27日金曜日

しってると便利な小技系関数

知っとくと意外と得する関数について今日は紹介していきます。

GameObject.SetActiveRecursively(bool)
あるゲームオブジェクトおよびそのオブジェクトの全ての子オブジェクトをアクティブor非アクティブにすることができる。
➡複雑な階層構造のオブジェクトをまとめて非アクティブにする際に便利です。

GameObject.GetComponentInChildren(Type)
あるゲームオブジェクトの子オブジェクトから指定のコンポーネントを取り出す。
➡GetComponent"s"にすることで複数あった場合にまとめて取得することが出来る。こちらも階層構造になっているオブジェクトを扱うときに便利。

Mathf.Rad2Deg Mathf.Deg2Rad
値を度数法と弧度法でそれぞれ変換する
➡ angle = radian * Mathf.Rad2Deg のように使用する。この場合は弧度法から度数法へ変換したことになる。

Mathf.PingPong(float t , float length)
0〜lengthの値をピンポン球を床に反発させているかのように行き来させた値を取得することが出来る。
➡サンプルにもあるが hoge = Mathf.PingPong(time.deltaTime . 10.0); のように使用するこの場合 hoge には0~10.0までの値が入る。

Lerp(Hoge fuga1, Hoge fuga2 , float rate) Slerp(Hoge fuga1, Hoge fuga2 , float rate)
Lerpは線形補完、Slerpは球面線形を補完を行い、rateの比率分だけ進んだ値を返す。
➡Lerpでは二点を直線的に結び、Slerpは曲線でなめらかに結ぶ。Vector3やQuaternionなど様々な型で用意されている。例えばLerp(v1,v2,0.5)ではv1とv2の中点が取得できる。

ほかにもたくさん便利な関数が用意されています。
本日は眠いのでここまで。後日またまとめていきます。



2012年7月26日木曜日

続・Layerについて

Layerについて昨日書けなかった部分を書いていきます。
昨日はカメラのカリングマスクとして使用しましたが、Lightのカリングマスクとして使用することも可能です。

まずは設定なしの状態

















カリングマスクを設定するにはLightのコンポーネントの下から二番目のタブで、カメラと同様に設定することが可能。


















まずは青いライトのカリングマスクからPlaneをのぞいた場合。
Planeには青いライトの影響がなくなっています。
















つづいて、青はSphereに、緑はCubeに、赤はPlaneにのみ影響するようにしました。
影響を明らかにするためにLightProbeをOffにしました。
















このような機能を使用することでプレイヤーキャラクターのみにあたるライト等を作成することが可能になっています。


続いてLayerMaskと衝突判定について。
先ほどのシーンのCubeとSphereにRigidbodyを追加することで、剛体運動をさせるようにします。この場合通常であれば下にあるPlaneに衝突します。
















ここでPhysicsManagerからLayerごとの衝突判定を設定します。PhysicsManagerはEdit➡ProjectSettings➡Physicsを選択することでInspector上に現れます。





















ここの下のマトリクスで衝突判定に関して設定できます。今回はSphereとPlaneの衝突判定をOffにしました。
















そうするとこのようにSphereとPlaneの衝突判定がなくなります。



















これらのようにLayer設定を分けることで様々なことが出来るようになります。この他にもゲーム制作では書かせないRaycastなどもLayerMaskを指定することで処理を軽くすることが可能になったりします。




2012年7月25日水曜日

Layerについて

UnityのLayerの機能を上手に利用することで様々な処理が行えるようになる。
まず、Layerの設定方法について。
インスペクタの最上部





この右下のタブで選択する。
自分でレイヤーを追加するには、AddLayerを選択することでUserLayerに命名出来る。

第一の使い方としてカメラのCullingMaskとして使用することが出来る。
インスペクタから












チェックマークが入っているレイヤーに指定されたオブジェクトはレンダリングされます。

















画像ではわかりにくいですが、このように設定次第で描画されたりされなくなったりします。
これを応用することでUIのみを別カメラで描画し、重ね合わせることが出来ます。
















このとき注意しなくてはならないのがカメラのClearFlagsとDepthです。
この例では右上をベースに左上を重ねているのですが、左上のスフィアを描画しているカメラの設定を


















このようにしています。
まず、Depthを-1から0にすることで-1となっているベースのカメラよりも後にこのカメラの描画結果を処理することになります。
次にClearFlagsをDepth onlyにすることで、すでにベースのカメラで描画したものの上にこのカメラで描画したものを書き込みます。ここをSkyboxもしくはSolid Colorにしてしまうと、既にベースのカメラで描画されている内容が塗りつぶされてしまい、現在のカメラでの描画しているものしか見ることが出来なくなってしまいます。

このようにLayerを分けることで描画関係で複雑なことが出来るようになります。
ほかにも衝突判定やライティング等においてもレイヤー分けすることで特殊な扱いができるので、それについては後日扱います。

2012年7月23日月曜日

OnCollisionHogeHoge()とOnTriggerHogeHoge()

衝突検知の際に扱う関数といえばOnCollisionEnter()もしくはOnTriggerEnter()ですが、
もうちょっとこれらの関数を知っておくと、より自由に衝突関係を扱うことが出来ます。

まず、衝突関係の関数を列挙します。

Collision系列
OnCollisionEnter(Collision)
OnCollisionStay(Collision)
OnCollisionExit(Collision)

Trigger系列
OnTriggerEnter(Collider)
OnTriggerStay(Collider)
OnTriggerExit(Collider)

Collision系列とTrigger系列の大きな違いとして
Rigidbodyの必要性
があります。

Trigger系列はColliderのIsTriggerのチェックボックスをオンにするだけで良いですが、
Collider系列は衝突したオブジェクト”両方”がColliderとRigidbodyを持っている必要があります。
つまり動くもの同士の衝突検知はOnCollisionHogeHoge()で、
どちらかが動かない場合はOnTriggerHogeHoge()で検知する必要があります。

また、それぞれの引数はCollisionとColliderと若干異なっています。
OnCollisionHogeHoge()では衝突自身を検知できるため引数がCollisionとなり、
OnTriggerHogeHoge()では衝突しているオブジェクトしか検知できないため、Colliderなのではないかと考えられます。

CollisionとColliderの大きな違いとしてContactPoint、
すなわち接点が取得できる出来ないにあると考えられます。

加えて、それぞれのStayおよびExitを使いこなせると自由に衝突関係を扱うことが出来るでしょう。
注意すべきはFugaFugaStay()系列で、OnCollisionStay()でもOnTriggerStay()でも、
有効になっている間はFixedUpdateの度に呼び出されます。これらのなかに重い処理を入れてしまうと簡単に処理落ちしてしまうので注意しましょう。特にMobile向けに開発する際には注意が必要です。



キーボードショートカット(Mac)

Unityでもなんでもとにかくツールを自由自在に扱うには、
キーボードショートカットを覚えることが重要です。

なので、今回は自分がよく使うキーボードショートカットをまとめていきます。

自分の環境はMacなのでWindowsの方はごめんなさい。

CMD + N = 新しいシーンの作成
CMD + S = 現在のシーンの保存

CMD + Z = アンドゥ
CMD + Shift + Z = リドゥ

CMD + C = 現在選択しているオブジェクトをコピー
CMD + X = 現在選択しているオブジェクトをカット
CMD + V = コピーしたオブジェクトの複製
CMD + D = 現在選択しているオブジェクトの複製
CMD + Shift + N = 空のGameObjectの作成

CMD + B = ビルド
CMD + Shift + B = ビルドオプションを開く

シーンビューがアクティブな状態で F = 選択しているオブジェクトにフォーカス
オブジェクトを選択している状態で V = 頂点スナップ

頂点スナップってなにか

Vキー押すと











こうなって、ほかのオブジェクトに近づけると












ぴたっとくっつく。
頂点ごとにいい感じにあわせるようになります。

まとめてみるとほとんど基本的なやつで以外と量は少なかったかも。
他に思い出したら追記していきます。