投稿

2013の投稿を表示しています

[Unity]DotFabで出力したモデルを取り込む

イメージ
ドット絵を 3D にできる DotFab を Unity で使ってみたときのメモです。

最新の v0.6.1 は 3D モデル出力機能がないので、v0.4.1 を使います。

(注 : 3D の知識はほとんどないので、以下おかしなことを言っているかもしれません)

DotFab の使い方は readme を見ればわかるので割愛しますが、SAVE_3D_OBJECT で出力した .obj (と .mtl) を Unity にドラッグ & ドロップしてインポートすると、下記の画像のようになってしまいました。


どうも大半のポリゴンのマテリアルが正しく設定されていないようです。

試しに Blender でインポートしてみると正しく表示できたので、Unity で .obj のインポートに何かあるのかもしれないと思い、形式を変換してみることにしました。

最終的には .dae 形式でエクスポートすると Unity で期待通りインポートできました。


気になるのは、Blender 上での頂点数は 586 だったのが、Unity 上では 44,000 になっていることです。これはさすがに多すぎるんじゃないかなと。
(このモデルで元々 586 頂点というのも、各ポリンゴンのマテリアル設定で色をつけるのではなくテクスチャを貼ればもっと減らせそうですね)


Cube の頂点数が 8 でなく 24 になるので、Verts の表示は純粋な頂点数でない(もしくは標準の Cube は面ごとに 4 頂点 * 6 面?)のかもしれませんが、それにしても 75 倍は多いような…。


原因はまだわかりませんが、とりあえず表示は一応できたということでメモ。

[Unity]NGUIでUnityの2Dスプライトをアニメーションする

イメージ
NGUI で Unity 4.3 の 2D スプライトを使う方法は [Unity]NGUIでUnityの2Dスプライトを使う に書きましたが、今回はこれをアニメーションさせる方法です。

NGUI のバージョンは 3.0.6f6 以降が必要です。

まずは上記記事などを参考に、Unity 4.3 の 2D スプライト表示とアニメーション、NGUI で Unity の 2D スプライト表示ができるところまで準備してください。

あとは SpriteRenderer と Animator をアタッチして、数行のコードを追加すれば完成です。(空のオブジェクトに下のコードだけアタッチすれば、必要なスクリプトは全てアタッチされます。)

コードは以下。( GitHub : unity-ngui/UI2DSpriteAnimation.cs )

using UnityEngine; using System; [RequireComponent(typeof(UI2DSprite))] [RequireComponent(typeof(SpriteRenderer))] [RequireComponent(typeof(Animator))] public class UI2DSpriteAnimation : MonoBehaviour { System.WeakReference spriteRenderer_ = new System.WeakReference(null); SpriteRenderer spriteRenderer { get { return (spriteRenderer_.Target ?? (spriteRenderer_.Target = GetComponent<SpriteRenderer>())) as SpriteRenderer; } } System.WeakReference ui2dSprite_ = new System.WeakReference(null); UI2DSprite ui2dSprite { get { return (ui2dSprite_.Target ?? (ui2dSprite_.Target = GetComponen…

[Unity]NGUIでUnityの2Dスプライトを使う

イメージ
Unity 4.3 で 2D スプライト機能などが強化されましたが、GUI 向けではないということで、現状 GUI は NGUI などのアセットを使うのがよいようです。

Unity の 2D スプライトと NGUI を併用する方法は少なくとも 2 種類、それぞれ独立させる方法と NGUI に取り込む方法がありますが、今回は後者について紹介します。

前提として、Unity の 2D スプライトの表示方法は把握していることとします。([Unity]Unity4.3の2D機能入門まとめ もどうぞ。)

NGUI は 3.x 系 (アニメーションも考えると 3.0.6f6 以降) を使ってください。

NGUI で Unity の 2D スプライトを表示するには、UI2DSprite を使うだけと簡単です。

いつも通りメニューから NGUI -> Create -> 2D UI として UIRoot などを作成したあと、NGUI -> Create -> Unity 2D Sprite します。

あとはスプライトをインスペクタにドラッグ&ドロップするだけ(下図)。


これで NGUI と座標系やサイズを共有し、NGUI のイベント処理も使えるようになります。

Unity のスプライトアニメーションとも連携できます。方法はこちら( [Unity]NGUIでUnityの2Dスプライトをアニメーションする )。


NGUI の更新情報はこちら。

ゲームは初心者にやさしく: NGUI 3.0.6 リリース

ゲームは初心者にやさしく: NGUI チュートリアルビデオ(3.0.6 対応で最新化!)
2013/12/9 追記 : [Unity]NGUIでUnityの2Dスプライトをアニメーションする を書きました。

[Unity]Unity4.3の2D機能入門まとめ

Unity4.3 で 2D 系の機能が強化され、スプライト表示やアニメーションなどが便利になりました。

これについては皆さんすでに書かれていますので、自分がとりあえず入門レベルになるまでにお世話になったサイトをまとめておきます。


Unity2DとNewGUIについて : Unity の中の人のスライド。Unity の 2D 機能の概要、噂の次期 GUI (uGUI) との住み分けの話など。uGUI が出るまでの GUI 作成は Unity の 2D スプライトではなく NGUI とか使っておくといいかも、といったことも書いてありました。


スプライトを表示して最低限のアニメーションをするところまでは以下のサイトを見ればできると思います。

Unity4.3 で追加された Sprite 機能を使ってみよう - その1 - Unityではじめるゲーム開発 - Mobile Touch

Unity 4.3 2D Spriteの使い方:TextrueとSpriteのパラメーターについて - タカシカンパニーブログ

テラシュールウェア [Unity]Unity2d機能、スプライトの使い方

テラシュールウェア [Unity]Unityのスプライトアニメーションの使い方(基本編)


標準のスプライト分割機能は一枚の画像に異なるサイズのスプライトを詰め込むと使いにくいので、ツール作ったほうがいいかな…と思っていたらすでに作られていました。まだ試してはいないのですが TexturePacker ユーザーには便利だと思います。

テラシュールウェア [Unity]TexturePackerで一つにまとめたテクスチャをUnity 2Dのスプライトで使う


もっと見る場合はこちらも。

UNITY - アップデート情報 : Unity4.3 リリースノート

Unity 4.3 - 2D Game Development Walkthrough - YouTube : 公式ビデオチュートリアル

[Unity]null合体演算子でコンポーネントへのアクセスをスマートにする

C# の null 合体演算子 "??" が地味に便利です。

C/C++ はじめ、他の言語ではあまり見かけない、というか C# くらいにしか無さそうな演算子なのでなじみが薄い方も多いのではないかと思いますが、 ?? の左が null でなければ左、null なら右を返す演算子です。

??演算子 (C# リファレンス)

(2013/12/8 追記 : 型によって期待通り動かないことがあるかもしれません。具体的には UnityEngine.Animator がダメでした(弱参照にした場合はもちろん大丈夫でした)。参照型だと思うのですが…理由はまだ分かりませんが取り急ぎ。 /Unity 4.3)

Unity だとこんな感じで GetComponent() や Find() などの結果を高速化のためにキャッシュしておいたり、
private Hoge hoge_ = null; void Func(){ Hoge hoge = hoge_ ?? (hoge_ = GetComponent<hoge>()); hoge.DoSomething(); }
子オブジェクトのコンポーネントへの getter を提供したり、
System.WeakReference piyo_ = new System.WeakReference(null); public Piyo piyo { get { return (piyo_.Target ?? (piyo_.Target = transform.GetComponentInChildren<Piyo>())) as Piyo; } }
あるコンポーネントが付加されていなかったら追加しつつ取得する拡張メソッドを書いたりと、地味ながらよく使う処理をスマートに書けます。
public static class GameObjectExtentions { public static Component ExAttachComponent(this GameObject gameObject, string type) { if(!gameObject){ return null; } return gameObject.G…

[Unity]Monodevelopの.NET Frameworkのバージョンを設定する

イメージ
C# のデフォルト引数など、C# 4.0 からの機能を MonoDevelop でビルドできるようにするには、MonoDevelop のフレームワークを .NET (Mono) 4.0 に設定する必要があります。(デフォルトでは 3.5?)

設定は MonoDevelop 2.8.2 現在、Project > Assembly-CSharp Options > Build > General > Target framework にあります。


MonoDevelop でビルドできるかどうかと Unity でビルドできるかどうかは関係ないので設定は必須ではありませんが、MonoDevelop でエラーが出ていると気持ち悪いしちょっと不便ですね。

参考 :
MonoDevelopでデフォルトのTarget frameworkをMono.NET 4.0に変更する - Virtual Memory

[Unity]NGUIで当たり判定を付ける

NGUI でスプライトに当たり判定を付ける場合、普通に

スプライトに Collider を付ける必要に応じて RigidBody も付けるOnCollisiionEnter などを書く
とした上で、

RigidBody の FreezePosision の z と FreezeRotation の x, y にチェック(負荷が減る、と思う)表示順の制御に z 座標を使っている場合、衝突し得るように Collider の Size.z などを調整クリック等のイベントを受け取るスプライトの Collider は最も手前になるようにするまたは、イベントを受け取るスプライトを含む UIPanel のレイヤを分け(スプライト個別にはレイヤを変更できないため UIPanel 単位になる)、UICamera の Event Receiver Mask をそのレイヤだけに、Camera の Culling Mask はそのレイヤも表示するようにする あたりに気を付けるとよさそうです。
複数のスプライトが他のオブジェクトの子である場合などは、Collider は各スプライトに付け、イベントは親オブジェクトで処理(スプライト側で一旦受けて親に SendMessage)するのもよいかもしれません。
3D 用の衝突判定を 2D で使うのは富豪的な気もしますが…

[Unity]NGUIのOnDragイベントを使う

NGUI のスプライトをドラッグで動かせるようにしたときのメモです。

(2013/5/9 追記 : 動かすだけなら UIDragObject だけで済みます。こちらはコーディング不要です。)

スプライトに Collider をつけた上で、

public class Player : MonoBehaviour { void OnDrag(Vector2 delta) { Vector2 mousePoint = UICamera.lastTouchPosition; Vector2 worldPoint = UICamera.currentCamera.ScreenToWorldPoint(mousePoint); transform.position = new Vector3(worldPoint.x, worldPoint.y, transform.position.z); } }
または

public class Player : MonoBehaviour { void OnDrag(Vector2 delta) { Vector2 mousePoint = UICamera.lastTouchPosition; Vector2 worldPoint = UICamera.currentCamera.ScreenToWorldPoint(mousePoint); // 普通は毎回 Find() しない transform.localPosition = GameObject.Find("UI Root (2D)").transform.InverseTransformPoint(new Vector3(worldPoint.x, worldPoint.y, 0)); } }
などですね。

引数の delta はスクリーン座標上での前回のマウス位置との差分(だと思う)なので、UIRoot の Scaling Style を Pixel Perfect にしていない限りはそのままでは使いにくそうですね。

2013/5/9 追記 : UID…

[Unity]NGUIでスプライトを隙間なく並べる

イメージ
NGUI で 2D ゲーム風にドット絵のマップチップを敷き詰めた時などに、スプライト間に 1px 程度の隙間が空いてしまう場合の確認内容です。

テクスチャの Filter Mode を Point にする

元画像を周囲 1px 拡大しておく(TexturePacker を使っているなら、Layout の Extrude を 1 にするだけで簡単にできます)



[Unity]NGUIで画面サイズに合わせる(NGUI2.3.0対応版)

以前 [Unity]NGUIで画面サイズに合わせる(その2) で書いたスクリプトが、NGUI 2.3.0 の変更との兼ね合いで正しく動かなくなっていたので、今更ですが対応版です。

UIRoot.automatic が obsolete 扱いになり、代わりに scalingStyle というパラメータに変更になったようです。

PixelPerfect : 拡大縮小しない(automatic = true 相当)FixedSize : 画面の高さに合わせる(automatic = false 相当)FixedSizeOnMobile : iOS, Android のときは FixedSize、それ以外では PixedPerfect
横がはみ出ないように画面の幅に合わせる機能は現在でもないようですね。

というわけで、数行しか変わっていませんが 2.3.0 対応版です。

using UnityEngine; [ExecuteInEditMode] public class UIRootScale : MonoBehaviour { public int manualWidth = 1280; public int manualHeight = 720; UIRoot uiRoot_; public float ratio { get { if(!uiRoot_){ return 1.0F; } return (float)Screen.height / uiRoot_.manualHeight; } } void Awake() { uiRoot_ = GetComponent<UIRoot>(); } void Update() { if(!uiRoot_ || manualWidth <= 0 || manualHeight <= 0){ return; } int h = manualHeight; float r = (float)(Screen.height * …

[Unity]インスタンス生成時に引数を渡したい

Unity で、インスタンス生成時にパラメータを設定したいとします。

たとえばプレハブから生成する場合、Object.Instantiate() は引数を取れないので、一般的には以下のように生成後にセットすることになります。

public class MyClass : MonoBehaviour { public int param1 { get; set; } public int param2 { get; set; } void Start(){ Debug.Log("MyClass : param = " + param1 + ", " + param2); } } public class MyTest : MonoBehaviour { public MyClass myClassPrefab; public int paramA; public int paramB; void Awake() { MyClass obj = Instantiate(myClassPrefab) as MyClass; obj.param1 = paramA; obj.param2 = paramB; } }
これでも大きな問題があるわけではありませんが、MyClass の param1, 2 がいつでも外部から書き換え可能になっているので、MyClass 側では初期化以降もパラメータが変わることの考慮や、MyClass を使う側では param1, 2 を後から変えていいのかどうかの判断が必要になります。

コメントで「初期化直後以外は変えるな!」と書いて済ましてしまうのもひとつの手ではありますが、もうちょっと考えてみましょう。(以下、こういう細かい話が続きますよ!)

さて、とりあえず param1, 2 を外部から直接変更できなくして、いかにも初期化時しか呼んではいけなさそうな関数 Initialize() でのみセットできるようにしてみます。

public class MyClass : MonoBehaviour { public int param1 { get; p…