Coding Behaviour Tree Task Issues

I’m currently working on Behaviour Tree Tasks and something I’m having major issues with is lines of code like this (where bbKey is an FBlackboardKeySelector type variable)

if (bbKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass())
 {
 }

The comparison simply never works. even when I compare a float key type with a UBlackboardKeyType_Float::StaticClass() it always returns false, has this approach been changed? What am I doing wrong?

Another question I’ve had, is that in certain scripts I’ve seen the KeySelectors are declared like this:

struct FBlackboardKeySelector bob;

Is this simply forward declaration, meaning in such a situation bob.GetValueType would not be able to be accessed?

Finally a question I have is about the function signatures of things like TickTask, that have a uint8* as a parameter:

void UBTTask_MoveTo::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)

I appreciate that the pointer is to the area in which a task would store its between tick data, such as on the wait how much time is left, yet the data is stored in a struct, not a uint8, so are these structs unions? If so, is no item in the union allowed to exceed a size of uint8? because I assume floats are 32bit as standard, but I have seen them in such structs.

if (bbKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) works in generic case, you must be doing something funky. Please share more details regarding your setup. Or try debugging it yourself, it’s a good practice if you want to work with C++.

struct FBlackboardKeySelector bob; is indeed a forward declaration and has not impact on the way bob variable works.

uint8* in TickTask (and other similar functions) is a pointer to node’s memory which size you declare by returning your memory’s struct size in GetInstanceMemorySize, like so:

uint16 UBTTask_MoveDirectlyToward::GetInstanceMemorySize() const
{
	return sizeof(FBTMoveDirectlyTowardMemory);
}

If your node has declared memory usage like that all you need to do is to cast uint8* pointer you get to pointer to your dedicated memory struct.

Cheers,

–mieszko

I’ve attached an image displaying the issue I’m currently having, hopefully I’m not doing anything idiotic, and I hope it’s the right level of detail to be useful, I think it’s all the elements that matter.

In regards to the forward declaration, am I correct in saying that by forward declaring the struct, I would not be able to access any of its members, only tell the compiler “this type exists don’t worry about what size it is or what’s in it”?

I think that GetInstanceMemorySize makes sense, it wouldn’t matter necessarily that it were a uint8* pointer or a uint16* as they would still point to the same address, so they could quite easily be cast between without issue as long as no pointer arithmetics were taking place, or is that incorrect?

Not immediately obvious to me why it’s not working, as Mieszko says you really need to step through in the debugger and find out what the value of tankPercentage.SelectedKeyType actually is. Is it null, for example?

What you say about forward declaration is in general correct. However in this case, I believe that it is more a case of C-style programming habits, where the struct keyword is necessary. Since in this case the declared variable is a member variable, forward declaration isn’t sufficient. The full struct definition needs to be known, so I’m pretty sure the struct keyword is redundant.

You’re right about the pointers, but uint8* tends to be used when working with raw memory, since a uint8 is always a single byte which makes addressing and offsetting easier.

I worked out the answer to this, in my case I wasn’t overriding the InitializeFromAsset function and caching the values of each of the keys. (looked in BTT_BlackboardBase for an example) Now that I’ve done this, the comparisons seem to be working fine.

Thank you! I ended up falling into the exact trap.