MRが楽しい

MRやVRについて学習したことを書き残す

Blenderの「名前を付けて保存」と「コピーを保存」を使い分ける

本日はBlenderの小ネタ枠です。
Blenderの「名前を付けて保存」と「コピーを保存」の使い分けについてです。

前提条件

以下の編集中のBlenderプロジェクトを利用します。
編集中のファイルが「~\Cube.blend」である点に注目します。

名前を付けて保存

メニューから[ファイル -> 名前を付けて保存]を選択して「Cube_Copy.blend」という別名でファイルを保存します。

「名前を付けて保存」は一般的なファイル保存の形式です。
別名でファイルを保存すると編集中のファイルは保存した「Cube_Copy.blend」ファイルに切り替わります。

コピーを保存

メニューから[ファイル -> コピーを保存]を選択して同じく「Cube_Copy.blend」という別名でファイルを保存します。

「コピーを保存」では編集中のファイルは切り替わりません。
別名でファイルは保存されますが、編集中のファイルはそのまま「Cube.blend」ファイルのままです。

バックアップファイルの作成など、編集途中のファイルを別名で保存しておきたい場合に便利です。

ReactiveCollectionでコレクションの変更をまとめて通知する

本日は UniRx の小ネタ枠です。
ReactiveCollection でコレクションの変更をまとめて通知する方法について記事にします。

前回記事

以下の前回記事の続きです。
bluebirdofoz.hatenablog.com

Merge

Merge オペレータを利用することで複数のシーケンスをまとめたObservableを作成できます。
今回はObservable.Mergeを使って様々な変更通知を1つのシーケンスにまとめたObservableを作ります。

サンプルスクリプト

以下のサンプルスクリプトを作成してみました。
コレクションの追加、更新、削除、移動、クリアの通知をまとめたObservableを購読してデバッグログを出力します。
・ReactivePropertyTest5.cs

using System;
using System.Linq;
using Cysharp.Threading.Tasks;
using UniRx;
using UnityEngine;

public class ReactivePropertyTest5 : MonoBehaviour
{
    // コレクションの変更のタイプ
    private enum ChangeType
    {
        Add,
        Remove,
        Replace,
        Move,
        Reset,
    }
    
    // ReactiveCollectionを使って、コレクションの変更を監視する
    private readonly ReactiveCollection<string> dataProp = new();

    // ReactiveCollectionの様々な変更を一括監視するObservable
    private IObservable<(ChangeType, string[])> DataPropObservable => Observable.Merge(
        dataProp.ObserveAdd().Select(_ => (ChangeType.Add, dataProp.ToArray())),
        dataProp.ObserveRemove().Select(_ => (ChangeType.Remove, dataProp.ToArray())),
        dataProp.ObserveReplace().Select(_ => (ChangeType.Replace, dataProp.ToArray())),
        dataProp.ObserveMove().Select(_ => (ChangeType.Move, dataProp.ToArray())),
        dataProp.ObserveReset().Select(_ => (ChangeType.Reset, dataProp.ToArray()))
    );

    void Start()
    {
        // コレクションの変更時に、変更のタイプと変更後のリストの内容を通知する
        DataPropObservable
            .Subscribe(data =>
            {
                Debug.Log($"ChangeType : {data.Item1}, Data : {string.Join(", ", data.Item2)}");
            })
            .AddTo(this);

        // 追加
        dataProp.Add("First");
        dataProp.Add("Second");
        dataProp.Add("Third");
        
        // 更新
        dataProp[2] = "End";
        
        // 削除
        dataProp.Remove("Second");
        
        // 移動
        dataProp.Move(0, 1);

        // クリア
        dataProp.Clear();
    }
}

以下の通り、コレクションの変更を1つの Observable を使って監視して出力することができました。

UnityでGraphic参照を使って様々なコンポーネントのカラーを一括管理する

本日はUnityの小ネタ枠です。
UnityでGraphic参照を使って様々なコンポーネントのカラーを一括管理する方法についてです。

Graphic基本クラス

Graphicは全てのビジュアルUIコンポーネントのための基本クラスです。
Graphicクラスを参照することで様々なビジュアルコンポーネントに対して共通の処理を行えます。
docs.unity3d.com

サンプルスクリプト

参照を設定したビジュアルコンポーネントの基本カラーを一括変更する以下のサンプルスクリプトを作成しました。
・GraphicTest.cs

using UnityEngine;
using UnityEngine.UI;

public class GraphicTest : MonoBehaviour
{
    [SerializeField] private Graphic[] _targetGraphicComponents;

    [SerializeField] private Color _enableColor = Color.white;
    [SerializeField] private Color _disableColor = Color.gray;

    [SerializeField] private bool _enable = true;
    
    // enableを変更するとInspector上で色が変わる
    private void OnValidate()
    {
        if (_targetGraphicComponents == null || _targetGraphicComponents.Length == 0)
        {
            return;
        }
        SetEnable(_enable);
    }
    
    private void SetEnable(bool enable)
    {
        foreach (var graphic in _targetGraphicComponents)
        {
            // 基本カラーを変更する
            graphic.color = enable ? _enableColor : _disableColor;
        }
    }
}

動作確認

以下のImageとTMP_Textコンポーネントで構成したUIオブジェクトを用意しました。

サンプルスクリプトを配置してImageとTMP_Textコンポーネントへの参照を設定します。
ImageとTMP_TextコンポーネントはともにGraphicを基本クラスに持つため、どちらもそのまま参照を設定することができます。

Enable変数を切り替えると、以下の通りImageとTMP_Textコンポーネントの基本カラーを一括で変更できました。

Blenderの操作履歴を参照して特定の操作まで編集を戻す

本日はBlenderの小ネタ枠です。
Blenderの操作履歴を参照して特定の操作まで編集を戻す方法についてです。

操作履歴(Undo History)

Blenderの操作履歴にはそれまで行った操作の履歴が一覧で表示されます。
履歴を選択することで特定の操作時点まで編集状態を戻すこともできます。

編集履歴はメニューから[編集 -> 操作履歴]で確認できます。

履歴の中の特定の操作を選択すると、その操作を実行した時点まで編集の状態が戻ります。
現在の操作ポイントには一覧の項目に●が表示されます。

Unityでアスペクト比が変わっても背景画像が見切れないようにする

本日はUnityの小ネタ枠です。
Unityでアスペクト比が変わっても背景画像が見切れないようにする方法を記事にします。

Screen Match Mode

CanvasScalerコンポーネントCanvas内のUI要素の全体的なスケールとピクセル密度を制御するために使用されます。
コンポーネントで設定できるScreen Match Modeでアスペクト比が基準解像度にフィットしないUI要素のスケーリング方法を変更できます。
docs.unity3d.com

デフォルトではMatch Width or Heightモードに設定されており、本モードは水平または垂直を基準にUIのサイズを維持します。
アスペクト比が変わっても背景画像が見切れないようにしたい場合は本設定でExpandモードを利用します。

サンプルシーン

Match Width or Heightによる動作の違いを確認するため、以下の1920x1080の解像度で背景画像を配置したサンプルシーンを作成しました。

Expandモードの場合

Expandモードの場合、解像度の変化に合わせて水平や垂直に展開してCanvasのサイズが変化するため、ピクセルが基準値よりも小さくなりません。

このため、以下のようにアスペクト比が変わっても背景画像が見切れないようになります。


Shrinkモードの場合

Shrinkモードの場合、解像度の変化に合わせて水平や垂直にトリミングしてCanvasのサイズが変化するため、ピクセルが基準値よりも大きくなりません。

このため、以下のようにアスペクト比が変わっても背景画像が画面全体を覆うようになります。


Match Width or Heightの場合

Match Width or Heightモードの場合、解像度の変化に合わせて水平または垂直を基準にしてCanvasのサイズが変化します。

Match:0の場合

Match:0の場合、水平方向に展開してサイズが変化するため以下のように見た目が変化します。


Match:1の場合

Match:1の場合、垂直方向に展開してサイズが変化するため以下のように見た目が変化します。

Unityで解像度が変わってもUIのレイアウトが変わらないようにする

本日はUnityの小ネタ枠です。
Unityで解像度が変わってもUIのレイアウトが変わらないようにする方法を記事にします。

UI Scale Mode

CanvasScalerコンポーネントCanvas内のUI要素の全体的なスケールとピクセル密度を制御するために使用されます。
コンポーネントで設定できるUI Scale ModeでUI要素のスケーリング方法を変更できます。
docs.unity3d.com

デフォルトではConstant Pixel Sizeモードに設定されており、本モードは設定したピクセル単位でUIのサイズを維持します。
解像度に合わせてUIのレイアウトを維持するにはScale With Screen Sizeモードを利用します。

サンプルシーン

UI Scale Modeによる動作の違いを確認するため、以下の1920x1080の解像度でUIを配置したサンプルシーンを作成しました。
背景のImageオブジェクトはStretchで、ボタンのButtonオブジェクトはピクセル単位で大きさを指定しています。


Constant Pixel Sizeモードの場合

Constant Pixel Sizeモードの場合、解像度の変化に合わせてImageオブジェクトはサイズが調整されますが、Buttonオブジェクトはピクセル単位で大きさを維持します。

このため、以下のように解像度によってButtonオブジェクトはレイアウト上の大きさが変化してしまいます。

1920x1080


1366x768


2560x1440


Scale With Screen Sizeモードの場合

Scale With Screen Sizeモードの場合、解像度の変化に合わせてButtonオブジェクトはも大きさが調整されます。

このため、以下のように解像度を変更してもButtonオブジェクトはレイアウト上の大きさが変化しません。

1920x1080


1366x768


2560x1440

UnityでスクリプトからHierarchy内のオブジェクトの順序を並べ替える

本日はUnityの小ネタ枠です。
UnityでスクリプトからHierarchy内のオブジェクトの順序を並べ替える方法を記事にします。

SiblingIndex

Hierarchy内のオブジェクトの順序はTransformのSiblingIndex関連の関数で参照・変更できます。
SiblingIndexで参照できるインデックスは同一階層のオブジェクトのインデックスである点に注意してください。

GetSiblingIndex

現在のオブジェクトのインデックスを取得します。

    public void GetSiblingIndexTest()
    {
        var siblingIndex = this.transform.GetSiblingIndex();
        Debug.Log($"SiblingIndex: {siblingIndex}");
    }


docs.unity3d.com

SetSiblingIndex

現在のオブジェクトのインデックスを変更します。
インデックスの上限を超える値を設定した場合は一番下(最大値)のインデックスに移動します。

    public void SetSiblingIndexTest()
    {
        var siblingIndex = 10;
        this.transform.SetSiblingIndex(siblingIndex);
    }


docs.unity3d.com

SetAsFirstSibling

現在のオブジェクトの一番上(最小値)のインデックスに移動します。

    public void SetAsFirstSiblingTest()
    {
        this.transform.SetAsFirstSibling();
    }


docs.unity3d.com

SetAsLastSibling

現在のオブジェクトの一番下(最大値)のインデックスに移動します。

    public void SetAsLastSiblingTest()
    {
        this.transform.SetAsLastSibling();
    }


docs.unity3d.com