Game Development Community

dev|Pro Game Development Curriculum

Component System, what's up?

by Jeff Raab · 12/01/2013 (11:26 pm) · 18 comments

'Lo everyone.

I've had a inquiry or two after the Component System's progress and when the next campaign attempt will take place.
So, lets go over that in a small progressive update!

So what's been happening?
Been working on features, additional behaviors/components as well as fixing and polish.
Some features are a bigger deal than others.

For example, the implementation has always had dependency systems in place, where a behavior can require certain other behaviors on the Entity before it'll enable. This was implemented in script, and while it worked perfectly fine, it's going to be cleaner and more robust to implement it at the engine level, especially as dependency functionality isn't something that really needs so much tweaking action.
Likewise, I'm going to implement the ability for certain fields to have dependencies. So a section of the behaviors' fields in the editor interface are disabled until the dependency is met, but other parts can still work. This is good for complex, multi-faceted behaviors like a Player Controller behavior or something.

A pretty major one that's been put in is Entity drag-mounting and nested creation. If you're familiar with how GUI elements work, where you can create them nested, like:

new Thing(Foo)
{
    new Thing(Bar)
    {
    };
};

And have it not only create both objects, but then mount Bar to Foo. This has been implemented into Entities. It also works with the World Editor, so you can click an entity in the Inspector tree and drag-n-drop onto another entity, and it'll mount the dragged Entity to the target Entity, retaining the current offsets.

What's neat is the child Entities aren't "hard mounted". They can be moved around, rotated, etc and it will adjust it's offsets respective of the parent.

This makes editing complicated objects really nice. Say you're setting up a Player object and have the actual Player done and positioned in the level as you want, and need to set up the camera in a side-scroller perspective.
Before, you would need to script in behavior to spawn the camera, mount it to the player object with specific offsets, and have to keep going back in and out to adjust the offsets in script until it was perfect.

Here, you would create the camera entity, move it into position so it looks good respective to the player object, and then drag-n-drop the Camera to the Player entity, mounting it. If you later find you need it's offset changed, or want to do one of those cool side scrollers with a dynamic zoom camera or whatever, then you'd just adjust the Camera's position and it moves, but always as relative to the parent object's position.

Ok, cool, but that doesn't matter if we're spawning stuff in from scripts like for a shooter game, right?
Normally, sure, but that brings me to my next feature being worked on:

Prefab integration.
Being able to nest creation of objects and have them just...WORK, is exceptionally useful when we want to rig up our fancy object like the Player with the Camera from the above example, and then actually DO stuff with it.

Imagine working on a Third Person shooter. You've got your player object with all the parts, and have just mounted the Camera in the perfect place and it feels good to control in the test level. But now you need to be able to replicate it for all the players that'll join the game as it goes, instead of having 1 player in the map a la single player.

So, we do what we've always done when we want to replicate complex groupings of objects. We prefab them.
You would go in, prefab the Player object(which grabs the camera as it's part of the Player Entity's heirarchy) and saves the setup out to a prefab file.
This keeps all the custom settings for the various behaviors on all the objects involved(such as physics settings, input settings, etc) so when you spawn the prefab, it's a fully functional iteration of your test build.
At that point, all you'd do is set the correct client owner for the ControlObject, Camera and Input behaviors so the right client controls it and it'd behave exactly like it does now with the player class and all the support spawn scripts.

This isn't finished yet, but it's chugging along pretty nicely. Other than a few hiccups, it builds the prefab of the Entity heirarchy, behaviors are correctly saved, and spawning the prefab replicates the entire heirarchy again. For the most part it's pretty good, but there's some bugs before it's perfect.

Anything else?
Other than a lot of bugfixes, and trying to polish where I can, I'm also working on building a pretty sizable library of behaviors out of the gate.

Ones that exist in some state now, but not necessarily perfect or even properly functional:

ControlObject behavior - tells the GameConnection you're controlling this Entity
Camera behavior - lets the Entity act as a camera
Render Shape behavior - lets it render a shape instance
Animation Controller behavior - If the Entity has a Render Shape behavior, we can animate it
Ambient Animation behavior - a animation controller behavior that lets you define one animation and it'll just
play that, on a loop. Good for small little flavor animations on static objects
Simple Physics behavior - replicates the player class' phyiscs. While it doesn't behave like a rigid body proper, it's
exceptionally difficult to get it to penetrate through other objects in the scene, making
it good for player objects
Box Collider behavior - lets you define a box that acts as a collider. Not dissimilar from the bounding box collision mode
on TSStatics
FPS Controls behavior - gives you WASD type controls with mouse input. Requires a physics behavior.
Spectator Controls behavior - gives you WASD/Mouse input controls, but doesn't require any kind of physics behavior. As
such, you can fly around and go anywhere.
Item Rotate behavior - simulates the Item class' rotation effect.
State Machine behavior - allows for a fairly lightweight state machine that is customizable.
Spot Light behavior - acts as a spotlight light object

And where are ones that are planned, but not yet implemented:

Render Sprite behavior - renders a sprite object, which can be constrained to certain axies like a billboard if you want.
Point and Sun light types
Sound Emitter behavior - lets the Entity act as a sound emitter
Particle emitter behavior - lets the Entity function as a particle emitter
Rigid Body Physics behavior - gives the Entity full rigid body physics. This is good for dynamic objects or vehicles.

I also hope to get a few other Collider types, like capsule, poly soup, or collision meshes.
In additon to that, I've got ideas for a plethora of other behaviors, but they're lower priority. If I get my way, the above mentioned ones will all be included at release.

Oh, speaking of the release...
Right.
Given the encroaching holiday season, and needing the bit of additional time to finish what I want to get in this as well as put together a proper demonstration, I'm thinking of attempting the community purchase campaign again early January. That way people can have recovered from the holiday insanity, while I get time to wrap up the target goals.
I'll have more details on this as it gets closer, but that's the goal.

Feel free to ask questions or want more details, I'm more than happy to clarify whatever ;)

-Jeff

#1
12/02/2013 (4:52 am)
Great to hear - I can't wait to get my hands on this!
#2
12/02/2013 (12:54 pm)
Sounds great jeff,

say if one would want to attach a camera behaviour -
would this be limited by the current view or could it be attached as an extra camera to a objects or a texture?

I do get that the functionality is not solid yet but still am just curious
as i feel a bit left in teh dark when it comes to those features.

What can be done with it and what cant be done?
#3
12/02/2013 (1:39 pm)
With the camera behavior, it turns the Entity that has the camera behavior into a camera - as in, similar to the current camera class.

However, only one camera can(currently, due to GameConnection code) be active at a time. I plan on including some helper functions into it for fast swapping between camera entities, but the basic idea is similar to the current camera object, just more flexible.

If you wanted multiple cameras, like resident evil 1, you would go in, set the cameras up throughout the map and set triggers down in the map that have code that basically says 'the client uses this camera now'.

So each camera entity would get placed wherever your design calls for it, and just sits there minding it's own business until it's told to activate. When it activates, it tells the client's GameConnection it's the camera object, and this in turn changes the player's view to that camera Entity.

The camera entities can then have additional behaviors, such as a behavior to track the player object, so it'll stay in view. Then when you hit another trigger, it'll swap to the next camera, etc.

For your standard shooter fare, FPS/TPS, you could go about it one of two ways.
You could prefab the player object like I was talking about above so that it has 2 camera entities, one in the third person position, and one in the first person position, and just swap between them like in the above RE example.
Or you could just mount it from the player shape's camera node to the eye node and vis versa - similar to the current Player class's arrangement.

Also, I haven't focused on render to texture with separate camera entities, but it's something I've kept in the back of my mind as that'll be reaaaaally useful for a lot of stuff. It's on my todo list.

Let me know if that gives you a better idea of how the camera behavior works.
#4
12/02/2013 (1:43 pm)
ic thanks for taking the time to explain further,
lookin forward to january and the demonstration :)
#5
12/02/2013 (3:49 pm)
Great was wondering when this would be back!
#6
12/02/2013 (4:14 pm)
One thing that almost always seems to come up when I'm briefing a new artist is mounting, and what does and doesn't work with that. Thoughts?
#7
12/02/2013 (4:28 pm)
@Az

Mounting is still a imperfect at the moment, as a 'proper' solution is pretty hard.

The idea would be something where you can just drop your object to be mounted not just on the target, but be able to specificly mount to nodes that are on it's shape file or whatever.

The problem is, the nodes in the shape file on the RenderShapeBehavior aren't objects, so they're not exposed to script or other sub-systems. There's no easy way to just drag-n-drop on the shape's eye node in a list or whatnot.

The hard part of getting that working isn't the drag-n-drop stuff, as you could encode workarounds that interpret it to behave correctly. The hard part is saving/loading the correct mounting info.

In my above example,

new Thing(Foo)
{
    new Thing(Bar)
    {
    };
};

It's very clear and concise. You create and mount Bar to Foo. However, when you want to create Bar and mount it to some data that Foo has, but isn't a literal object, it gets very complicated.

I've been mulling over how to get it working where you can just mount to nodes of shape behaviors and whatnot as easily as you can mount entities to entities, but it's tricky. The best approach I have is non-permanent objects.

You'd do something like:
new Thing(Foo)
{
   new RenderShapeBehavior(ShapeBhvr)
   {
       shapeFile = "bleh";
     
       new ShapeNode(Eye)
       {
           new Thing(Bar);
       };
   };
};

The behavior object and shapeNode object would be created long enough to properly interpret mounting hierarchies and the like, and then are deleted and their simID is released so it doesn't take up space in the sim dictionary.

It's more convoluted, but it wouldn't be used like that much outside of saving to prefabs and mission files, so it should work ok.

For now, you'd mount things similar to how GUI stuff is done, like mentioned before.
Either the nested object approach, or doing

new Thing(Foo);
new Thing(Bar);

Foo.add(Bar);

Then adjusting the offset by just setting Bar's transform, which is relative from Foo.
#8
12/02/2013 (5:20 pm)
This is sounding very impressive and interesting to be able to open up T3D to easily create anytype of game and will be very useful to get T3D out of the mind set its FPS only.
#9
12/02/2013 (10:07 pm)
Jeff - how does, for example, the animation controller find and talk to the shape component? It seems like a similar method could be used to get into about shape nodes for mounting purposes.
#10
12/02/2013 (10:38 pm)
@Dan

In the engine, it's a pretty simple Entity->getBehavior("RenderShapeBehavior") which returns the behavior instance. Then you can just get the shapeInstance through a regular getShape() function call.

Like I'd mentioned, the hard part is saving/storing the mounting to a node.

Torque doesn't let you do function calls in the nested creation statements, so the nested creation has to do all the work in setting the mounting and hierarchy.

While this doesn't matter so much when you're doing creation via scripts, it makes it really hard to save that info out to the mission file or a prefab, which drastically limits it's practicality.
#11
12/03/2013 (12:51 am)
@Jeff,
I have set aside some money for funding this. Let us know if ur trying another fund raiser or if you just want to do the buyout via paypal or something. I don't care. This is awesome stuff.
#12
12/03/2013 (1:51 am)
I have some ideas for that, basically doing the same thing I did in my TGE code I shared with you. The mountee stores the node it should be mounted to, and finds the node in the parent when it needs to update its transform. Doing repeated getBehavior calls might be bad for performance though - some sort of caching may have to happen.

Anyway, when the code's out I'll be digging right into it ;).

hey, do you reckon we could overload TorqueScript's -> operator, currently used to find named GUI sub-objects, to find components of an entity? So in script that'd look like %entity->RenderShapeBehavior.
#13
12/03/2013 (10:46 am)
@Dan
When you mentioned the storing the node and stuff before, I was thinking a hard variable in the Entity class, which just adds bulk. But in retrospect, I could easily have a dynamic variable for that.

When the entity is loaded it gets that, does the mounting to the specific node(if available) and then we just purge the dynamic variable from the entity so it's out of the way. That would probably work rather well, actually.

As for overloading the pointer-type operator, I think that's a pretty awesome idea. Similar to the internalName functionality of the GUI stuff. I'll look into that, that'd be a good, quick, shorthand for scripts.
#14
12/03/2013 (12:08 pm)
@Jeff Raab
even if this comes a bit early and at the same time it might be a shock for a couple of ppl

However there is currently work going on that is going to put the Torque3D Codebase to better use
and at the same time it will gain much more publicity

Now the thing is i believe we could help in your next kickstarter/purchase campaign

simply by doing PR and or even gettin you in officialy
and this way we could path the way for future contributions to the Engine
by Kickstarting or Community purchase campaigns for
the Enhancements and more

most important the income of the purchase campaigns would go to the contributor and this would ensure that that the Engine stays OpenSrc
along with a growth of Contributors.

At the end evryone would benefit,
note this would no longer be Torque3D
as The Engine am talking about is going to be named GREED and its going to be its own thing
but unlike other T3D MIT Derivates - GREED will stay under the MIT License
to ensure that the "Gift we received by GrageGames" stays a Open Source Engine.

However at the same time ppl who wish can use it in their Engine aswell
so this truly might be the best solution.

Anyways we all look forward and if you have interest into my suggested approach
my e-mail is in my profile
#15
12/03/2013 (1:48 pm)
Or a MountToNode component that holds the logic of getting the node transform, and setting the entity transform based on that. Not sure if that would be friendlier/more performant than looking up a dynamic variable.
#16
12/03/2013 (6:21 pm)
@J0linar
If the community purchase campaign succeeds, then this will be released under MIT(ideally gets integrated into T3D core, but that'd be down the line) so you would be free to put it into GREED, while others can keep with regular T3D if they wish.
So if you help with the community purchase, everyone benefits.

@Dan
That was the current approach, but I think that the dynamic field that's removed after it's used is going to be a lot lighter weight than the additional SimObjects for the instances of the mountToNode component.
#17
12/03/2013 (6:47 pm)
Jeff i do get that we can simply take it if its released
what i suggested was to go a different route.

Not labeling it as a torque3D Enhancement
but instead going thru greed to ensure a maximum of ppl gets reached

www.moddb.com/engines/greed-tech-mit
is currently ranked 15 in the charts
and that without even showcasing

my point is the wave of stuff that is going to come
will be direct PR.
Well Greed is not pushing Torque3D away/ its simply a ressurection
and even our website reflects back to the Engines History

Anyways offer stays, you would be listed as a Contributor
and your Component System would receive PR and support - that is something
that Torque3D cant and neither GarageGames as they just dropped the ball.
I will stop here if you didnt got what this would mean for your product then my words where pointless.
#18
12/03/2013 (9:14 pm)
"Anyways offer stays, you would be listed as a Contributor"

i think he better spend his valuable time on his job and t3d.
someone else (any programmer,me or anyone) can port that work to greed .
and u can give credit both.

looking forward for it.