カテゴリー別アーカイブ: Unity

[Unity3D][NGUI]ボタンの作り方最小構成

環境

  • Unity3D : 4.5.1f3
  • NGUI : 3.7.4

やること

  • ボタン用のGameObjectを作る … A
  • AにButtonとUILabelかUISpriteをアタッチする
  • AにBoxColliderをアタッチする
  • ボタンを押した時用のスクリプトを書く … B
  • BをAにアタッチする。
  • AにアタッチしたButtonのイベント
  • 実はBはAにアタッチしなくても良い。

続きを読む

[Unity][uniSWF]newしたMovieClipが突然なくなってしまう現象でハマった話

Uniswfを使用しているとプログラム上で動的にMovieClipを生成したくなることがある。
これでちょっと複雑な構造にするだけで意図した動作がなされないことが良くある。

次のコードで例を示す。

    public Vector2 v2Out;
    MovieClip linkage;
    List<MovieClip> c = new List<MovieClip>();
    private void Test(){
        var stage = MovieClipOverlayCameraBehaviour.instance.stage; 
        var a = new MovieClip();
        var im = new MovieClip();
        a.addChild(im);

        var textureA = Resources.Load("images/iconA")  as Texture2D;
        var textureB = Resources.Load("images/iconB")  as Texture2D;
        a.graphics.drawRectUV( 
            texture,
            new Rect(0, 0, 1, 1),
            new Rect(0, 0, textureA.width, textureA.height)
        );
        im.graphics.drawRectUV( // この描画は失われる。
            texture,
            new Rect(0, 0, 2, 2),
            new Rect(0, 0, textureB.width, textureB.height)
        );

        this.linkage.addChild( a );
        c.Add(a);
        a.x = cor.v2Out.x;
        a.y = cor.v2Out.y;

        MovieClipOverlayCameraBehaviour.instance.stage.addChild(this.linkage);
    }
    private void TestMcStructOut(){
        var stage = MovieClipOverlayCameraBehaviour.instance.stage; 
        Debug.Log( "ListCount : " + this.c.Count + " : linkage has :" + this.linkage.numChildren + " : stage has :" + stage.numChildren + " : a's child : " + (this.linkage.getChildAt(0) as MovieClipUtil).numChildren );
    }
    void Update(){
        if(c.Count < 1) Test();
        else{
            //c.ForEach( d => this.linkage.addChild( d ) );
            //c.ForEach( d => d.visible = true );
            c[0].x = v2Out.x;
            c[0].y = v2Out.y;
        }
        TestMcStructOut();
    }

‘Vector2’ 型のメンバ v2Out は描画させたい MovieClip の位置を変更させるためのものとして用意。
Unityを再生中でもMovieClipをぐりぐり動かせる。

Test関数内部で作成しているMovieClipの構造を改めて示すと、

    stage -> linkage -> a -> im

これを実行すると最初のフレームだけ textureA, B の両方が描画され、次のフレームでは im に描画した textureB は消滅している。

状況を整理すると
– linkage はメンバなので次のフレームでは削除される
– a はメンバではないけれども list c で参照を保持している。
– im はメンバでもないし参照を保持していない。
– 消えているのはimだけでaに描画したテクスチャは表示され続けている。

推察1 MovieClip im がメンバじゃないから失われている

im は Test() の中で創られているので関数終了後はUnity上では参照を失っている。
なので自動でガベコレ的なものがuniSWF内で動作しているのであれば参照を保持しておけば大丈夫なはずだと考え、メンバに MovieClip 型の tmpim を追加した。

しかし結果は描画されず。

メンバ変数に格納すると参照をすぐに見いだせる。当たり前だけど参照そのもは破棄はされていないことが確認できた。

    if(tmpim != null) Debug.Log("alright!"); // ここを通る事は無い。

推察2 親子関係だけ外れてしまったのでは?

前項で調べた通り、参照先は失われていなかったので描画対象ではなくなったのではと考え、子の数を調べる関数でチェックを行った。

    private void TestMcStructOut(){
        var stage = MovieClipOverlayCameraBehaviour.instance.stage; 
        Debug.Log( "ListCount : " + this.c.Count + " : linkage has :" + this.linkage.numChildren + " : stage has :" + stage.numChildren );
    }

ここに記述されている ‘numChildren’ が子の数を保持しているプロパティ。
これを回すと最初の ‘Test()’ では linkage.numChildren が 1 だけど次のフレームで記述されたログには 0 になっている。

ここで外れてしまう親子関係だけどうにかするのも手としてはありなのだけどもう一歩踏み込んでみた。

親子関係は破壊されるけれども参照先として’MovieClip’が保持される事が分かったのでこれをもうちょっと掘り進めたら以下のようになる実装になっているということが分かった。

uniSWF_couldnotStoreMovieClip by Kunihiro OHGAKI, on Flickr

その場で ‘new’ した ‘MovieClip’ に ‘addChild’ した孫 ‘MovieClip’ は次のフレームでは親子関係が破棄されている。

まとめ

  • MovieClip をその場で生成する場合はメンバに格納すべき。
  • メンバに格納済の MovieClip でも、さらにその子の MovieClip に描画した場合は親子関係が破棄される。
  • その場で ‘new’ した MovieClip に直接 graphics を記述した場合は問題なく保持される。

対策

List形式とかで生成したやつは全部格納しておき、そこからアクセスするとか。

けっこう色んなパターンを調べてやっとこの結論に至ったのだけれども間違いがあったらご指摘いただきたい。

Unityによる2Dゲーム開発入門 ~プログラミング初心者がゲームを公開する最短コース

おまけ

uniSWFの問題点

  • uniSWFはswf化してからunityに取り込むので何かするにもFlaファイルを開かなければならないのでアプリケーション常に2つ立ち上げっぱなし。
  • さらにflaの素材編集となるとphotoshopも立ち上げなければならない。
  • さらにphotoshopのデータで曲線使ってたりするとillustratorも…
  • ちょっとしたレイアウト調整がGameObjectのInspectorでできない。やれるけど標準的ではない。
  • ソフトウェアレンダリングなので最初の1フレームはデバイスの画面によって拡大縮小された表示が見える。
  • 描画コストが高い。ドローコール減らせない。
  • unityのアップグレードにどこまでついて来れるのやら心配。
  • ドキュメントが完成してない。実は実装済みでドキュメントに記載が無いって事も多々ある。
  • swf作成のお約束が多い。
  • フォントが不自由。
  • フォントサイズも不自由。

uniSWFの使いどころ

  • アニメーション作業がしやすいのでガチャみたいな画面全域で表示しつつ演出過剰にしたい場所では作業を完全に切り分けられるのでオススメ。
  • monoDevelopでソースが見れるのでswfがどういう構造になってるのか勉強になるかも。

演出だけは突出した真価を発揮する。uniSWFをコレからも宜しくお願いします。間違ってもUI全部にuniSWFを使っては行けない!マジで!(涙目)

[JS]GoogleDocsの画像をgithubに貼付けるための直リンク生成bookmarkletを作った

githubにはwikiを記述できるのだけど、wikiに記述する画像はuploadできない。
dropbox等のローカルにファイルが占有されることがないかたちで共有するにはどうしたらいいか調べ所、google drive上のimageから直リンクが取れるという事がわかった。
Permalinks for Google Drive Images

手順

  1. google drive に共有用フォルダを作成する。
  2. 画像をup
  3. google drive 上にある画像を右クリックで 開く->ドライブビューワ で開く。
  4. URLを先のリンクに従って変更する
  5. ねんがんの 直リンクURI をてにいれたぞ

ここで4のURLを毎度変更するのが面倒だったのでブックマークレットを作成した。
続きを読む

[Unity3D][Unity:Editor]Editor拡張会のまとめの続き

Editor拡張会のまとめの続き

エラい時間が空いたどころか、年が明けてしまいました。今年も宜しくお願いします。
それとは別で講習中にとっていたメモが消失してしまって問題内容とか解答とかが分からなくなってしまったのでこのシリーズいったんやめようと思いますです。
テーマやコードはupされているのでそれにリンクを張る形をとった上で今回でいちど閉じたいと思います。

[wp_ad_camp_1]

Q 3

  • お題:GenericMenu
    • EditorWindowにコンテキストメニューを表示し「CreateCube」を選択してCubeを生成しなさい

やること

  • 右クリックのイベントを取得しなければならい。
  • イベントはOnGUI内で確認できる。
  • メニューはGenericMenuオブジェクトをnewする。
  • アイテムを追加する。
  • ShowAsContext()を忘れずに。

createCubeはprimitiveを使う。

GameObject.CreatePrimitive(PrimitiveType.Cube);

GenericMenuとは何か

  • GenericMenu
    GenericMenuとはコンテキストメニューとかドロップダウンメニューとかを提供するクラス。

  • AddItemでアイテムを追加して項目を増やす。

  • AddDisableItemはグレーアウト。
  • AddSeparator
  • DropDown
  • GetItemCountでアイテム数を確認。
  • ShowAsContextで実際に表示を行う。

GUIContentとは何か

以降のお題と回答例

Q 3 Pratical

解答例

Q 4

  • お題:CustomEditor

Q 4 Pratical

Q 5

  • お題:Gizmo

Q 5 Pratical

Q 6

  • お題:Handles

Q 6 Pratical

Q 7

  • お題:ScriptableObject & AssetDatabase

Q 7 Pratical

Q 8

  • お題:PostProcessor

Q 8 Pratical

Q 9

  • お題:EditorApplication & EditorUtility

Q 9 Pratical

Q 10

  • お題:Undo & Redo

Q 10 Pratical

ありません。

C#ショートコードプログラミング 第2版 (MSDNプログラミング)

[Unity3D][C#][Unity:Editor]GUILayout/EditorGUILayout/ObjectFieldまとめ

UnityEditorの出題2とGUILayoutやらEditorGUILayoutやら

引き続き、Editor拡張の会の出題と解答を参考に作成してます。

CodeIQにも出題されているのでやってみると面白いと思います。
日本Androidの会 秋葉原支部 Unity部 安藤 圭吾さんの問題に挑戦中!

[wp_ad_camp_1]

Q 2

  • お題:EditorWindow
    • ウィンドウを出現させて各パラメータの調整項目を出現させてね!
  1. EditorWindow継承クラスをGetWindow、またはCreateWindowで出現させる。
  2. OnGUIイベント内でEditorGUILayoutを使ってパラメータの反映をさせるためのUIを作成する記述をする。

GUILayoutはUnityの用意したゲーム画面用のGUIでやたらと重いクラス。
とはいえ3Dをバリバリ使う事が無ければそれほど気にならない。
GUILayoutにEditro部分のように描画させようとしても記述が増えてしまう。

EditorGUILayoutに名前部分の記述をさせるとこうなる

this.name = EditorGUILayout.TextField("名前",this.name);
EditorGUILayoutだとこんなにシンプル。
実際に表示される内容は、項目名と入力ボックス。入力をすると自動的に参照先に上書きされる。

GUILayoutに同じ事やらせるとこうなる

GUILayout.BeginHorizontal();<br />
GUILayout.Label("名前");<br />
this.str = GUILayout.TextField("Default Name");<br />
GUILayout.EndHorizontal();

お分かりいただけただろうか…。長い。

ただ、UnityEngine内にあるし、ゲーム画面側にも描画できるので覚えて居た方が良い。
実機デバッグでむちゃくちゃ重宝する。

そしてwindow.Show();は忘れずに。

Q 2 Pratical

  • 追加:基礎編に追加でテクスチャをD&Dする矩形を設けてくださいな。
    解答例

できませんでした。

回答例から何をすべきだったかを導きだす。
– テクスチャ格納メンバの追加
– テクスチャ格納領域の表示

テクスチャはUnityEngine.Texture2Dを使用することで解決できるが、問題はDrag&Dropする領域。
EditorGUILayoutを見てみるとオブジェクトを格納できるのは1つだけ。
EditorGUILayout.ObjectFieldを参照してみる。

実際、出題中もここは確認したのだけれど、そもそも格納メンバがTexture2Dというところまで到達できていなかったので、この項目を使うべきだとは思わなかった。これはUnityが用意しているObject型に対する造詣がまだまだ甘かったということの証左。精進します。

“`
Texture2D texture;

texture = (Texture2D)EditorGUILayout.ObjectField(texture, typeof(Texture2D), false, GUILayout.Width(64), GUILayout.Height(64));

“`

回答例をみてみると、EditorGUILayout.ObjectFieldの表示サイズを変更している。
第四引数、第五引数だ。これについては後述する。

ObjectFieldの引数について

ドキュメントの丸写しだけれども。
– label
– フィールドの戦闘にだすためのラベル
– obj
– 実際にターゲットになるオブジェクト
– objType
– オブジェクトのタイプ
– allowSceneObjects
– シーン内のオブジェクトを受け入れるか否か。後述。
– options
– 次の項目で解説。

allowSceneObjectsについて

これをfalseにすると、assetの一部のオブジェクトを参照していた場合、assetはシーン内の参照を保持する事は出来ない。
– ※訳あってんのか…?

試しにGameObjectを格納することができるフィールドを用意して試してみたところ、Trueにするとシーン内(Hierarchy)内からD&Dすることができ、selectボタンをクリックした際もAssetsとSceneが選択できる。
逆にfalseにするとDrag&Dropをしようにも矩形は反応してくれないし、selectボタンをクリックしてもAssetsのみしかタブが表示されない。

つまり、そういうこと。

Gitポケットリファレンス

[Unity3D][C#]MenuItemの第二引数は何?

UnityEdtorの出題1とMenuItemのまとめ

CodeIQにも出題されているのでやってみると面白いと思います。
日本Androidの会 秋葉原支部 Unity部 安藤 圭吾さんの問題に挑戦中!

[wp_ad_camp_1]

Q 1

  • お題:MenuItem
    • メニューに項目追加してください。

実装方法

よく使う難易度の低い出題。
メタデータを埋め込まなければならない。
メタデータはC#以外では聞き慣れなかったのでわからないひとにとってはけっこうしんどいのではと今更ながら思った。
– 参考:C#::属性

[MenuItem("directory/like/this")]
static void OnChoseMenu(){}

Q 1 Pratical

  • 追加:メニューアイテムから項目を実行することで、洗濯中のGameObjectに子オブジェクトを追加しなさい。
    解答例

肝になるのはValidate()関数。
ここの関数はBoolを返すのだけど、その返り値に応じて二つ目の関数が実行されるか否かが決定するというところ。
どういうながれでそうなってるのか、ドキュメントを見てみる。

Documentより

// Validated menu item.
// Add a menu item named “Log Selected Transform Name” to MyMenu in the menu bar.
// We use a second function to validate the menu item
// so it will only be enabled if we have a transform selected.
[MenuItem ("MyMenu/Log Selected Transform Name")]
static void LogSelectedTransformName ()
{
Debug.Log ("Selected Transform is on " + Selection.activeTransform.gameObject.name + ".");
}

この前半部分が本来実行させたい内容を記述している。
後半に実行させるにあたっての条件を記述している。
ここでTrueが返らないとメニューアイテムの項目がアクティブにならず、グレーアウト表示がなされる。

// Validate the menu item defined by the function above.
// The menu item will be disabled if this function returns false.

[MenuItem ("MyMenu/Log Selected Transform Name", true)]
static bool ValidateLogSelectedTransformName () {
// Return false if no transform is selected.
return Selection.activeTransform != null;
}

falseにすると挙動は変わらない。どういった処理の流れになるのか、色々ためしてみた。

2つ以上の項目名が同じでショートカットの文字列が違う

  • このとき、両方とも併存させることができるのでValidateにあたる関数はそれぞれ作成することができる。
  • ショートカット部分も含めて同じ文字列にしておかないと、Validate用の関数として認められない。

Validate用関数はいつ呼ばれているか

return する前にDebug.Log()を仕掛けたら、メニューが閉じられる瞬間にDebug.Logの記述がなされた。

内部的な処理そのものはメニューを開いたタイミングで走り、メニューを閉じると各UIにOnGUIが呼び出されてコンソールの記述が変更される、という流れなのだろう。

つまり、代に引数はあらかじめ実行するか否かの指定として機能していると仮定できる。

実処理用の関数でもtrueを指定するとメニューを開くだけで実行される

試しにvalidate後に実行される関数の第二引数をtrueにしたところ、メニューが開かれるだけで実行されてしまった。

デフォルトの値

パラメータを省略するとfalseになるようだ。

試しに同じ階層に返り値voidの同族性の関数を2つならべたところ、競合し、記述が後の方が採択された。
エラーは出なかった。

翻ってちゃんとした実装について

というわけで間違った使い方をいくつか書いてみた。

英語があまり堪能ではないので上述のような記述を見つける事が出来なかったけれども、やってみた結果、そういった理由のようなので、答えはそういうことなんだろう。

せっかくなので試した時に使ったコードも載せておく。

Unity4入門   最新開発環境による簡単3Dゲーム製作
浅野 祐一 荒川 巧也 森 信虎
ソフトバンククリエイティブ
売り上げランキング: 19,094

[Unity3d]スクリプトファイルのデフォルト文字コードの指定

前回のポストで述べた方法ではWindows版のデフォルトの文字コードは変更されない。
変更してもUnityで生成する限りは元に戻るとのこと。

[wp_ad_camp_1]

解決策は次のリンクの通り。
DEBUG.LOG::スクリプトファイルのutf-8変換

開発ツール徹底攻略 (WEB+DB PRESS plus)

[Unity3d]プロジェクトを開始時する前にしておきたいソースファイルの文字コードの設定

プロジェクトの途中、いろんな環境で作業しているスタッフが混在していたり、スタッフが途中で増員すると環境が一人だけ違っていたりする事がある。特にコミットされたファイルの文字コードが違っていたりすると後で変更することは可能だが、svnのdiffが効かなくなったりblameで変遷を追えなくなる。

とはいえ、Unityで生成されるファイルはデフォルトでUtf-8なので、これ以外を使おうとする場合はコミット前に毎度確認しなければならなくなる。

そういった事態を回避する為に、予め特定の文字コードでファイルが生成されるように設定しておくと後々の不幸な出来事が無くなるのでメモしておく。

[wp_ad_camp_1]

親ファイル

新規に生成されるファイルは特定のファイルをコピーしただけになるので、親ファイルを特定して変更すればすべて解決する。

Environment3XMac

  • /Applications/Unity/Unity.app/Content/Resources/NewBehaviourScript.boo
  • /Applications/Unity/Unity.app/Content/Resources/NewBehaviourScript.cs
  • /Applications/Unity/Unity.app/Content/Resources/NewBehaviourScript.js
  • /Applications/Unity/Unity.app/Content/Resources/NewShader.shader

NewBehaviourScript.csとかjsとかbooとかshaderとかのファイルがあるのでこれを書き換えておく。
生成時にこれがまるっとコピペされるので署名等も入れておくと便利。

ちなみにこれらは3.xの場合。

4.x以降の場合

Environment4XMac

ファイルは.txtとして完全にテキストファイル化している。さらに、環境変数っぽいものも使えるようで、これを駆使して様々な記述ができそうではある。

Sublime Text 2 ならFileから変更が可能。
EnvironmentEncodeMac

Windows版の場合

3.xについては以下の通り。
EnvironmentFileDir_mac

  • Unity/Data/Editor/Resources/NewBehaviourScript.boo
  • Unity/Data/Editor/Resources/NewBehaviourScript.cs
  • Unity/Data/Editor/Resources/NewBehaviourScript.js
  • Unity/Data/Editor/Resources/NewShader.shader

4.xについては様々な問題により調査してません。が、多分Mac版同様の構成になってると思われるので次の単語で検索すると出てきそう。
– 80-Javascript-NewBehaviourScript.js.txt
– 81-C# Script-NewBehaviourScript.cs.txt
– 82-Boo Script-NewBehaviourScript.boo.txt
– 83-Shader-NewShader.shader.txt
– 84-Compute Shader-NewComputeShader.compute.txt

※最後のファイルは何なんでしょう…。はやく4.x環境に完全以降したい!

注意

UnityのTextAssetはiOSむけにコンパイル後、UTF-16withBOMのファイルを読み込ませてパースしようとすると、BEだろうがLEだろうがパースエラーになって落ちる。

Microsoft Windows 8 (DSP版) 64bit 日本語(新規インストール用)

Unity+NGUIで3Dオブジェクトに2D表示を行う

下準備・用意するもの

  • UISpriteオブジェクトを用意
  • 2Dカメラ(NGUIから Create New UI で作ったやつ)
  • 3D空間のカメラ(mainカメラ)
  • 3D空間のブジェクト

サンプル

gist

やってること

  1. 3Dカメラでワールド座標からスクリーン上の座標に変換
  2. 1の値を別のカメラのスクリーン座標上に変換
  3. 2D上に表示させたいアイテムのx,y座標だけ2で得た座標を上書き

※zは描画順やカメラの有効射程から外れるので無視。

ポイント

UISpriteは bottom に原点がくるように指定する。

bottomにすると原点が中央下部になるので、3Dオブジェクトのちょい上にあらかじめ表示が可能になる。

Spriteオブジェクトが乗ったパネルオブジェクトをPoint2DのplaneObjectに参照させる

そうするとパネル内で表示物を切り替えたりするときに便利だから。

ゲームメカニクス  おもしろくするためのゲームデザイン (ゲームデベロッパー)

のめりこませる技術 ─誰が物語を操るのか