RのWeb制作

Webサービス制作のための技術情報を。データ分析(Python、機械学習コンペ他)や自作野球ゲームMeisyoのこと中心。

モバイル制作 Unity(C#)

[Unity]チュートリアル用に使える!指定のオブジェクトのみ注目させるコードの紹介

投稿日:

個人的にGoogle Playだったりでゲームを遊んでるれいです。

個人開発のゲームで特に目立つ、チュートリアルで指定のオブジェクト(例:育成ボタン)を注目させるときに背景をクリッピングさせる

アレ、黒背景の画像+透明の丸の切り抜きでやるのはいいんですが・・・なかなか見た目が残念になりやすいです
四角(矩形)にするとそれはそれで見づらい

というわけで、特別な工夫なしに指定のオブジェクトだけ注目させるコードを作りました。

出来栄え


指定のオブジェクトだけを注目させる、かつクリックできるようにしています

2ステップ実現方法

(1)オブジェクトの階層を入れ替えて、背景画像の前面に出す
(2)元の階層に戻す

めちゃくちゃ簡単でした。
それでは実際にコードの使い方を見ていきましょう。

設定

階層構造は以下の通りにします。

背景が画像1と画像2より前面に出ています。

見た目はこんな感じ。

GameObjectには以下で紹介する2つのスクリプトをアタッチし、設定しておきます。

DisplayBackground1Controller.cs

using UnityEngine;

/// <summary>
/// DisplayBackground1シーンの背景Panel制御
/// HierarchyToggleController を使用して、矢印キーで Image1/Image2 の親を切り替える
/// </summary>
public class DisplayBackground1Controller : MonoBehaviour
{
    [SerializeField] private HierarchyToggleController hierarchyToggleController;

    void Start()
    {
        if (hierarchyToggleController == null)
        {
            Debug.LogError("HierarchyToggleController が見つかりません。");
        }
    }

    void Update()
    {
        if (hierarchyToggleController == null)
            return;

        // 矢印キー入力で親を切り替え
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            hierarchyToggleController.SetActive("Image1");
        }
        else if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            hierarchyToggleController.SetActive("Image2");
        }
        else if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            hierarchyToggleController.DisableAll();
        }
    }
}

HierarchyToggleController.cs

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// 任意のオブジェクトを指定した親に移動して、Z順序を変更する汎用コンポーネント
/// Inspector でキーごとにオブジェクトと移動先の親を設定し、キーベースで ON/OFF を切り替える
/// </summary>
public class HierarchyToggleController : MonoBehaviour
{
    [System.Serializable]
    public class HierarchyToggleEntry
    {
        public string key;                  // キー(例:"Image1", "Image2")
        public Transform targetObject;      // 親を変更するオブジェクト
        public Transform newParent;         // 移動先の親(新しい親)

        // 実行時に使用(元の親と兄弟順序を保存)
        [System.NonSerialized] public Transform originalParent;
        [System.NonSerialized] public int originalSiblingIndex;
    }

    [SerializeField] private List<HierarchyToggleEntry> toggleEntries = new List<HierarchyToggleEntry>();

    // キーでエントリを高速参照するための辞書
    private Dictionary<string, HierarchyToggleEntry> entryDict = new Dictionary<string, HierarchyToggleEntry>();

    // 現在アクティブなキー(null の場合はアクティブなものはない)
    private string currentActiveKey = null;

    void Start()
    {
        // 各エントリの元の親と兄弟順序を保存し、辞書を初期化
        foreach (var entry in toggleEntries)
        {
            if (entry.targetObject != null)
            {
                entry.originalParent = entry.targetObject.parent;
                entry.originalSiblingIndex = entry.targetObject.GetSiblingIndex();

                // 辞書に追加(キーが重複していないと仮定)
                if (!entryDict.ContainsKey(entry.key))
                {
                    entryDict.Add(entry.key, entry);
                }
            }
        }
    }

    /// <summary>
    /// 指定したキーのオブジェクトを親変更状態にする
    /// 既に別のキーがアクティブな場合、それを先に Disable する
    /// </summary>
    public void SetActive(string key)
    {
        if (!entryDict.ContainsKey(key))
        {
            Debug.LogWarning($"HierarchyToggleController: キー '{key}' が見つかりません。");
            return;
        }

        // 既存のアクティブなエントリがあれば Disable
        if (currentActiveKey != null && currentActiveKey != key)
        {
            DisableInternal(currentActiveKey);
        }

        // 指定キーのエントリをアクティブにする
        var entry = entryDict[key];
        if (entry.targetObject != null && entry.newParent != null)
        {
            entry.targetObject.SetParent(entry.newParent, worldPositionStays: true);
            currentActiveKey = key;
        }
    }

    /// <summary>
    /// 指定したキーのオブジェクトを元の親に戻す
    /// </summary>
    public void Disable(string key)
    {
        if (!entryDict.ContainsKey(key))
        {
            Debug.LogWarning($"HierarchyToggleController: キー '{key}' が見つかりません。");
            return;
        }

        if (currentActiveKey == key)
        {
            DisableInternal(key);
            currentActiveKey = null;
        }
    }

    /// <summary>
    /// すべてのアクティブなエントリを Disable する
    /// </summary>
    public void DisableAll()
    {
        if (currentActiveKey != null)
        {
            DisableInternal(currentActiveKey);
            currentActiveKey = null;
        }
    }

    /// <summary>
    /// 内部用:指定キーのエントリを元の親に戻す処理
    /// </summary>
    private void DisableInternal(string key)
    {
        var entry = entryDict[key];
        if (entry.targetObject != null && entry.originalParent != null)
        {
            entry.targetObject.SetParent(entry.originalParent, worldPositionStays: true);
            entry.targetObject.SetSiblingIndex(entry.originalSiblingIndex);
        }
    }

    /// <summary>
    /// 現在アクティブなキーを取得
    /// </summary>
    public string GetCurrentActiveKey()
    {
        return currentActiveKey;
    }

    /// <summary>
    /// 指定したキーがアクティブかどうかを確認
    /// </summary>
    public bool IsActive(string key)
    {
        return currentActiveKey == key;
    }
}

何をしているのか

配置を操作したいオブジェクトを辞書型のような形式で管理します。
指定したキーのオブジェクトについて、前述の通り(1)前面に出す⇔(2)元に戻すを制御しているだけです。

うれしいポイント

・クリッピングとは違い、画面の大きさの違いによる位置ずれを起こしづらいです。
※設定によってはうまく働かない可能性があるのでテストしてください。
・オブジェクトはいくつでも指定可能。多数のオブジェクトがあっても登録すればすべて同じように使えます。
・別のシーンでも1つのコード(HierarchyToggleController.cs)で使える応用性があります。

さいごに

ワイもさっそくゲーム内に導入しよう~また何かあれば書きます( ^^)/~~

-モバイル制作, Unity(C#)

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

Unityで”Class” is missing the class attribute ‘ExtensionOfNativeClass’が発生する原因がわからない ⇒ Easy Save3でした

はじめに 通常、”Class” is missing the class attribute ‘ExtensionOfNativeClass’というエラ …

監督たちの甲子園 世紀の逆転劇 公式サイト

ゲーム説明 伝統、戦略、想いが交錯する甲子園へ ――あなたの采配で一球のドラマを、勝利を掴み取れ! 一球のドラマを楽しもう! 次の一球にドキドキ、ワクワクする圧倒的な臨場感の3Dキャラ×物理シミュレー …

【Flutter】Googleアカウント認証SHA-1キーのためにkeytoolを使えるようにする

FlutterのGoogleアカウントでの認証(Authentication)のためにSHA-1キーが必要です。ただし、簡単に取得ができません。そのため、下記を参考にして進めます。 Google Au …

UnityでiOS版をリリースする際に、Firebaseを使っていると起こるビルドエラー「Undefined symbols for architecture arm64」への対応

起こること 「Undefined symbols for architecture arm64」がでて、XCodeのビルドができない。 原因と対策 Firebase等がインストールできていない。 Fi …

ゲームアプリ運営の分析ノウハウ vol.3 この状態のアプリはやべえ編

はじめに 皆さんお久しぶりです。れいです。 近しい友人(アプリ運営を長年経験)が転職することになり、色々話してみましたがやべえ状態ってあるんやなと思ったので共有します。 これは…他山の石としてください …