「魔法少女戦記外伝」DL委託販売中!!

DMM 同人様 Melonbooks DL様 DLsite.com 様
DMM 同人様 Melonbooks DL 様 DLsite.com 様



最新記事ほか

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【Unity】Inspector に区切りを入れる【小ネタ】

久々の小ネタ記事となりました、管理人 Empress でございます。
しばらく月一の作業進捗のみとなっていましたが、久々に小ネタを投下しようと思います。


Unity を使ってゲームの開発をしていると、Inspector の項目が増えて増えて仕方がないと思います。

20160729_00.png


もともと標準機能として盛り込まれている Attribute にも [Space(~)][Header("~")] などで差別化を図ることもできるのですが、パッと見でわかり辛く項目が縦に伸びてしまいがちです。

20160729_01.png



エディタ拡張を駆使すると一定数の項目をまとめて折りたたむような処理が可能ですが、機能が特定のクラスに限定されてしまい、いつでもどこでも使えるわけではありません。

20160729_02.png
(仕様が固まっていれば、割り切ってこんな使い方も可能なんですが・・・)


そんな悩みをもとに可読性を維持しつつ、使用できる場所を限定しない「区切り」を作ってみました。





■まずは調査
ひとまず先駆者がいないか調べてみたところ、かなり理想に近いものを作成されているかたがいらっしゃいました。

KLONK GAMES - Custom Attributes in Unity3D
http://www.klonk-games.com/2014/10/custom-attributes-unity3d/

いい感じではあるのですが、できることならもう少し種類を増やせるようにしたいところです。


■手を加えてみる
というわけで、もうちょっといろいろ機能を盛り込みたいので上記のソースを基に手を加えた結果がこちらです。

20160729_03.png


■ソース
・・・で、実際に手を加えたソースがこちらになります。(原型はほぼないですがw)

using UnityEngine;
using System;

#if UNITY_EDITOR
using UnityEditor;
#endif

///
/// 区切り線の色
///

public enum SeparatorColor
{
Default = 0,

Black = 0,
Gray,
White,
Red,
Orange,
Yellow,
YellowGreen,
Green,
Cyan,
Blue,
Magenta,
}

/**
* インスペクタ内部で区切り線を引く
*/
[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = true)]
public class SeparatorAttribute : PropertyAttribute
{
// 区切り線サイズ
float lineSize = 1f;
public float LineSize { get { return lineSize; } }
// 題字
string title = null;
public string Title { get { return title; } }

// 区切り線色
SeparatorColor lineColor;
// 区切り線色(Color)
public Color LineColor { get { return GetColor(lineColor, DefaultLineColor); } }
// フォント色
SeparatorColor fontColor;
// フォント色(Color)
public Color FontColor { get { return GetColor(fontColor, DefaultFontColor); } }

// フォントスタイル
GUIStyle style = new GUIStyle();
public GUIStyle GuiStyle { get { return style; } }

// 題字のサイズ(ピクセル単位)
public Vector2 TextSize
{
get { return GuiStyle.CalcSize(new GUIContent(title)); }
}


// 標準区切り線サイズ
public const float DefaultLineSize = 1f;
// フォントを太字に
const FontStyle defaultFontStyle = FontStyle.Bold;

// 標準区切り色
public static readonly Color DefaultLineColor = Color.gray;
// 標準フォント色
public static readonly Color DefaultFontColor = Color.black;

///
/// 文字を使用しない区切りコンストラクタ(引数なし、線のサイズのみ、線のサイズ&色指定)
///

/// 区切り線のサイズ(省略可)
/// 区切り線の色(省略可)
public SeparatorAttribute(float size = DefaultLineSize, SeparatorColor lineCol = SeparatorColor.Default)
{
SetInfomation( null, SeparatorColor.Default, size, lineCol);
}
///
/// 文字を使用しない区切りコンストラクタ(線の色のみ指定)
///

/// 区切り線の色
public SeparatorAttribute(SeparatorColor lineCol)
{
SetInfomation(null, SeparatorColor.Default, DefaultLineSize, lineCol);
}
///
/// 文字を使用する区切りコンストラクタ(題字&題字色&線情報指定)
///

/// 題字("", nullは文字無しと同じ)
/// 区切り線のサイズ(省略可)
/// 区切り線の色(省略可)
public SeparatorAttribute(string title, float size = DefaultLineSize, SeparatorColor lineCol = SeparatorColor.Default)
{
SetInfomation(title, SeparatorColor.Default, size, lineCol);
}
///
/// 文字を使用する区切りコンストラクタ(題字&線情報指定)
///

/// 題字("", nullは文字無しと同じ)
/// 題字の色
/// 区切り線のサイズ(省略可)
/// 区切り線の色(省略可)
public SeparatorAttribute(string title, SeparatorColor fontColor, float size = DefaultLineSize, SeparatorColor lineCol = SeparatorColor.Default)
{
SetInfomation(title, fontColor, size, lineCol);
}

///
/// 区切り線情報を設定
///

/// 題字("", nullは文字無しと同じ)
/// 題字の色
/// 区切り線のサイズ
/// 区切り線の色
void SetInfomation(string title, SeparatorColor fontColor, float size, SeparatorColor lineCol)
{
this.title = title;
// フォントを太字に
this.style.fontStyle = defaultFontStyle;
// フォントの色を指定
this.fontColor = fontColor;
GUIStyleState styleState = new GUIStyleState();
styleState.textColor = FontColor;
this.style.normal = styleState;

this.lineSize = size;
this.lineColor = lineCol;
}

///
/// SeparatorColor -> Color 変換
///

/// 選択色
/// 標準扱いする色
/// Color型色情報
Color GetColor(SeparatorColor selColor, Color defColor)
{
switch (selColor)
{
case SeparatorColor.White:
return Color.white;
case SeparatorColor.Red:
return Color.red;
case SeparatorColor.Orange:
return new Color(1f, 0.5f, 0f);
case SeparatorColor.Yellow:
return Color.yellow;
case SeparatorColor.YellowGreen:
return new Color(0.5f, 1f, 0f);
case SeparatorColor.Green:
return Color.green;
case SeparatorColor.Cyan:
return Color.cyan;
case SeparatorColor.Blue:
return Color.blue;
case SeparatorColor.Magenta:
return Color.magenta;
case SeparatorColor.Black:
return Color.black;
case SeparatorColor.Gray:
return Color.grey;
default:
return defColor;
}
}
}

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(SeparatorAttribute))]
public class SeparatorDrawer : DecoratorDrawer
{
// 属性情報
SeparatorAttribute spAttr
{
get { return (SeparatorAttribute)attribute; }
}

public override void OnGUI(Rect position)
{
Color lineColor = spAttr.LineColor;
if (string.IsNullOrEmpty(spAttr.Title))
{
Rect line = position;
line.yMin += (GetHeight() - spAttr.LineSize) / 2f;
line.height = spAttr.LineSize;
EditorGUI.DrawRect(line, lineColor);
}
else
{
// テキストの横幅
// テキストと区切りの余白
const float spc = 2f;
// 区切りの幅
float lineWidth = (position.width - spAttr.TextSize.x) / 2.0f - spc;
// 左ライン
Rect line = position;
line.yMin += (GetHeight() - spAttr.LineSize) / 2f;
line.width = lineWidth;
line.height = spAttr.LineSize;
EditorGUI.DrawRect(line, lineColor);
// テキスト
Rect strPos = new Rect(position.position, spAttr.TextSize);
strPos.x += lineWidth + spc;
strPos.y += (GetHeight() - spAttr.TextSize.y) / 2f;
GUI.Label(strPos, spAttr.Title, spAttr.GuiStyle);
// 右ライン
line = position;
line.xMin += lineWidth + spc + spAttr.TextSize.x + spc;
line.yMin += (GetHeight() - spAttr.LineSize) / 2f;
line.width = lineWidth;
line.height = spAttr.LineSize;
EditorGUI.DrawRect(line, lineColor);
}
}

// ピクセル単位で GUI の高さを Inspector に通知
public override float GetHeight()
{
if (!string.IsNullOrEmpty(spAttr.Title))
{
if (spAttr.LineSize < spAttr.TextSize.y)
return spAttr.TextSize.y;
}
return spAttr.LineSize + 4f;
}
}
#endif

(エディタ拡張に関するコードが含まれていますが、このソースはEditorフォルダに含めないでください。)

詳しい内容についてはエディタ拡張に関する情報と照らし合わせていただけますと幸いですが、肝となる部分に少しだけ補足を・・・

・色の指定
 本当は Color 型で指定できるようにしたかったのですがC#の仕様で属性の引数にできる型が制限されているため、強引にオリジナルの列挙型 SeparatorColor での指定方法を採用しました。
(私の調査不足かもしれませんので、引数に Color などが盛り込める場合はご一報いただけますと幸いです)

・SeparatorAttribute クラスで変数をプロパティに置き換えている理由
 Visual Studio などの統合環境ではコード補足機能が優れているため何も考えずに public 宣言で公開情報にしてしまうと、属性引数として指定できない ColorGUIStyle などの変数も補足説明としてポップアップ表示してしまいますので、誤解を与える情報を抑止する保険といったところです(汗

・FontStyle.Bold の採用
 標準のスタイルだと区切り線に埋もれてしまいそうな感じがしたことと、標準で用意されている [Header("~")] との差別化が理由です。こちらも属性の引数に指定すべきか迷いましたが、複雑すぎる引数もどうかと思い見送りました。

ちなみに標準の色やフォントの形などを変更したい場合は、以下の箇所を各自で変更してご利用ください。

// 標準区切り線サイズ
public const float DefaultLineSize = 1f;
// フォントを太字に
const FontStyle defaultFontStyle = FontStyle.Bold;

// 標準区切り色
public static readonly Color DefaultLineColor = Color.gray;
// 標準フォント色
public static readonly Color DefaultFontColor = Color.black;



■使用例
ソースの解説はこのあたりで切り上げまして、実際のコードでの使用方法ですが以下のような書式でご利用ください。
こちらのソースは前述のスクリーンショットと同じ結果になるコードですが、属性の記述方法は例としてわざと統一性がない方法にしています。

[SerializeField, Separator]
string Name;
[SerializeField]
[Separator("ステータス")]
int HP;
[Separator(4)]
[SerializeField]
int maxHP;
[SerializeField, Separator(SeparatorColor.YellowGreen)]
int MP;
[SerializeField, Separator(SeparatorAttribute.DefaultLineSize, SeparatorColor.Red)]
int maxMP;
[Separator("調整", 20.5f, SeparatorColor.Cyan)]
[SerializeField, Range(1, 50)]
float JumpPower = 8f;
[Separator("攻撃に関するパラメータ群ですがどのように見えているでしょうか?")]
[SerializeField, Range(1, 50)]
float AttackPower = 8f;

[Separator("えふぇくと", SeparatorColor.Red, 20.5f, SeparatorColor.Orange)]
[SerializeField]
GameObject effectPrefab;
[SerializeField]
Vector3 effectPosition;

上記のコードは少しごちゃごちゃしていますが、具体的には5通りの記述になります。

・[Separator]
  標準的な横線のみの区切り線を描画。
・[Separator(4f [, SeparatorColor.~] )]
  区切り線の太さを float 型で指定して描画。0fを入れると線が消え、負値は正値と同じように扱われます。
  第二引数で区切り線の色を指定することもできますが省略可能です。
   記述例
    [Separator(4)]
    [Separator(8.5f, SeparatorColor.Cyan)]
・[Separator(SeparatorColor.~)]
  区切り線の色を SeparatorColor 型で指定して描画。線の太さを変更せず色のみを変更します。
   記述例
    [Separator(SeparatorColor.Black)]
・[Separator("文字列", [, 線の太さ] [, SeparatorColor.~])]
  区切り線の間に文字を入れて描画。文字指定を null や "" にすると、横線のみと同じように扱われます。
  文字列が Inspector の幅を上回ってもエラーは発生しません。
  第二引数で区切り線の太さ、第三引数で区切り線の色を指定することもできますが省略可能です。
   記述例
    [Separator("高雄")]
    [Separator("愛宕", 5f)]
    [Separator("鳥海", 5f, SeparatorColor.Blue)]
・[Separator("文字列, SeparatorColor.~, [, 線の太さ] [, SeparatorColor.~])]
  区切り線の間に文字を入れ、文字の色を指定して描画。
  第三引数で区切り線の太さ、第四引数で区切り線の色を指定することもできますが省略可能です。
   記述例
    [Separator("金剛", SeparatorColor.Red)]
    [Separator("比叡", SeparatorColor.Red, 5f)]
    [Separator("榛名", SeparatorColor.Red, 5f)]
    [Separator("霧島", SeparatorColor.Red, 5f, SeparatorColor.Blue)]

個人的には [Space(~)] や [Header("~")] よりは見やすくなったと思っているのですが・・・いかがでしょうか?


■最後に
大規模な開発環境ならばこのような小手先技に頼らずに、マウスだけで操作が完結するような Asset Store に並べても遜色のないゴリゴリのエディタ拡張もしていくべきなのだとは思うのですが、少人数での開発ならばあまりエディタ拡張ばかりに時間を費やせません。

ですが見た目をスッキリさせて調整項目を分かりやすくするだけでも、開発効率は変わってくると思います(よね?)

というわけで今回の小ネタは以上となりますが、このような小ネタで少しでも開発のお役に立てましたら幸いです。

ではでは今回はこの辺で~ノシ

スポンサーサイト

tag : Unity Unity小ネタ プログラミング

コメントの投稿

非公開コメント

プロフィール

Empress

Author:Empress
同人サークル「Atelier Empress」を立ち上げてしまった愚か者です。少しずつでも作品を公開していければと思う次第でございます。

検索フォーム
リンク
カテゴリ
タグ一覧

同人 Unity 進捗 雑記 コミケ C89 小ネタ プログラミング Unity小ネタ 年末 新年 Android 

委託販売
スポンサード リンク
FLOWER KNIGHT GIRL オンラインゲーム 千年戦争アイギス オンラインゲーム
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。