UI优化时保留原预制体 新预制体和新脚本的绑定引用关系的快速引用

适用场景

优化功能时 保留老预制体且老预制体的脚本公共变量引用绑定很多 ,

新脚本需要重新绑定时

原因

  1. 不能在UI初始化写查找代码 查找的代码其实都是一样的 且毫无意义 从性能上说 代码里查找差一点点,所以预制体挂在了大量脚本
  2. 如果结合MVC思想,这种绑定只是纯View的代码
  3. 引用关系大量 且需要更换脚本

实现

首先,获取Mark脚本中指定的组件类型type,并调用FnmGetNameField方法获取一个字典dicNameField,该字典存储了需要绑定的成员变量名及其对应的子物体名(这里假设子物体名与成员变量名存在某种关联)。接着,为目标组件创建SerializedObject,用于在编辑器环境下操作组件的序列化数据。然后遍历字典,对于每个成员变量:

通过FindProperty方法找到对应的SerializedProperty。虽然有部分条件判断被注释掉,但原本的意图可能是进一步确保属性类型为可引用对象类型(如GameObject或其他组件)。

使用targetCompo.gameObject.transform.Find(pair.Value).gameObject在目标组件所在的游戏对象下,根据子物体名查找对应的子物体。如果找到,就将该子物体赋值给成员变量对应的SerializedProperty的objectReferenceValue,完成绑定。最后,通过ApplyModifiedProperties将修改应用到组件,使其在编辑器中显示的绑定关系得到更新。

csharp 复制代码
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System;
using UnityEditor;
using UnityEngine;
using static UnityEngine.InputManagerEntry;

public class ComponentBinder : MonoBehaviour
{
    /// <summary>
    /// 对象
    /// </summary>
    private static Component targetCompo;
    [MenuItem("GameObject/ForBind", priority = 29)]
    public static void CreateUICode()
    {
        GameObject obj = Selection.activeGameObject;

        if (!obj) return;

        //获取标记的脚本
        Mark mark = obj.GetComponent<Mark>();

        if (!mark)
        {
            Debug.Log("请挂载Mark脚本");
            return;
        }

        targetCompo = obj.GetComponent(mark.CompoClass.GetType().Name);
        try
        {
            Type type = mark.CompoClass.GetType();
            Dictionary<string, string> dicNameField = FnmGetNameField(type);
            SerializedObject serializedObject = new SerializedObject(obj.GetComponent(mark.targetCompoClass.GetType().Name));
            foreach (var pair in dicNameField)
            {
                SerializedProperty property = serializedObject.FindProperty(pair.Key);
                //if (property != null && property.propertyType == SerializedPropertyType.ObjectReference)
                //{
                    GameObject referencedGameObject = targetCompo.gameObject.transform.Find(pair.Value).gameObject;
                    if (referencedGameObject != null)
                    {
                        property.objectReferenceValue = referencedGameObject;
                    }
                //}
            }
            serializedObject.ApplyModifiedProperties();

            if (dicNameField.Count > 0)
            {
                StringBuilder msg = new StringBuilder("==>成员 : ");

                foreach (string name in dicNameField.Keys)
                {
                    msg.Append(name + "、");
                }

                Debug.LogError(msg + " 无法绑定,请确认物体绑定了Bind脚本或名字与成员名是否一致。");

                return;
            }

        }
        catch (Exception e)
        {
            Debug.LogError("绑定对应物体出错了\n" + e.Message);
            return;
        }

        Debug.Log("=====>获取物体" + obj.name + "上的脚本" + mark.CompoClass.name + "的成员成功了。");
    }

    /// <summary>
    /// 查找脚本中所有需要绑定成员的名字、数据
    /// </summary>
    /// <param name="type">脚本类型</param>
    /// <returns></returns>
    private static Dictionary<string, string> FnmGetNameField(Type type)
    {
        Dictionary<string, string> dicNameField = new Dictionary<string, string>();
        SerializedObject serializedObject = new SerializedObject(targetCompo);
       
        foreach (FieldInfo field in type.GetFields())
        {
            if (!field.IsNotSerialized)
            {
                dicNameField[field.Name] = (serializedObject.FindProperty(field.Name).objectReferenceValue).name;
                Debug.Log("=====>获取物体" + field.Name + "|||" + (serializedObject.FindProperty(field.Name).objectReferenceValue).name + "");
            }
        }
        return dicNameField;

    }

}

遇到的问题

1.提示了Scene mismatch (cross scene references not supported)

当在 Unity 中遇到 "Scene mismatch (cross scene references not supported)" 这个提示时,意味着你正在尝试进行跨场景的引用操作,但 Unity 默认是不支持这种跨场景引用的,以下是可能导致该问题出现的原因以及对应的解决办法:

一、原因分析

  1. 通过 GameObject.Find 查找其他场景中的物体
    在你之前的代码中,如果使用了 GameObject.Find 函数去查找物体,并且期望找到的物体位于当前场景之外的其他场景中,就会触发这个错误。例如,在场景 A 的脚本代码里,尝试通过 GameObject.Find 去获取场景 B 中的某个游戏对象来绑定到变量上,像这样:
csharp 复制代码
public class MyScript : MonoBehaviour
{
    void Start()
    {
        GameObject otherSceneObject = GameObject.Find("ObjectNameInAnotherScene");
        // 后续尝试使用这个对象进行赋值等操作,就可能触发错误
    }
}

因为 GameObject.Find 只会在当前激活的场景中查找符合条件的对象,无法跨越场景去查找。

  1. 在序列化属性中设置了跨场景的对象引用

在 Unity 编辑器环境下,通过 Inspector 面板或者自定义编辑器脚本设置序列化公共变量(比如 GameObject 类型的变量)的引用时,如果不小心将一个来自其他场景的对象拖放到变量引用位置,同样会出现此问题。例如,在场景 A 中的脚本组件的 Inspector 中,想要为一个 public GameObject myObject; 变量指定引用,却错误地拖放了场景 B 里的游戏对象。

2.pecified cast is not valid.

在 Unity 中遇到 "Specified cast is not valid." 这个错误提示,通常意味着你正在进行一个类型转换操作,但实际的数据类型与期望转换的类型不匹配,以下是几种可能导致该错误出现的情况以及相应的解决办法:

  1. 变量赋值时类型不匹配
    情况描述:
    当你试图将一个不兼容类型的值赋给某个变量,并且进行了显式或隐式的类型转换时,就可能出现此错误。例如,你有一个变量声明为 int 类型,却试图将一个 string 值赋给它并进行转换(即便在代码中看起来像是合理的类型转换写法)。
    示例代码及分析:
相关推荐
不吃斋的和尚1 小时前
Unity中一个节点实现植物动态(Shader)
unity·游戏引擎
waicsdn_haha2 小时前
Visual Studio Code 2025 安装与高效配置教程
c语言·ide·windows·vscode·微软·编辑器·win7
程序猿多布2 小时前
Unity 位图字体
unity
pchmi3 小时前
CNN常用卷积核
深度学习·神经网络·机器学习·cnn·c#
yuanpan3 小时前
23种设计模式之《组合模式(Composite)》在c#中的应用及理解
开发语言·设计模式·c#·组合模式
莲动渔舟4 小时前
国产编辑器EverEdit - 在编辑器中对文本进行排序
java·开发语言·编辑器
千年奇葩4 小时前
Unity shader glsl着色器特效之 模拟海面海浪效果
unity·游戏引擎·着色器
滴_咕噜咕噜4 小时前
C#基础总结:常用的数据结构
开发语言·数据结构·c#
太妃糖耶6 小时前
Unity摄像机与灯光相关知识
unity·游戏引擎
007_rbq6 小时前
XUnity.AutoTranslator-Gemini——调用Google的Gemini API, 实现Unity游戏中日文文本的自动翻译
人工智能·python·游戏·机器学习·unity·github·机器翻译