Skip to content

Latest commit

 

History

History
562 lines (421 loc) · 29.3 KB

README_JA.md

File metadata and controls

562 lines (421 loc) · 29.3 KB

uPalette

license license license

ドキュメント (English, 日本語) | デモ

Unityプロジェクトにおける色や文字スタイルを一元的に管理するためのシステムです。

Demo

目次

詳細

コンセプトと特徴

アプリケーション開発では一般的に、一つの色を複数の箇所に適用します。
以下はボタンの背景色やアイコンの色、アウトラインに同じ青色を適用している例です。

Apply blue color

次に、この色を青色から緑色に変更することを考えます。
Unityでは色の値はPrefabやSceneにシリアライズされるので、これらすべての値を一つ一つ変更する必要があります。

Change the color to green

当然ながら、この作業量はプロジェクトの規模に応じて増加します。
uPaletteを使えば色を一元管理することでこのような変更を一括で適用することができます。

uPalette

またuPaletteでは、色だけではなく文字スタイルやグラデーションを管理することもできます。

Character Styles & Gradients

さらにテーマ機能を使えば、色や文字スタイルのセットをテーマとして保存できます。
アクティブなテーマを切り替えることでそのテーマに応じた色や文字スタイルが反映されます。

Theme Feature

セットアップ

要件

Unity2020.1 以上

インストール

インストールは以下の手順で行います。

  1. Window > Package Manager を選択
  2. 「+」ボタン > Add package from git URL を選択
  3. 以下のURLを入力してインストール

Install

バージョンを指定したい場合には以下のようにURLの末尾にバージョンを付与します。

バージョンの更新もインストールと同様の手順で実行できます。

No 'git' executable was found. Please install Git on your system and restart Unity のようなメッセージが出た場合、マシンにGitをセットアップする必要がある点にご注意ください。

基本的な使い方

Palette Storeを作成する

uPaletteを使うにはまずWindow > uPalette > Palette EditorからPalette Editorを開きます。
Palette Editorを開くと下図のようなウィンドウが表示されます。

Palette Editor

次に、中央のCreate Palette Storeボタンを押下することでPalette Storeアセットを作成します。
Palette StoreはuPaletteで扱うデータを保持するためのアセットです。
プロジェクト内の任意の場所に配置できますが、ランタイムで使うアセットなのでEditorフォルダやStreamingAssetsフォルダ配下には置かないよう注意してください。

Palette Storeアセットを作成するとPalette Editorは以下のような表示に切り替わります。

Palette Editor

エントリを作成する

uPaletteでは、色や文字スタイルの設定のことをエントリと呼びます。
Palette Editorの右上にある「+」ボタンを押下することで、エントリを追加することができます。

Add Entry

エントリ名をクリックすることでリネームすることができます。
また、エントリの削除は右クリックから行えます。

Rename & Remove Entry

要素をドラッグすると順番を並び替えることもできます。

エントリを適用する

作成した色や文字スタイルをコンポーネントに反映するには、対象のGameObjectを選択した状態で対象のエントリのApplyボタンを押下します。
すると適用可能なコンポーネントとプロパティの名前がリストアップされるので、適用したいものを選択します。

Apply Entry

これで、エントリとプロパティが同期されます。
同期されているエントリの値が変化するとプロパティが自動的に書き変わります。

Change Entry Value

この時、対象のGameObjectにはSynchronizerと呼ばれるコンポーネントがアタッチされています。
このコンポーネントのInspectorからエントリを切り替えることもできます。
またこのコンポーネントをデタッチすると、エントリとの同期が解除されます。

Synchroizer

なお、Prefabに対してエントリを適用した場合には、通常のPrefabワークフローと同様、Prefabにはシリアライズされていない状態となります。
シリアライズを行うには右クリックメニューなどからApplyしてください。

Serialization

同期中のGameObjectをハイライトする

エントリの右クリックメニューからHighlightを選択すると、同期中のGameObjectをハイライト(選択)できます。

Highlight

色以外のエントリを取り扱う

ここまで、uPaletteで色を管理する方法について説明しました。

uPaletteには色の他にも文字スタイルやグラデーションといったパレットの種類が存在します。
PaletteEditorの左上のドロップダウンメニューから、パレットの種類を切り替えることができます。

Various Palettes

各ドロップダウンメニューの説明は以下の通りです。

名前 説明
Color 色を管理するために使用します。
Gradient グラデーションを管理するために使用します。
Character Style uGUI Textの文字スタイルを管理するために使用します。
Character Style TMP Text Mesh Proの文字スタイルを管理するために使用します。

エントリをフォルダ分けする

エントリ名をスラッシュで区切ると、エントリをフォルダ分けすることができます。
フォルダ分けされたエントリはPalette Editor上で下図のように階層表示されます。

Folder Mode

フォルダ分けするかどうかの設定は、以下のメニューから変更することができます。

  • Project Settings > uPalette > Use Folder View in Palette Editor

フォルダ分けをしない場合には全ての要素がフラットに表示され、ドラッグ&ドロップで並び替えられます。
フォルダ分けをする場合には名前順に並び替えられます。

テーマ機能の使い方

テーマとは?

テーマ機能を使うと、エントリのセットを「テーマ」として保存できます。
テーマは複数保存でき、それを切り替えることでテーマに応じた色や文字スタイルを反映することができます。

Theme

テーマを作成する

テーマを作成するには、Window > uPalette > Theme EditorからTheme Editorを開きます。
デフォルトでは、Defaultという名前のテーマが存在しており、左上の「+」ボタンを押下することで新しいテーマを作成できます。
Entry Editorと同様の操作でリネーム、削除、並び替えなどができます。

Theme Editor

テーマを追加すると、Palette Editorにそのテーマのエントリを設定するためのカラムが追加されます。
これを編集することでそのテーマに応じた値を設定できます。

Palette Editor

なおテーマはパレットの種類ごとに設定できます。
パレットの種類はTheme Editor左上のドロップダウンから変更できます。

Change Palette Type

テーマを切り替える(エディタ)

Theme EditorからActivateボタンを押下することでテーマを切り替えることができます。
テーマを切り替えると、そのテーマのエントリの値が即座に反映されます。

Change Theme

テーマを切り替える(スクリプト)

ランタイムにおけるテーマの切り替えにはPaletteクラスのSetActiveTheme()を使用します。
以下は自動生成したテーマのEnumを使用して、ColorPaletteのテーマを切り替えるスクリプトの例です。

using System;
using UnityEngine;
using uPalette.Generated;
using uPalette.Runtime.Core;

public class Example : MonoBehaviour
{
    public void OnGUI()
    {
        foreach (ColorTheme colorTheme in Enum.GetValues(typeof(ColorTheme)))
            if (GUILayout.Button(colorTheme.ToString()))
            {
                var colorPalette = PaletteStore.Instance.ColorPalette;
                colorPalette.SetActiveTheme(colorTheme.ToThemeId());
            }
    }
}

これを適当なGameObjectにアタッチして再生すると、以下のようにテーマを切り替えることができます。

Change Theme

応用的な使い方

エントリの値の変更を通知するSynchronizeEvent

上述の通り、Synchronizerコンポーネントは指定したエントリの値が変更されたときに対象のプロパティにその値を反映します。
これに対し、以下のSynchronize Eventコンポーネントを使用すると、値の変更通知だけをイベントとして受け取ることができます。

  • Color Synchronize Event
  • Gradient Synchronize Event
  • Character Style Synchronize Event
  • Character Style TMP Synchronize Event

使用するには上記のコンポーネントをアタッチし、値が変わったときの処理をUnityEventに設定します。

Change Theme

エントリやテーマを表すEnumを自動生成する

スクリプトからuPaletteを操作する場合、テーマやエントリの情報にアクセスするためのスクリプトを自動生成しておくと便利です。
Project Settings > uPalette > Name Enums File GenerationWhen Window Loses Focusに設定すると、Palette EditorやTheme Editorからフォーカスが外れた際にこのファイルが自動生成されます。
Name Enums File Locationにフォルダを指定するとそのフォルダに生成されます。未指定の場合にはAssetsフォルダ直下に生成されます。

Project Settings

以下のようなEnumが生成されます。

using System;

namespace uPalette.Generated
{
    public enum ColorEntry
    {
        Red,
        Green,
        Blue,
    }
}

またこのEnumの拡張メソッドとして定義されているToEntryId()を使用すると、当該エントリのIDを取得することができます。

using uPalette.Generated;

public class Example
{
    private void Foo()
    {
        ColorEntry.Red.ToEntryId();
    }
}

他の種類のエントリやテーマについても同様にして使用できます。

なお、プロジェクト設定のContains Folder Name to Name Enumsにチェックを入れると、フォルダ名もEnumに含められます。
このチェックを外すと、フォルダ名を除外した名前がEnumに使用されます。

スクリプトからエントリの値を取得・監視する

スクリプトからエントリの値を取得したり監視するには、以下のように各PaletteのGetActiveValue()を使います。
IReadOnlyObservableProperty<T>が返されるので、現在の値を取得する場合にはこれのValueプロパティを使用します。
テーマが変更された時など、値の変更を監視したい場合にはSubscribe()を使用して値の変更を監視することもできます。

using System;
using UnityEngine;
using uPalette.Generated;
using uPalette.Runtime.Core;

public class Example : MonoBehaviour
{
    private void Start()
    {
        // Get the color palette.
        var colorPalette = PaletteStore.Instance.ColorPalette;

        // Get the color entry id from the auto-generated ColorEntry enum.
        var targetColorEntryId = ColorEntry.KeyColor1.ToEntryId();

        var colorProperty = colorPalette.GetActiveValue(targetColorEntryId);

        // If you want to get the current value, use the Value property.
        var targetValue = colorProperty.Value;

        // If you want to get the value when the theme is changed, subscribe the property.
        IObserver<Color> observer;
        var disposable = colorProperty.Subscribe(observer);
    }
}

パレットデータをPreloadedAssetsで管理しない

デフォルトでは uPalette のパレットデータは PreloadedAssets に登録され、ランタイムで自動的に読み込まれます。
これはパレットのデータがアプリ内に組み込まれることを意味します。

パレットデータをアセットバンドル化する場合など、PreloadedAssets に登録したくない場合には以下の設定を行います。

  • Project Settings > uPalette > Automatic Runtime Data Loading のチェックを外す

Automatic Runtime Data Loading

この設定を行うと、uPalette のパレットデータは PreloadedAssets から削除されます。
この場合 PaletteStore のロードを手動で行う必要があります。
ロードされた PaletteStorePaletteStore.Instance に自動的に登録されます。
uPalette を使用する GUI を読み込む前にロードする必要がある点に注意してください。

// You must load the PaletteStore manually before loading GUIs that use uPalette.
var _ = Resources.Load<PaletteStore>("PaletteStore");

なお、エディタでは常に AssetDatabase を通してロードされた PaletteStore が使用されます。

uPaletteのデータをスクリプトから編集する

以下のようにPaletteStoreから各パレットを取得することで、uPaletteのデータをスクリプトから編集することができます。
PaletteStoreはScriptableObjectなので、編集した後には必ずDirtyフラグを立ててUnityに編集したことを知らせる必要がある点にご注意ください。

// Get PaletteStore.
var paletteStore = PaletteStore.Instance;

// Get each palette.
var colorPalette = PaletteStore.Instance.ColorPalette;
var gradientPalette = PaletteStore.Instance.GradientPalette;
var characterStylePalette = PaletteStore.Instance.CharacterStylePalette;
var characterStyleTMPPalette = PaletteStore.Instance.CharacterStyleTMPPalette;

// Set the dirty flag after editing.
EditorUtility.SetDirty(paletteStore);

// Save assets if you need.
AssetDatabase.SaveAssets();

独自のコンポーネントに値を反映する

uPaletteには標準的なコンポーネントのプロパティに値を反映するためのSynchronizerがあらかじめ用意されています。

これとは別に、独自のコンポーネントに値を反映するためのSynchronizerを作成することもできます。
例として、グラデーションをプロパティとして持つ独自のコンポーネントを考えます。

using UnityEngine;

public class SampleGradient : MonoBehaviour
{
    [SerializeField] private Gradient _gradient;

    public Gradient Gradient
    {
        get => _gradient;
        set => _gradient = value;
    }
}

このプロパティに値を反映するためのSynchronizerは以下のように作成できます。

using UnityEngine;
using uPalette.Runtime.Core.Synchronizer.Gradient;

[AddComponentMenu("")]
[DisallowMultipleComponent]
[RequireComponent(typeof(SampleGradient))]
[GradientSynchronizer(typeof(SampleGradient), "Gradient")]
public sealed class GraphicColorSynchronizer : GradientSynchronizer<SampleGradient>
{
    protected override Gradient GetValue()
    {
        return _component.Gradient;
    }

    protected override void SetValue(Gradient value)
    {
        _component.Gradient = value;
    }
}

エントリが見つからなかった時の挙動を設定する

対象のエントリが見つからなかった場合、エラーログを出したい場合もあれば、それを無視したい場合もあるでしょう。
Project Settings > uPalette > Missing Entry Errorから、エントリが見つからなかった時の挙動を設定できます。

Missing Entry Error

選択肢は以下の通りです。

名前 説明
None 何もしない。
Warning 警告ログを出力する。
Error エラーログを出力する。
Exception 例外をスローする。

実装されているSynchronizer一覧

uPaletteに標準で実装されているSynchronizerは以下の通りです。

エントリの種類 対象クラス名 対象プロパティ名
Color UnityEngine.UI.Graphic color
Color UnityEngine.UI.Outline effectColor
Color UnityEngine.UI.Selectable colors.normalColor
Color UnityEngine.UI.Selectable colors.selectedColor
Color UnityEngine.UI.Selectable colors.pressedColor
Color UnityEngine.UI.Selectable colors.disabledColor
Color UnityEngine.UI.Selectable colors.highlightedColor
Color UnityEngine.UI.InputField caretColor
Color UnityEngine.UI.InputField selectionColor
Color TMPro.TMP_InputField caretColor
Color TMPro.TMP_InputField selectionColor
CharacterStyle UnityEngine.UI.Text font / fontStyle / fontSize / lineSpacing
CharacterStyleTMP TMPro.TextMeshProUGUI font / fontStyle / fontSize / enableAutoSizing / characterSpacing / wordSpacing / lineSpacing / paragraphSpacing

技術的詳細

エントリを反映するタイミングについて

Unityでは、各コンポーネントに設定されている色やテキストスタイルなどの情報はそのまま値としてシリアライズされます。
したがって、これら変更したときにはこのシリアライズされた値を書き換えるべきです。

しかしこれでは、エントリを変更した際に多くのSceneやPrefabに変更が加わってしまいます。
そこでuPaletteでは以下のルールに従って色を反映しています。

  • uPaletteのエントリは値ではなくIDとしてシリアライズ
  • Edit ModeではOnEnable時にこのエントリを反映・変更を監視する
  • Play ModeではStart()のタイミングでエントリを反映する

また、Edit ModeでSceneを開いたときに変更が加わらないよう、シリアライズされたIDのエントリを反映するときにはDirtyフラグを立てない実装にしています。

バージョン1からのアップデート方法

uPaletteをバージョン1からバージョン2にバージョンアップする上で、データ構造やデータの置き場所を大きく変更しました。

バージョン1を使用していた方は、Palette Storeを作成する前にProject Settingsから以下のボタンを押下することでバージョン2にデータを移行できます。

How to update

ボタンを押下するとPalette Storeアセットの保存パネルが表示されるので、任意の場所に保存してください。
ただしこのアセットはランタイムで使うアセットなので、EditorフォルダやStreamingAssetsフォルダ配下には置かないよう注意してください。

デモ

デモシーンは以下の手順で再生できます。

  1. リポジトリをクローンする
  2. 以下のシーンを開いて再生

ライセンス

本ソフトウェアはMITライセンスで公開しています。ライセンスの範囲内で自由に使っていただけますが、使用の際は以下の著作権表示とライセンス表示が必須となります。

また、本ドキュメントの目次は以下のソフトウェアを使用して作成されています。

toc-generatorのライセンスの詳細は Third Party Notices.md を参照してください。