Unity

【Unity宴】イベントトリガーに設定しているところで文字送り、コンフィグ制御

Unity

相当苦労して実装したので、メモがてら置いておきます。
宴Q&Aに自分のやり取りとコード修正のやり取りがあるので、そこから抜き出してコピペすれば使えるようにもなります。

イベントトリガーに文字送りを対応させる方法


宴Ver4.1.8以降にサンプルソースコードが追加されるようです。
以下が更新された時に入っているコード。

Config(コンフィグ)メニューへの独自項目の追加について


実装した目的は、E-moteでイベントトリガーに設定したタイムラインを再生させる挙動において、この部分で文字送りが不可能になっていました。
それを解消するために文字送り可能にすることと、人によってはウザいと思われそうだったのでコンフィグでイベントトリガーのタイムライン挙動を無効化したかった、という目的です。

実際、マウスオーバーでひたすら反応しますので。
スマホの場合は知りませんが。

ド素人がChatGPTを使って構築したものなのでコードは汚いですが、一応は使えます。
Live2Dでイベントトリガーに何か仕込みたい人とかがいたら使えるでしょう。文字送りのみならAdvEngineを参照、取得し、UguiManagerを呼べば動きます。

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using Utage;

public class AdvInputCaller : MonoBehaviour, IPointerClickHandler
{
    AdvEngine engine;
    AdvUguiManager uguiManager;

    private bool? currentRaycasterState = null;

    void Start()
    {
        engine = GameObject.FindFirstObjectByType<AdvEngine>();
        if (engine != null)
        {
            uguiManager = engine.GetComponentInChildren<AdvUguiManager>();
        }

        if (uguiManager == null)
        {
            Debug.LogWarning("AdvUguiManager が見つかりませんでした。");
        }
        ApplyRaycasterFromAdvEngineParam();
    }

    void OnEnable()
    {
        ApplyRaycasterFromAdvEngineParam();
    }

    void ApplyRaycasterFromAdvEngineParam()
    {
        if (engine == null) return;
        bool isEnabled = engine.Param.GetParameterInt("Raycaster") == 1;
        ApplyRaycasterState(isEnabled);
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left) return;
        CallOnInput();
    }

    public void CallOnInput()
    {
        if (uguiManager != null)
        {
            uguiManager.OnInput();
        }
    }

    public void ToggleRaycaster(bool isEnabled)
    {
        currentRaycasterState = isEnabled;
        ApplyRaycasterState(isEnabled);
    }

    private void ApplyRaycasterState(bool isEnabled)
    {
        var canvases = GetComponentsInChildren<Canvas>(true);
        foreach (var canvas in canvases)
        {
            var raycaster = canvas.GetComponent<GraphicRaycaster>();
            if (raycaster != null)
            {
                raycaster.enabled = isEnabled;
                Debug.Log($"[{gameObject.name}] GraphicRaycaster on '{canvas.name}' is now {(isEnabled ? "ENABLED" : "DISABLED")}");
            }
        }
    }
}


制御側。基本的にAdvInputCaller でトグルすれば使えます。
プレハブリストが書いてありますが、既にClone化されてキャラは登場しますのでリストは入れなくてok。むしろ、リストに設定すると起動時に既に画面に出てる。

using UnityEngine;
using UnityEngine.UI;
using Utage;
using UtageExtensions;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using System.Collections;

public class RaycasterConfigController : MonoBehaviour
{
    [SerializeField] private List<GameObject> prefabList;
    private List<GameObject> instantiatedObjects = new List<GameObject>();

    public AdvEngine Engine => this.GetAdvEngineCacheFindIfMissing(ref engine);
    [SerializeField] private AdvEngine engine;

    public Toggle toggle;

    public static RaycasterConfigController Instance { get; private set; }

    void Awake()
    {
        // シングルトンパターンの設定
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            Destroy(gameObject); // 重複してたら消す
        }
    }

    void Start()
    {
        StartCoroutine(InitAfterUtageReady());
    }

IEnumerator InitAfterUtageReady()
{
    yield return new WaitUntil(() => Engine.Param.IsInit);

    Debug.Log("Param is ready");

    // パラメーターを先に取得
    bool isEnabled = GetRaycasterValue() == 1;

    // プレハブクローン化
    foreach (var prefab in prefabList)
    {
        var instance = Instantiate(prefab, transform);
        instantiatedObjects.Add(instance);

        var raycasters = instance.GetComponentsInChildren<GraphicRaycaster>(true);
        Debug.Log(raycasters.Length + " Raycasters found in " + instance.name);

        // 生成直後にGraphicRaycasterの状態を反映
        foreach (var raycaster in raycasters)
        {
            raycaster.enabled = isEnabled;
            Debug.Log($"{raycaster.name} Raycaster set to {(isEnabled ? "ENABLED" : "DISABLED")}");
        }
    }

    // Toggle設定
    if (toggle != null)
    {
        toggle.isOn = isEnabled;
        toggle.onValueChanged.AddListener(OnToggleChanged);

        // 再反映(既に反映済みだが念のため)
        ToggleRaycasters(isEnabled);
    }
}

    // UTAGE Paramから現在の設定を取得
    public int GetRaycasterValue()
    {
        if (!Engine.Param.IsInit)
        {
            Debug.LogWarning("まだパラメーターが初期化されていません");
            return 1;
        }
        return Engine.Param.GetParameterInt("Raycaster");
    }

    // UTAGE Paramに設定を書き込み
    public void SetRaycasterValue(int value)
    {
        if (!Engine.Param.IsInit)
        {
            Debug.LogWarning("まだパラメーターが初期化されていません");
            return;
        }

        Engine.Param.SetParameterInt("Raycaster", value);
        Debug.Log("Raycaster Set To: " + value);
        Debug.Log("Immediately Read: " + Engine.Param.GetParameterInt("Raycaster"));
    }

    // ON/OFF切り替え処理
    // GraphicRaycasterのON/OFFを切り替えるトグル関数
    public void ToggleRaycasters(bool isEnabled)
    {
        // パラメーターも同時に更新(ここが追加ポイント)
        SetRaycasterValue(isEnabled ? 1 : 0);

        foreach (var inputCaller in engine.GraphicManager.GetComponentsInChildren<AdvInputCaller>(true))
        {
            inputCaller.ToggleRaycaster(isEnabled);
        }

        Debug.Log("Raycaster Param value = " + GetRaycasterValue());
    }

    // Toggle UI連動
    // Toggleから呼び出す例
    public void OnToggleChanged(bool value)
    {
        SetRaycasterValue(value ? 1 : 0);  // ← パラメータに書き込む
        ToggleRaycasters(value);
        Debug.Log("Toggled! Set Param to: " + (value ? 1 : 0));
        bool isEnabled = RaycasterConfigController.Instance.GetRaycasterValue() == 1;
        ToggleRaycasters(isEnabled);

    }

    // リセットなどで初期値に戻す場合
    public void OnClickConfigReset()
    {
        SetRaycasterValue(1);
        toggle.isOn = true;
    }
}

宴のエクセルシート、Paramのところに

Lavel=Raycaster

Type=Int

Value=1

FileType=System
(通常のセーブデータだと初動制御でうまくいかず、キャラが表示された2回目以降で正常になるため。
コードの影響でコンフィグでオフにしてもキャラが出る時にキャンバスでRaycasterがオンになってしまいます。Systemデータで制御すれば一致して即時反映するのでこれで運用します。)


と、やれば機能します。

後は親オブジェクトにアタッチすれば準備完了。コンフィグ制御するならコンフィグのトグルにアタッチします。
子オブジェクトに設定しているイベントトリガーはこんな感じ。クリックすれば文字送り可能に。

コメント