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

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

関連記事

【生成AIテスト記事】Unity運営に関する各種プラットフォーム(Google, Apple, Unity)の情報公開可否

Deep Researchすげえ、ってことで ”「禁止」とされている所はやらず、「許可」とされているところは自分で調べて実行する”でいいんじゃないかな。 調べる手間の削減っていいよね、という生成AIの …

C# 最適化による読み込み速度向上実験

ゲーム 監督たちの甲子園(仮)で、オーダー設定を作っています。 ただ、動作がクソ重いので最適化でどれくらい重いのか、最適化するとどうなるのか比較したいと思います。 動作イメージは下記の通りです。 動画 …

UnityでiOS版をリリースする際に、FirebaseとXCode16を組み合わせると起こるビルドエラー「unsupported option ‘-G’ for target ‘arm64-apple-iosXX.X’」への対応

はじめに こちらのポストがワイにも役に立ったので、「実際どうするの?」ということも含めて書いておこうと思う。 Unity + firebase x Xcode16で、こんなエラーunsupported …

【Flutter】ToDoアプリの作成

StatefullWidgetの状態管理、データの受け渡し、デバイスへのToDoリスト保存の解説がなかったので例となるアプリを作成しました。 こちらのアプリを応用すれば、大体のアプリが作れるのではない …

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

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