自定义编辑器中的弹出字段会在播放时重置

时间:2018-12-05 12:23:01

标签: unity3d

尝试编写自定义编辑器的代码,但是当我按下播放按钮时,下拉列表或弹出字段的值始终会重置。

我浏览了一些类似的问题,发现添加“ apply”修改和置为脏的解决方案,但是都不能解决问题。

有什么想法吗?

这是下面的代码:

$.ajax({
    url: '<?php echo base_url();?>index.php?staff/fetch_history',
    method: 'POST',
    dataType: 'html',  // here is the change
    data: {
        category_id: $("#category_id").val(),
        agent_id: $("#agent_id").val(),
        year: $("#year").val(),
    },
    success: function (response) {
        jQuery('#ajax-content').html(response);
    }
});

2 个答案:

答案 0 :(得分:0)

您应该在EnemyAI类中定义choiceIndex属性和基值,然后像下面这样在EditorScript中对其进行设置:

mc.choiceIndex = EditorGUILayout.Popup(mc.choiceIndex, _choices);

也在if语句中:

 if (_choices[mc.choiceIndex] == "snailer"){
     ...
 }

希望有帮助!

答案 1 :(得分:0)

首先:不要结合

EditorUtility.SetDirty(target); 
serializedObject.ApplyModifiedProperties();

尽量不要混用SerialzedProperties,我称之为“直接”属性(使用target)!这会导致很多麻烦。

您也在打电话

serializedObject.ApplyModifiedProperties();

但是我看不到你打给哪里

serializedObject.Update();

首先获取当前值。

我还认为评论不属于那里

// Draw the default inspector
var mc = target as EnemyAI;

至少那不是那里发生的事情。


最后,重置您的值的原因是您在编辑器脚本中引入了_choiceIndex,所以serialzedObject.ApplyModifiedProperties()EditorUtility.SetDirty(target)都没有 由于它不是目标类的SerializedField,将对其产生任何影响。这还不好,原因有三:

  1. 编辑器脚本将不会编译到内部版本->该值将不可用
  2. 您也无法从您的实际班级访问该值->有什么好处呢?
  3. ,即使它只是编辑器内部内容的控制值:每次初始化编辑器脚本时,都会重置该值。发生

    • 每次重新编译后
    • 进入或退出播放模式后
    • 每次目标对象都获得焦点

要保存该值,您应该将_choiceIndex放在EnemyAI类中,但为什么不简单地使用您的枚举EnemyAI.Type或更好地说已经存在的字段type呢?假设

[SerialzeField] private EnemyAI.Type type;

在您的编辑脚本中,您只需执行

// This automatically also uses the label "Type"
EditorGuyLayout.PropertyField(serializedObject.FindProperty("type"));

还有

if ((EnemyAI.Type)_choiceIndex.intValue == EnemyAI.Type.snailer)

或者,如果您想坚持使用字符串列表,例如要通过编辑器脚本填充更多选择选项,您可以使用int来执行相同的操作,但也可以使用SerializedProperty

在EnemyAI中

[SerializeField] private int _choiceIndex;

然后在编辑器中

SerializedProperty _choiceIndex = serialzedObject.FindProperty("_choiceIndex");
_choiceIndex.intValue = EditorGuyLayout.Popup("Type", _choiceIndex.intValue, choices);

所以我的一些外带规则就像

  1. 始终,如果要更改/保存值,请使用SerlialzedProperty。要使它们运行有时会有些棘手(尤其是使用列表或嵌套类),并且您很容易犯错,因为您是通过变量名(字符串)获取它们的。但是它们带来了很多好处,例如自动将内容标记为脏,撤消/重做等。

  2. 曾经直接使用target as <some type>来访问内容的原因应该是从编辑器中调用类的方法(首选不变的方法)序列化的值)。但也要在这里:仅在确实有必要时才使用它,因为如前所述,将SerializedProperty和直接更改混在一起常常会使事情搞砸。

  3. 仅在以下情况下才应在检查器中引入变量

    • 您没有兴趣保存它们
    • 他们在每次检查员失去焦点时重置
    • 它们是您永远不会更改的常量值(例如,字段标签或choices数组)

最后一条一般提示:

您不应在每次抽奖中使用serializedObject.FindProperty。而不是像{p>一样在OnEnable()中收集一次您的所有财产

SerializedProperty _type;
// ...

private void OnEnable()
{
    _type = serializedObject.FindProperty("type");
    // ...
}

public override void OnInpectorGUI()
{
    // ...
    EditorGUILayout.PropertyField(_type);
    // ...
}