C# 在Unity上以编程方式绑定脚本属性(非运行时的编辑模式)

C# 在Unity上以编程方式绑定脚本属性(非运行时的编辑模式),c#,unity3d,unity-editor,C#,Unity3d,Unity Editor,例如,我有一个名为Foo的monobhavior派生类: class Foo : MonoBehaviour { public Button lastButton; public Image []images; } [CustomEditor(typeof(Foo))] class FooEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector()

例如,我有一个名为
Foo
monobhavior
派生类:

class Foo : MonoBehaviour {
   public Button lastButton; 
   public Image []images;
}

[CustomEditor(typeof(Foo))]
class FooEditor : Editor {

    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        Foo foo = (Foo)target;
        if(GUILayout.Button("Bind last Button and all Images")) {
           /* how to bind programatically last foo.GetComponentsInChildren<Button>(); 
              to foo.gameObject.scene's 
                 foo.gameObject.GetComponent<Foo>().lastButton 
              in edit mode's property window 
                 (without have to drag on the editor)?
           */
           /* and how to bind programatically all foo.GetComponentsInChildren<Image>(); 
              to foo.gameObject.scene's 
                 foo.gameObject.GetComponent<Foo>().images 
              in edit mode's property window 
                 (without have to drag all one by one)?
           */
        }
    }
}
Foo类:单一行为{
公共按钮;
公众形象[]形象;
}
[CustomEditor(typeof(Foo))]
类编辑器:编辑器{
公共覆盖无效OnInspectorGUI()
{
DrawDefaultInspector();
Foo-Foo=(Foo)目标;
if(GUILayout.Button(“绑定最后一个按钮和所有图像”)){
/*如何以编程方式绑定最后一个foo.GetComponentsInChildren();
到foo.gameObject.scene的
foo.gameObject.GetComponent().lastButton
在编辑模式的属性窗口中
(无需在编辑器上拖动)?
*/
/*以及如何以编程方式绑定所有foo.GetComponentsInChildren();
到foo.gameObject.scene的
foo.gameObject.GetComponent().images
在编辑模式的属性窗口中
(不必一个接一个地拖动)?
*/
}
}
}
我想在不需要一个接一个拖动或在运行时执行的情况下自动执行,如何以编程方式执行


我能想到的唯一解决办法(如果没有这样的API)是保存场景,解析场景,然后更新yaml文件上的绑定,并强制UnityEditor重新加载yaml,但不确定它是否能工作,因为

,尽管老实说,我仍然不理解“绑定”的目的,在我看来,您实际上是在谈论通过编辑器脚本简单地引用所有组件,而不必拖放它们。(可能这里有装订,我只是不知道用这个名字?)

首先,确保
FooEditor
的整个代码都放在名为
Editor
的文件夹中,或者将其包装在

#if UNITY_EDITOR
    // any code using UnityEditor namespace
#endif
以便在以后的构建中剥离它们。否则,您将得到编译器错误,因为
UnityEditor
将不存在于生成中

然后,重要的是始终在编辑器脚本中操作s中的s。这会将所有标记处理为脏,为您保存更改和撤消/重做条目。如果你碰巧直接操纵了恶魔,你必须自己处理这些事情

因此,在加载和写回真正的目标组件及其序列化对象之间的值方面起着关键作用——我喜欢称之为“影子克隆”

或者也

var serializedLastButton = new SerializedObject(lastButtonField.objectReferenceValue);
现在,当再次使用
FindProperty(propertyName)
更改其中的任何字段时,请确保再次使用

serializedLastButton.Update();

// make changes

serializedLastButton.ApplyModifiedProperties();

你想和Foo绑定什么?还有多少对象?@Ruan很多,我想通过按一下按钮自动绑定来减少手动拖放/布局和编码工作流。我已经制作了一个属性生成器(图像、按钮、脚本等),现在第二步是自动将组件/脚本绑定到我生成的属性。因此,当您按下
Foo.lastButton
时,您正试图将图像绑定到
Foo.images
?如果是,这些图像在哪里?它们是游戏对象还是项目目录中的图像?否@Ruan,它在UnityEdit(
GUILayout.Button
)的编辑模式下工作,当我单击该按钮时,我想从场景中存在的游戏对象/脚本中绑定Foo.images和Foo.lastButton(通常我们使用拖放)我读了文件,但还是不明白:到底什么是绑定?这样做的预期行为是什么?这真是太棒了,但是如果我想修改其他脚本的属性(例如
foo.gameObject.GetComponent()
)而不是foo的脚本属性,该怎么办?我提出了另一个与此主题相关的问题:我看到你已经解决了。实际上,您只需使用
newserializedObject(someObjectReference)
即可获得它的序列化对象。我在回答中提到了它,但删除了它,因为我认为提到它可能会让人困惑;)
var serializedLastButton = new SerializedObject(lastButtonField.objectReferenceValue);
serializedLastButton.Update();

// make changes

serializedLastButton.ApplyModifiedProperties();