You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity:为实例化预制体子对象绑定OnClick并引用克隆预制体元素

问题描述

我有一个登录面板预制体,通过以下代码克隆:

public class LoginOpener : MonoBehaviour
{
    public GameObject popupPrefab;

    protected Canvas m_canvas;
    protected GameObject m_popup;

    protected void Start()
    {
        m_canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
    }

    public virtual void OpenPopup()
    {
        m_popup = Instantiate(popupPrefab, m_canvas.transform, false);
        m_popup.SetActive(true);
        m_popup.transform.localScale = Vector3.zero;
        m_popup.GetComponent<Popup>().Open();
    }
}

登录面板预制体结构:

  • Login Panel
    • Email Text(挂载TMP_InputField组件)
    • Password Text(挂载TMP_InputField组件)
    • Login Button(挂载Button组件)
    • Another button

FirebaseManager脚本:

public class FirebaseManager : MonoBehaviour
{
    [Header("Login References")]
    [SerializeField]
    private TMP_InputField loginEmail;
    [SerializeField]
    private TMP_InputField loginPassword;
    [SerializeField]
    public static FirebaseManager instance;

    public void LoginButton()
    {
        StartCoroutine(LoginLogic(loginEmail.text, loginPassword.text));
    }
}

需求:将FirebaseManager中的LoginButton()方法绑定到克隆预制体的Login Button上,同时将克隆预制体的邮箱、密码输入框赋值给管理器的loginEmail和loginPassword引用。


解决方案

步骤1:完善FirebaseManager单例机制

确保场景中始终存在唯一的FirebaseManager实例,避免找不到引用的问题:

public class FirebaseManager : MonoBehaviour
{
    [Header("Login References")]
    [SerializeField]
    private TMP_InputField loginEmail;
    [SerializeField]
    private TMP_InputField loginPassword;
    public static FirebaseManager instance;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void LoginButton()
    {
        StartCoroutine(LoginLogic(loginEmail.text, loginPassword.text));
    }

    // 补充登录逻辑协程(根据你的Firebase实现完善)
    private IEnumerator LoginLogic(string email, string password)
    {
        // 此处编写Firebase登录逻辑
        yield return null;
    }
}

步骤2:修改LoginOpener绑定引用与事件

在克隆预制体后,直接通过子对象路径获取组件,完成引用赋值和按钮事件绑定:

public class LoginOpener : MonoBehaviour
{
    public GameObject popupPrefab;

    protected Canvas m_canvas;
    protected GameObject m_popup;

    protected void Start()
    {
        m_canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
        
        if (FirebaseManager.instance == null)
        {
            Debug.LogError("场景中未找到FirebaseManager实例,请添加挂载该脚本的对象!");
        }
    }

    public virtual void OpenPopup()
    {
        if (popupPrefab == null || FirebaseManager.instance == null)
        {
            Debug.LogError("预制体或FirebaseManager实例未设置!");
            return;
        }

        m_popup = Instantiate(popupPrefab, m_canvas.transform, false);
        m_popup.SetActive(true);
        m_popup.transform.localScale = Vector3.zero;

        // 获取预制体子组件(注意名称要和预制体中子对象完全一致)
        TMP_InputField emailInput = m_popup.transform.Find("Email Text").GetComponent<TMP_InputField>();
        TMP_InputField passwordInput = m_popup.transform.Find("Password Text").GetComponent<TMP_InputField>();
        Button loginBtn = m_popup.transform.Find("Login Button").GetComponent<Button>();

        // 空值检查,避免空引用报错
        if (emailInput == null) Debug.LogError("未找到Email输入框,请检查预制体中子对象名称!");
        if (passwordInput == null) Debug.LogError("未找到Password输入框,请检查预制体中子对象名称!");
        if (loginBtn == null) Debug.LogError("未找到Login Button,请检查预制体中子对象名称!");

        // 赋值给FirebaseManager的引用
        FirebaseManager.instance.loginEmail = emailInput;
        FirebaseManager.instance.loginPassword = passwordInput;

        // 绑定按钮点击事件
        loginBtn.onClick.RemoveAllListeners();
        loginBtn.onClick.AddListener(FirebaseManager.instance.LoginButton);

        m_popup.GetComponent<Popup>().Open();
    }
}

关键注意事项

  1. 子对象名称必须完全匹配:transform.Find()的参数要和预制体中子对象的名称(含大小写、空格)完全一致。
  2. 组件挂载验证:确保预制体中的输入框确实挂载了TMP_InputField,按钮挂载了Button组件。
  3. 场景初始化:必须在场景中放置一个挂载了FirebaseManager脚本的对象,否则会触发实例不存在的报错。

内容的提问来源于stack exchange,提问作者user17890799

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:45:41