Forums › 💬 NodeCanvas › ⚙️ Support › Set Field issue with BB variables
Set Field action returns Success, but BB variables are not assigned to the requested fields.
Example scene with only two 3D spheres:
sourceSphere has a bound behaviour tree and a blackboard that contains variable myGameObject == sourceSphere
targetSphere has a C# script component with a public GameObject variable “target”.
SourceSphere’s BT has only a single node and action: Set Field, configured as targetSphere.target=$myGameObject from the UI menus which allow the user to set the target’s transform, variable and value.
End result: BT returns success, but targetSphere.target remains null.
If I drag ‘n drop sourceSphere from the scene hierarchy into Set Field’s Set Value slot directly, the BT behaves as expected, targetSphere.target gets sourceSphere assigned to it.
In addition, the UI behaviour for Set Field is inconsistent:
– When the Set Field action is first created, targetSphere can be assigned as the transform, the public variable selected from a drop-down list, and myGameObject selected as a blackboard value.
– After pressing Play and then stopping the editor build, the BT changes behaviour, and Set Field’s pull-down menu no longer displays myGameObject as a valid variable for the slot, instead only listing NONE and (DynamicVar) as the available options.
Hello,
You are very correct here. It’s a bug. Although It’s 2 lines change, here is the whole code.
Please open up SetField.cs and replace the whole code with this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
using System.Reflection; using NodeCanvas.Framework; using NodeCanvas.Framework.Internal; using ParadoxNotion; using ParadoxNotion.Design; using UnityEngine; namespace NodeCanvas.Tasks.Actions{ [Category("✫ Script Control/Common")] [Description("Set a variable on a script")] public class SetField : ActionTask { [SerializeField] private BBObjectParameter setValue; [SerializeField] private System.Type targetType; [SerializeField] private string fieldName; private FieldInfo field; public override System.Type agentType{ get {return targetType?? typeof(Transform);} } protected override string info{ get { if (string.IsNullOrEmpty(fieldName)) return "No Field Selected"; return string.Format("{0}.{1} = {2}", agentInfo, fieldName, setValue); } } protected override string OnInit(){ field = agentType.RTGetField(fieldName); if (field == null) return "Missing Field Info"; return null; } protected override void OnExecute(){ field.SetValue(agent, setValue.value); EndAction(); } //////////////////////////////////////// ///////////GUI AND EDITOR STUFF///////// //////////////////////////////////////// #if UNITY_EDITOR protected override void OnTaskInspectorGUI(){ if (!Application.isPlaying && GUILayout.Button("Select Field")){ System.Action<FieldInfo> FieldSelected = (field)=>{ targetType = field.DeclaringType; fieldName = field.Name; setValue.SetType(field.FieldType); }; if (agent != null){ EditorUtils.ShowGameObjectFieldSelectionMenu(agent.gameObject, typeof(object), FieldSelected); } else { var menu = new UnityEditor.GenericMenu(); foreach (var t in UserTypePrefs.GetPreferedTypesList(typeof(Component), true)) menu = EditorUtils.GetFieldSelectionMenu(t, typeof(object), FieldSelected, menu); menu.ShowAsContext(); Event.current.Use(); } } if (agentType != null && !string.IsNullOrEmpty(fieldName)){ GUILayout.BeginVertical("box"); UnityEditor.EditorGUILayout.LabelField("Type", agentType.Name); UnityEditor.EditorGUILayout.LabelField("Field", fieldName); UnityEditor.EditorGUILayout.LabelField("Field Type", setValue.varType.FriendlyName() ); GUILayout.EndVertical(); EditorUtils.BBParameterField("Set Value", setValue); } } #endif } } |
Thanks a lot!
Thanks, it’s working now.
