simonrcodrington
New member
Hi
I've got a question about the correct way to handle saving/loading state when it comes to behaviors. I would really appreciate any feedback because it feels like I'm not doing this optimally.
I've been using Behavior Designer to create various actions in my game. Each of these behaviors is an external behavior and takes care of a single series of tasks (such as collecting a resource, moving an agent to multiple positions etc).
I've created a prefab and it contains a BehaviorTree component with an external behavior and a custom monobehavior component. Here is a 'collectionResource' behavior.
Overall the agent will start, get given a 'resource' to look for, find that resource on one of the businesses, move to it, collect it and take it back to it's origin
The variables are all mapped from the external behaviors to the custom monobehavior component
The reason for this custom monobehavior along-side this behavior tree is that I need to save and load this data. I'm using Easy Save 3 to save the public variables on it and overall I'm able to save the values below :
And then re-load them later (right now it's just a button in the UI to load the data), but it calls the following:
Since this is a prefab, I just instantiate the prefab onto the agent and access my custom monobehavior on it, via that I can access the BehaviorTree component and set up variables (and start the behaviorTree). All of this works and I can swap out behaviors on the fly for a single agent (imagine a sim game where an agent can chop a tree, finish and then go mine gold etc)
My question is about HOW I'm supposed to set these behavior trees up logically. If I load the data, all of the data gets copied back into the behavior (via setting the variables up as above) so that's great. However, because this could get saved at any moment, I'm having issues creating the trees such that the behavior can re-start and get back to the proper state it should be.
I've managed to get this working by setting this up as above, a top level SELECTOR that looks at a series of sequences, inside each of the sequences I've created a custom 'CompareSharedCollectionBehaviorType' which is a copy of your 'CompareSharedInt' comparison conditional. Inside the behavior I have a 'SharedCollectionBehaviorState' which is just a custom shared type so I can use an Enum here for comparisons. This lets me check the variable to see if it's 'START', 'SEARCH_BUSINESS', 'MOVE_TO_BUSINESS', 'MOVE_TO_ORIGIN' etc.
I tried to use the CODE editing options here, but i get a 500 ERROR when positing it. This system is just an enum, a shared enum I created and a comparison conditional.
To the right of this ENUM check is a custom action, where inside I manually update that 'SharedCollectionBehaviorState' variable. When I've successfully found a business, moved to the business or moved back to origin I update that accordingly. Like below, the start action just moves the state to the next, the search business phase.
This works fine, as soon as one of these tasks finishes, the selector returns true and the behavior finishes, when it finishes it restarts and now moves from left to right hitting each sequence and checking that conditional so it selects where it should execute from.
This works on this smaller behavior, but as I create more complex behaviors I feel like setting it up this way is going to become super complex. I've looked into the resources on Conditional Aborts, but I can't really see how they would help me improve this design (as it needs to be written in such a way that if we're creating a brand new agents it can move left to right, manually setting up it's data / when we reload it can resume at the proper state and continue)
Id really appreciate any feedback on how to improve this. I can make a small self-contained unity example if that would help illustrate what I'm trying to achieve.
Regards
Simon
I've got a question about the correct way to handle saving/loading state when it comes to behaviors. I would really appreciate any feedback because it feels like I'm not doing this optimally.
I've been using Behavior Designer to create various actions in my game. Each of these behaviors is an external behavior and takes care of a single series of tasks (such as collecting a resource, moving an agent to multiple positions etc).
I've created a prefab and it contains a BehaviorTree component with an external behavior and a custom monobehavior component. Here is a 'collectionResource' behavior.
Overall the agent will start, get given a 'resource' to look for, find that resource on one of the businesses, move to it, collect it and take it back to it's origin
The variables are all mapped from the external behaviors to the custom monobehavior component
The reason for this custom monobehavior along-side this behavior tree is that I need to save and load this data. I'm using Easy Save 3 to save the public variables on it and overall I'm able to save the values below :
And then re-load them later (right now it's just a button in the UI to load the data), but it calls the following:
Since this is a prefab, I just instantiate the prefab onto the agent and access my custom monobehavior on it, via that I can access the BehaviorTree component and set up variables (and start the behaviorTree). All of this works and I can swap out behaviors on the fly for a single agent (imagine a sim game where an agent can chop a tree, finish and then go mine gold etc)
My question is about HOW I'm supposed to set these behavior trees up logically. If I load the data, all of the data gets copied back into the behavior (via setting the variables up as above) so that's great. However, because this could get saved at any moment, I'm having issues creating the trees such that the behavior can re-start and get back to the proper state it should be.
I've managed to get this working by setting this up as above, a top level SELECTOR that looks at a series of sequences, inside each of the sequences I've created a custom 'CompareSharedCollectionBehaviorType' which is a copy of your 'CompareSharedInt' comparison conditional. Inside the behavior I have a 'SharedCollectionBehaviorState' which is just a custom shared type so I can use an Enum here for comparisons. This lets me check the variable to see if it's 'START', 'SEARCH_BUSINESS', 'MOVE_TO_BUSINESS', 'MOVE_TO_ORIGIN' etc.
I tried to use the CODE editing options here, but i get a 500 ERROR when positing it. This system is just an enum, a shared enum I created and a comparison conditional.
To the right of this ENUM check is a custom action, where inside I manually update that 'SharedCollectionBehaviorState' variable. When I've successfully found a business, moved to the business or moved back to origin I update that accordingly. Like below, the start action just moves the state to the next, the search business phase.
This works fine, as soon as one of these tasks finishes, the selector returns true and the behavior finishes, when it finishes it restarts and now moves from left to right hitting each sequence and checking that conditional so it selects where it should execute from.
This works on this smaller behavior, but as I create more complex behaviors I feel like setting it up this way is going to become super complex. I've looked into the resources on Conditional Aborts, but I can't really see how they would help me improve this design (as it needs to be written in such a way that if we're creating a brand new agents it can move left to right, manually setting up it's data / when we reload it can resume at the proper state and continue)
Id really appreciate any feedback on how to improve this. I can make a small self-contained unity example if that would help illustrate what I'm trying to achieve.
Regards
Simon
Last edited: