With the hard GsoC deadline rapidly approaching, I thought it suitable to wrap up what I have achieved this summer and my ideas for future development that could be done in the areas I have been working.
Event Driven Behaviour Trees.
Behaviour trees have been updated to an event driven design using a wider, more expressive set of termination statuses (See BTStatus in tools/behaviourtree.h.) Instead of evaluating the whole tree every frame, the new trees only expand a set number of nodes each frame. The number of these can be set using the property "Update Rate." These changes will improve the ability to handle large trees or applications with large numbers of characters.
Furthermore, I have implemented the behaviour tree as a propclass allowing a tree to be assigned to an entity. Because of this change trees are now executed by performing the action "BT Start" as opposed to the previous method of executing the root node. Examples of this can be found in appbttest and the Frankie's in lifesimdemo.
The manual coding of trees, however, has remained largely the same - with nodes constructed and children added using the same methods. Therefore, existing implementations only need to replace the previous execution of the root node with the initiation of the propclass celPcBehaviourTree and starting it by the action "BT Start."
Alternatively, behaviour trees can now be designed in and loaded from XML thanks to plgaddon_behaviourtreeload.
Other methods have also been added, most notably the ability to name a node by SetName allowing for clearer debug messages when a node raises an unexpected error and allowing loop decorators to loop infinitely.
Examples of how to load a behaviour tree from xml are available in appbttest and the life sim demo. Appbttest also has an example of constructing a behaviour tree in code and a related tutorial in the cel user manual.
Future work that may be helpful for the further development of these tools include a save to XML method (for outputting trees either coded or loaded and then manipulated at run time), the continued development of additional decorators (expanding the capabilities of the trees) and the incorporation of behaviour trees into csEditor and/or AresEd. I think the latter may be the key to wide spread adoption of this method in future applications and so am very keen to assist with this where I can post-GSoC.
Recast and Detour (R&D) Update.
The R&D plugin has been updated to revision 345 (the currently latest available) and the construction of NavMeshes is now performed in parallel.
I have also fixed a large number of issues left over from the pre-existing implementation of this plugin that required app developers to handle the deletion of variables initialised within the R&D plugin.
Appnavmeshtest and apppathfinding both demonstrate how to construct, display and use navmeshes.
Due to the unexpected discovery of the bugs mentioned above, I did not get time to get around to a number of deliverables that were considered lower priority but would be significant improvements to the R&D plugin. Namely they are the better handling of portals and the partial loading of NavMeshes. The first I think is a key improvement and should be addressed asap as the current method hardly/doesn't work and effectively limits users to only path finding within a sector, not across sectors.
Other issues noted with the creation of NavMeshes that could do with further attention have been noted in the outside sector of the bias level and the interior sector of the castle level.
Bias Level: Outside Sector.
When constructing a navmesh for this sector, the process seems to never stop. However, I predict it would given a very long time. The delay is in the double for loops on lines 2343-2345 of celNavMesh.cpp in the function celNavMeshBuilder::BuildNavMesh. Normally tw and th take values approximately in the range 1-20 but for outside they are both over 600. I think this is because the outside sector is huge, but also because it is a very uniform, flat surface. However, the latter should make it very simple to cover.
Castle: Interior Sector.
The navmesh constructed for the interior sector appears to be made up of multiple overlapping (and slightly different) navmeshes. There should be only one. I think this may be related to the handling of portals, because if you generate the navmesh for this sector alone or even with only one other sector it does not occur. As soon as navmeshes are generated for this sector and two others the overlapping occurs. I think that focussed efforts on a new method of handling portals will fix this incorrect behaviour. This problem is less severe than the above, however, as the path finding still works correctly in this sector despite the overlapping meshes.
Finally, I have also added methods to PcSteer for adding a HNavStruct if available and then using this when seeking to find a path rather than the bespoke path finding solution previously used. For an example of this use please see appsteering.
The work I have done on PcSteer could be improved by allowing pursue, flee and wander to also use the HnavStruct but I think a more significant change should be made to this plugin.
I propose that the plpfsteer is deprecated and the functionality of pcSteer merged into pcPathFinder. If the merged propclass is given a HNavStruct it can use that to move between sectors and pathfind within (with HNavStruct eventually being updated to have improved functionality between sectors) or alternatively it is given a celGraph to move between sectors and uses it's naeve move directly towards goal position pathfinding within them. It would also then allow methods such as FollowCyclicPath or FollowTwoWayPath to be used with R&D as well.
The new pcPathFinder would then include all methods for moving agents in an environment with the possibility of using either the celGraph or the recast plugin. Rather than the current convoluted architecture where pcPathFinder uses celGraph and pcSteer which may or may not use the R&D plugin.
In closing, I think this has been a very succesful summer. I feel this year I have learnt a lot more about the architecture of CEL as a whole and the experience of fixing memory management bugs in other people's code I'm sure will be priceless in the future (despite how frustrating it was at the time!)
Last GSoC I hoped to continue working on CS/CEL after the summer alongside my PhD, this never happened because I understimated how much of my life would become my PhD. After this GSoC I will be writing my thesis and trying to secure a job, so I will not make any promises for how much code I will be able to commit but I do hope to still be a part of the community and assist where I can with getting this code merged back into trunk and used more in future games and applications.
Finally I would like to thank everyone that has made this summer so productive and enjoyable. In particular: Anthony for being my mentor, Christian for his input and advice throughout, Matthieu Kraus for some key comments/suggestions regarding R&D and Jorrit, Vincent Knecht & Anders Reggestad for checking out my branch and testing/trying the apps I've worked on. Thank you all.