Game Development Community

dev|Pro Game Development Curriculum

Behavioral Sciences

by Jeff Raab · 06/01/2013 (7:54 am) · 8 comments

Been a ridiculous amount of time since I've posted anything up on here.

So, where to start...

In the course of developing my games I've started and half-finished a multitude of side/sub-projects that helped me learn things I needed to get closer to the completion of my main game. I'll document more of these(and as I've mentioned in some posts on the forums, quite a few of them have to do with the editors, pipeline, workflow, etc.

There's one in particular I'm going to highlight today, as it's nearing production-worthiness now, and that's a Behaviors/Component system.

There'd been a few that have popped up before, so it's not like this is a new endeavor or anything, but for the lack of anyone bringing it out, and me having an itch for mission-scripting due to some of the elements in my game, I needed a system for quickly slamming together an object that could be powered through scripts, ideally without needing to make and load script files.

If you've ever dealt with stuff like hammer, or UnrealEd or any other plethora of editors for other engines, they're pretty friendly when it comes to 'mission scripting', aka being able to build and orchestrate scripted actions or objects that are unique to the level itself.

T3D touches on this in a bare minimum way, like through the Triggers having the command callbacks, which is USUALLY good enough, but I was dealing with some pretty ornate behaviors that vary largely mission-to-mission, so I needed flexibility without having to have half a million custom datablocks and script files to get a one-off scripted event to work in one mission, never to be seen again.

The first thing I tried was the 'Actor' class object.
Derived straight from gamebase, it was super lightweight, and had a multitude of callbacks and commands. The datablock was actually entirely optional, so you could either build a permanent object with a datablock and use the callback methods in script for complex objects used multiple times, or slap an Actor object in the mission, assign it a shape and script in some behaviors right into the mission file using the commands.

I actually got it as far as being able to code input and control with a player object, driven entirely through script(collisions being engine-side still) but otherwise movement, velocity, and base physics was done in script, entirely in the mission file itself.
The problem was that the command callbacks are limited to 1024 characters, which when you get into really complex stuff like building a player object, takes EVER so slightly more than that.
I couldn't find a workable solution to expand the command length, so I stepped back and re-thought my approach.

That's when I remembered there was that newfangled COMPONENT system wafting about in T3D like some poor guy's appendix.
I remembered T2D actually DID stuff with behaviors, and T3D's component/behavior system is pretty much exactly that just...you know, not working.
So I cracked open T2D to figure out how it handled behaviors, and set to work retooling the T3D code to actually be usable.
I also retooled the Actor class to be the class of choice to use behaviors with, as it was super-lightweight and as mentioned, the datablock was optional.
With behaviors, I could easily drop in an Actor, slap a few behaviors onto it and never have to touch unique scripts for the object, which is close to what I wanted.

But as I was working on it, I decided that a base, script-only behavior system was kinda limited. Good, but limited.
So I figured, 'Hey, I bet I could slap together engine-side components so the actor class can have behaviors to manage it's rendering, ticking, etc'!

So I launched into that, and a few days later, I can indeed slap a behavior onto the Actor object and it'll render based on the behavior, the only code in the actor object basically checking if there are any render type behaviors assigned onto it.
The real trick was getting behaviors to network in a sane sort of way.
On the surface, networking is pretty easy. Declare the class a netobject, set the ghost flags, have your pack/unpack and bam, networked central.

Which is great!...

...unless you need the Actor, Behavior instance and behavior template to all know about each other, at creation of each, simultaneously so when everything is ghosted, it works right. THAT was trickier.
But after a lot of trial and error and realizing I reaaaaaally hate ghosting things, I managed to get the behavior system to realize that ghosts are totally cool, and they should be them all the time.

The end result being properly ghosted behaviors, which is mandatory for client-side stuff like rendering behaviors.

So I have the Actor class, which works with the component/behavior system, mundane script behaviors AND engine-behaviors, hooks for stuff like rendering, networking, ticking, etc in there for derived and custom behaviors. Oh, and clean, natural editor integration.
There's that, too.

I decided to take a page from T2D's look for how behaviors are managed in the inspector, because honestly it always felt more coherent and easier to understand that the heirarchial folder interface I've seen other implementations use.
So, when you have an Actor object, there's a Behaviors group. A clean object has no behaviors, and only a add button and a drop down, which loads all the existing behaviors into the list.
Pick a behavior in the drop down, punch add, and blam. You have a behavior on the object ready for unique settings on that instance.
You edit the behavior like a special, fancy field in the editor, and each behavior comes with a nice big 'remove this behavior' button as well.
It's all very clean, easy to understand, and without extra crap floating in the interface.

At this point, I've got some bug-fixing to do, decent bit of cleanup and build some core example behaviors as a starting point. But on a base level, it's functional now.

Whenever it DOES get out there, however it happens, I also mentioned I want a starter library of behaviors as a base. There are currently 3 engine-type behaviors, and the script behavior.
Tickable, Render, and Network.

Tickable would be done through a hook in the processTick. It'll tick down to the behaviors(passing the move pointer if needed) and would allow stuff like physics, control object, health, etc all handled there. Think how the Player class has ProcessTick->updateMove and you've got the idea.

Render is What It Says on the Tin. Hooks into the render call, allowing you to render shapes, billboards or whatever you need.

Network would be a more ethereal class. You'd build behavior fields to hold data that needs to get passed back and forth easily to the client for whatever reason, and this behavior will make sure it gets ghosted over for usage. This could be good for gameplay that necessitates the player HUD being aware of player/enemy positions, etc. This has a less rigidly defined usage, but could be helpful.

The script behavior is also WISotT. It doesn't do any real work on the engine side outside of whatever callbacks, intending to be done with scripts. This is likely to be the most used behavior for gameplay stuff.

From there, I'm also going to have a editor integration script, so you can slam together an Actor object with whatever behaviors you need, and once it's good, you can right-click to get a pop-up in the inspector, and have a 'Save to Script' option. This would open a window to let you pick where to deposit the datablock and necessary script functions, and add all these behaviors and whatever unique field data to the onAdd. So You could build the player object for your game on the fly in the editor to test it out, and when you're happy, you can then just have the editor export it to script for use whenever you need without needing to manually build it in script.

As for release itself, I want to get this out there to the community, maybe eventually even integrated into the main branch. But for the short term, if at all possible, it'd be nice to recoup some of the time/work cost that went into it. I saw someone on the forums mention a 'Community Purchase' idea for the Vertex Color paint shader and that seems like a reasonable idea. It gets the community to pitch in, I get some re-reimbursement for the work, and we can throw it to the wolves to get it perfected through open development.
That said, I have absolutely no idea on a price or how I'd put that plan into motion. So if you guys had any input on that, I would greatly appreciate it.

And, to close, Pics or it Didn't Happen(Once I get a chance, I'll make a video, but I never had to leave the editor to do anything in the pics below - pictures linked because I didn't resize them.):

No Render Behavior
Selecting Render Behavior
Added Render Behavior, and picked shape file.

Feel free to hammer me with questions. Feedback is pretty important at this point ;)

#1
06/01/2013 (10:07 pm)
Nice! T3D could benefit greatly from this sort of component stuff. The editor integration looks kind of perfect. Though I would have named a unified Player/AIPlayer class 'actor' and named the base class 'prop', or even 'entity' if prop is too specific.
#2
06/01/2013 (11:31 pm)
Fair point.
I approached it as calling it 'actor' from my roots in Unreal, which is what the core scene object is called.
Ideally in the end, the idea being that Actor takes over Shapebase's place, and everything is diffused into behavior components and prefabbed behavior sets to achieve the same end.

In that light, calling your main object that 'acts' in the scene an Actor, and you just have different behaviors and whatnot on it does make sense(as your actor could have Control Object and AI behaviors to make them act like player objects just as easily).

Just my 2 cents on the naming convention, of course ;)
#3
06/02/2013 (12:56 am)
Me no understand... The pictures make me all warm and fuzzy inside though. :D
#4
06/02/2013 (6:37 am)
I figured a forum thread would be better for more in-depth discussion and suggestions: here
#5
06/03/2013 (4:54 pm)
This is really interesting and I would like to see what it becomes especially as a part of MIT.

I like the community purchase idea, I know I have suggested it a few times.

It could just be done through Kickstarter though you will lose 5%. Or as a forum thread and people pledge what they think they can. A set price to aim for is a must I think. Kickstarter is nice and private however, and I think this could be good and bad, people could be looking too much to get money for their work and others will contribute for free. So I think the community purchase items need to be substantial additions to the engine.
#6
06/03/2013 (8:19 pm)
@Edward
I concur. I have a lot of things I'm working on as part of working on my game, and as much of it as I can will get put out there, some are bigger than others. I agree only large, or pretty moving changes SHOULD be community purchased, but at the same time that is up to the author's discretion.
That said, I was looking at maybe doing indie gogo, since that seems to be the favored place for GG ;)
That said asking price is something I'm not sure on. It's a little weirder to figure for than, you know, like $20 a sale :P
I was thinking in the range of a few hundred dollars(3-5?) would be sufficient to offset the work being done into it and it's low enough to be reasonable for the community too, I think.
#7
06/03/2013 (8:43 pm)
Jeff, send me an email please, so we can discuss compensation without having to involve crowd funding. Adress is in my profile.
#8
06/24/2013 (4:31 am)
@Jeff:
Can you plz email Vince Gee and myself. our emails are

pyoskowitz@winterleafentertainment.com
vgee@winterleafentertainment.com

we have a few questions about this.

Thanks!