I guess I’m doing something wrong in how I’m defining the Variable that’s passed into the condition? Or am I not reading the correct property to determine the value of the variable?
Thanks for any help!
EDIT: I guess it’s because I selected Variables, which is something from Visual Scripting, not from Behaviour. But there doesn’t appear to be a way to pick a BlackboardVariable as the type.
public override bool IsTrue()
{
return ReferenceEquals(Variable.Value, null);
}
.Value is the generic type, that the Blackboardvariable represents. the nullcheck asks if the value itsself is null. Lets say there is nothing dragged in that field, your check returns TRUE, since the value is automatically null aswell. If there is something dragged in that field, but the value itsself is null, your check returns TRUE
I have the problem that I one of my Nodes needs to have an OUT Variable, which can be null when the node is initialized, but it needs to be assigned.
Checking:
if (ReferenceEquals(Target.Value, null)) { }
will succeed, if no variable assigned, or the assigned variables value is null
Checking: if (ReferenceEquals(Target.ObjectValue, null)) { }
Is never returning false as @mroshaw showed above
Checking: if (ReferenceEquals(Target, null)) { }
Is never returning true.
Yeah, I just fired up a new project with the Behaviour Sample, using Behaviour 1.0.5. The included example condition, NullCheckCondition, does exactly the same as mine does - returns false irrespective of whether the variable is indeed null or otherwise.
Great!
Theres also this Node made by you guys, which has an OUT Variable.
In Code you guys tried to make the node fail, if the OUT is not assigned, but since the
if(Object == null) will never return null, this node can never fail
namespace Unity.Behavior
{
[Serializable, GeneratePropertyBag]
[NodeDescription(
name: "Find With Tag",
description: "Finds a GameObject with a tag.",
story: "Find [Object] with tag: [Tag]",
category: "Action/Find",
id: "c83ba0235980a2a0ff12705e1f4fdcea")]
internal partial class FindObjectWithTagAction : Action
{
[SerializeReference] public BlackboardVariable<GameObject> Object;
[SerializeReference] public BlackboardVariable<string> Tag;
protected override Status OnStart()
{
if (Object == null)
{
return Status.Failure;
}
Object.Value = GameObject.FindGameObjectWithTag(Tag.Value);
return Object.Value == null ? Status.Failure : Status.Success;
}
}
}
Hi, thank you for bringing that issue to our attention.
Several users have been reporting issue around the null checking being an issue with our node. It seems like something is going wrong because of the additional logic those operators can have.
Can you try using ObjectValue.Equals(null)?:
if (Variable.Type.IsValueType)
{
return false;
}
return Variable.ObjectValue.Equals(null);
Just to add, I’ve also created an Action to set a variable to null - for example, to clear out a target Transform when the AI loses sight of the player:
public partial class SetVariableNullAction : Action
{
[SerializeReference] public BlackboardVariable Variable;
protected override Status OnStart()
{
Variable.ObjectValue = null;
return Status.Success;
}
}
In order to get the Condition to work with this, I’ve had to amend it slightly:
public partial class VariableIsNullCondition : Condition
{
[SerializeReference] public BlackboardVariable Variable;
public override bool IsTrue()
{
if (Variable.Type.IsValueType)
{
return false;
}
return Variable.ObjectValue is null || Variable.ObjectValue.Equals(null);
}
}
You can also set a Blackboard variable to null/default by using SetVariableVariable without passing a Value field.
Based on several users report and a quick internal investigation, it seems like Variable.ObjectValue is null or using the == operator is always returning false so you should only need Variable.ObjectValue.Equals(null).
You are actually right about checking is null first, for some reason the behavior change and cause nullreference on build player.
I believe this might be caused by the fact that BlackboardVariable are creating a default value to be serialized in blackboards. So even a Blackboard variable don’t have a value assigned don’t means it doesn’t have an object allocated in memory. Leading to a “null” value being different from the object itself not being allocated in memory and being null.
where that Branch on node always returns true, even if Target is null (which happens once the first branch completes).
I don’t know if I should use a simple Variable Comparison condition like that in the Branch on node, like I’m doing, and this is an error, or if I should use a custom condition to check for null. Any idea?
I’ve looked a little bit more in the area and it there is a bug in editor where null comparison of BlackboardVariable.ObjectValue is always returning true. This is not the case in Playber build, where the comparison is able to return false!
So for now I would recommend you to make a condition like mentioned above to make it behave the same in both editor and player build.