Down to the base Components
by Jeff Raab · 03/30/2014 (4:52 am) · 11 comments
Hey guys, ho-
Nope, none of that. Where are the components?
Wow, ok, right to the point. That's cool.
Short version is they're still on their way. When this whole thing started, it started riding the back of the barebones framework of what was originally pioneered in T2D, and the scaffolding of the system was brought into T3D at some point(though obviously not at all used)
While that made for a great starting point, the fact is it was never really designed to be used for components. T2D's usage of behaviors is really as far as the system was actually developed, even if there were other parts in there. Lots of it was weird, unneeded chaff, like the ability to HAVE behaviors being a component, and other weird back-referencing redundancies like that.
So a little while back I pushed to peel out a lot of that old stuff that was in there. It was pretty good work, but it seemed clear that it started as one thing, and ended as another and most of it wasn't really useful now. So I opted to simplify the chain.
(Also, for reference, I consider a Component to be a engine-side element, and a Behavior to be script-based - mainly gameplay-specific stuff)
In the component code as it is in stock, you get something like:
GameBase > SimComponent > DynamicConsoleMethodComponent > BehaviorComponent > Entity
It worked, but...wow.
So now, it's:
GameBase > BehaviorObject > Entity
Behavior object basically acts as the framework for interaction with behaviors/components, as well as the necessary script interfacing so you can use scripts on entities and behaviors.
So a lot lighter, less messy and more to the point.
The other big thing I moved towards is a much heavier focus on interfaces. I was doing some direct "find a behavior with X template" stuff before, which WORKED, but just...yech.
So now we have files that contain some standard interfaces, and each behavior does it's own thing when the interfaces are called.
So if you have an interface for...say, getting the velocity of a physics component. you'd just do:
This means instead of needing to be aware of all the types of components, we just necessitate they operate through some standard interfaces. What they do on their side is irrelevant to us.
Alright, so what's taking so long
I...huh. I figured the above explanation covered that, but hey, you're the voice in my head.
The recent time sinks come from 2 places:
a) Adding more components and behaviors I figure are pretty necessary - if I don't have the ones I need to build the demo people wanted to see, then I clearly don't have enough, and
b) The overhaul mentioned above broke some stuff.
Specifically, the collider components don't interact correctly is the current big problem. Once I figure that out, however, it's just a matter of finishing out the new components/behaviors and fixing a few things in the editor before we're there.
Wait, what about those new ones? Stop holding out on me!
Man, you're pushy.
Ok, so the current list of working, proper components is:
Rendering
Render Shape Component - renders TSShapes, like you would expect
Convex Shape Component - acts like the ConvexShape class. I plan to use this for enviornmental stuff in the demo
Physics
Simple Physics Component - Simplistic physics. Think akin to the player class or item. Affected by gravity and impulses, but nothing fancy
Animation
Animation Component - interfaces with a Render Shape Component to play animations on the shape. Controllable in script
Collision - collider issue non-withstanding
Box Collider Component - You define a box's scale and it collides. Basically your bounding box collision. Box size can be changed on the fly.
Mesh Collider Component - Takes the geometry of the owner Entity's Render Shape Component and builds poly soup collisions for it.
HitBox Collider Component - Goes through the owner Entity's Render Shape and finds any meshes with a certain prefix and generates collisions for them. This operate as hitboxes, but the prefix can be whatever you want.
Light
Spotlight Component - Lets the Entity act as a spot light
Game/Misc
State Machine Component - sets up a state machine with completely adjustable transition parameters
Camera Component - Lets the Entity act as a camera.
Zone Behavior - Lets the entity handle events like a zone. When something collides with it, it keeps a list of the offending objects.
There's also a bunch of script behaviors that aren't engine-side components for gameplay stuff.
Huh, alright, that does sound pretty cool.
Thank you.
Anything else before you stop talking to yourself?
A few cool things to mention:
I adjusted how it handles loading behaviors, so other than a script-side function call for when clients connection(important to some behaviors) all the network processing and dependencies are handled basically automagically. There's more or less no other script-side hooks.
Colliders - when they get working - should be reaaaally neat. I was talking to Dan Buckmaster about some of the cool possibilities with it.
See, the colliders have 2 things that are pretty neat about them.
The first, is they have a toggle for if they should block a colliding entity or not. If it's set to off, it'll trigger collision events, do all the relevant callbacks, but it won't stop the movement of the impactor. If it's on, it will stop the impactor.
This is important, because that lets you treat any collider-componented Entity as a trigger or zone. Because you have a wide range of collider options - not just box/polyhedron, this MASSIVELY expandes the flexibility of triggers and zones to more or less whatever shape you want them to be.
Second is something that I'm still polishing fully, but is mostly in there: Tags.
I won't lie, pretty much ripped the idea off from Unity. But that's because when implemented right, the idea is so. Very. Cool.
See, as cool as typemasks are, they REALLY suck when you're trying to do a component system. You typemask your entity as X, but the purpose of the entity changes considerably depending on what components it has.
So, we do tags.
Tags are strings that act as a descriptive label for an entity. You can have basically as many tags on an entity as you want. You could label one entity with: "AI", "Warrior", "Bad Guy", "Dumb", etc.
You can search for tags on an given entity, or look for any entity that has a given tag. This can be done in the engine as well as in script.
To give you an idea of how powerful this could be in concert with some other components, this was a setup I described to Dan:
So lets say we have an enemy AI with all their rendered shapes, and state machines and whatever.
They also have 3 collider components, a Box Collider and 3 Hitbox colliders.
The Box collider is set to collide with anything unless it's tagged as a projectile or melee weapon.
Hitbox collider 1 has it's prefix set to look for anything with 'Hitbox' in the rendered shape, and is set to collide with only things tagged as projectile or melee weapon.
Hitbox collider 2 has it's prefix set to look for anything with 'VisionCone' in the rendered shape, which ends up being 1 mesh in the shape, a cone originating from the eye bone. This is set to collide with anything, but does not block things colliding with it.
The AI is configured to catch callbacks from the second Hitbox collider. So when something collides with it, it calls back to the AI, and the AI can check the list of things that it's colliding with currently like a trigger or zone. This simulates the FOV/visibility functions AI have. It's also automagically reactive when stuff enters in. If you have the AI set to react when they see a hand grenade or dead body, the second those entities collide with the vision hitbox collider, it fires a callback when the AI is set up to catch.
As for the other 2 colliders, what those enable is you to have the box collider act as your general-purpose collisions, colliding with environment stuff, other players, etc, and leave the first hitbox collider to only react to weapon attacks. That has it's own callbacks so you can easily do locational damage gameplay and the like.
Wow, sounds spiffy. Seriously though, you're slower than my dead goldfish. Hurry up
I'm...I'm pretty sure you're supposed to flush those, not keep them as a chronological reference.
Either way, yes, It's taking a while, but I want it done right and hopefully you can see from the collider example above, when it's working and done right, you should be able to do some pretty insane stuff with it.
And this has been a (not) brief update on what the dealio is.
As always, feel free to level comments and questions at me. I'm more than glad to answer them.
Nope, none of that. Where are the components?
Wow, ok, right to the point. That's cool.
Short version is they're still on their way. When this whole thing started, it started riding the back of the barebones framework of what was originally pioneered in T2D, and the scaffolding of the system was brought into T3D at some point(though obviously not at all used)
While that made for a great starting point, the fact is it was never really designed to be used for components. T2D's usage of behaviors is really as far as the system was actually developed, even if there were other parts in there. Lots of it was weird, unneeded chaff, like the ability to HAVE behaviors being a component, and other weird back-referencing redundancies like that.
So a little while back I pushed to peel out a lot of that old stuff that was in there. It was pretty good work, but it seemed clear that it started as one thing, and ended as another and most of it wasn't really useful now. So I opted to simplify the chain.
(Also, for reference, I consider a Component to be a engine-side element, and a Behavior to be script-based - mainly gameplay-specific stuff)
In the component code as it is in stock, you get something like:
GameBase > SimComponent > DynamicConsoleMethodComponent > BehaviorComponent > Entity
It worked, but...wow.
So now, it's:
GameBase > BehaviorObject > Entity
Behavior object basically acts as the framework for interaction with behaviors/components, as well as the necessary script interfacing so you can use scripts on entities and behaviors.
So a lot lighter, less messy and more to the point.
The other big thing I moved towards is a much heavier focus on interfaces. I was doing some direct "find a behavior with X template" stuff before, which WORKED, but just...yech.
So now we have files that contain some standard interfaces, and each behavior does it's own thing when the interfaces are called.
So if you have an interface for...say, getting the velocity of a physics component. you'd just do:
mBehaviorOwner->getInterface<VelocityInterface>();And it gets the first interface of the generic 'VelocityInterface' as an example.
This means instead of needing to be aware of all the types of components, we just necessitate they operate through some standard interfaces. What they do on their side is irrelevant to us.
Alright, so what's taking so long
I...huh. I figured the above explanation covered that, but hey, you're the voice in my head.
The recent time sinks come from 2 places:
a) Adding more components and behaviors I figure are pretty necessary - if I don't have the ones I need to build the demo people wanted to see, then I clearly don't have enough, and
b) The overhaul mentioned above broke some stuff.
Specifically, the collider components don't interact correctly is the current big problem. Once I figure that out, however, it's just a matter of finishing out the new components/behaviors and fixing a few things in the editor before we're there.
Wait, what about those new ones? Stop holding out on me!
Man, you're pushy.
Ok, so the current list of working, proper components is:
Rendering
Render Shape Component - renders TSShapes, like you would expect
Convex Shape Component - acts like the ConvexShape class. I plan to use this for enviornmental stuff in the demo
Physics
Simple Physics Component - Simplistic physics. Think akin to the player class or item. Affected by gravity and impulses, but nothing fancy
Animation
Animation Component - interfaces with a Render Shape Component to play animations on the shape. Controllable in script
Collision - collider issue non-withstanding
Box Collider Component - You define a box's scale and it collides. Basically your bounding box collision. Box size can be changed on the fly.
Mesh Collider Component - Takes the geometry of the owner Entity's Render Shape Component and builds poly soup collisions for it.
HitBox Collider Component - Goes through the owner Entity's Render Shape and finds any meshes with a certain prefix and generates collisions for them. This operate as hitboxes, but the prefix can be whatever you want.
Light
Spotlight Component - Lets the Entity act as a spot light
Game/Misc
State Machine Component - sets up a state machine with completely adjustable transition parameters
Camera Component - Lets the Entity act as a camera.
Zone Behavior - Lets the entity handle events like a zone. When something collides with it, it keeps a list of the offending objects.
There's also a bunch of script behaviors that aren't engine-side components for gameplay stuff.
Huh, alright, that does sound pretty cool.
Thank you.
Anything else before you stop talking to yourself?
A few cool things to mention:
I adjusted how it handles loading behaviors, so other than a script-side function call for when clients connection(important to some behaviors) all the network processing and dependencies are handled basically automagically. There's more or less no other script-side hooks.
Colliders - when they get working - should be reaaaally neat. I was talking to Dan Buckmaster about some of the cool possibilities with it.
See, the colliders have 2 things that are pretty neat about them.
The first, is they have a toggle for if they should block a colliding entity or not. If it's set to off, it'll trigger collision events, do all the relevant callbacks, but it won't stop the movement of the impactor. If it's on, it will stop the impactor.
This is important, because that lets you treat any collider-componented Entity as a trigger or zone. Because you have a wide range of collider options - not just box/polyhedron, this MASSIVELY expandes the flexibility of triggers and zones to more or less whatever shape you want them to be.
Second is something that I'm still polishing fully, but is mostly in there: Tags.
I won't lie, pretty much ripped the idea off from Unity. But that's because when implemented right, the idea is so. Very. Cool.
See, as cool as typemasks are, they REALLY suck when you're trying to do a component system. You typemask your entity as X, but the purpose of the entity changes considerably depending on what components it has.
So, we do tags.
Tags are strings that act as a descriptive label for an entity. You can have basically as many tags on an entity as you want. You could label one entity with: "AI", "Warrior", "Bad Guy", "Dumb", etc.
You can search for tags on an given entity, or look for any entity that has a given tag. This can be done in the engine as well as in script.
To give you an idea of how powerful this could be in concert with some other components, this was a setup I described to Dan:
So lets say we have an enemy AI with all their rendered shapes, and state machines and whatever.
They also have 3 collider components, a Box Collider and 3 Hitbox colliders.
The Box collider is set to collide with anything unless it's tagged as a projectile or melee weapon.
Hitbox collider 1 has it's prefix set to look for anything with 'Hitbox' in the rendered shape, and is set to collide with only things tagged as projectile or melee weapon.
Hitbox collider 2 has it's prefix set to look for anything with 'VisionCone' in the rendered shape, which ends up being 1 mesh in the shape, a cone originating from the eye bone. This is set to collide with anything, but does not block things colliding with it.
The AI is configured to catch callbacks from the second Hitbox collider. So when something collides with it, it calls back to the AI, and the AI can check the list of things that it's colliding with currently like a trigger or zone. This simulates the FOV/visibility functions AI have. It's also automagically reactive when stuff enters in. If you have the AI set to react when they see a hand grenade or dead body, the second those entities collide with the vision hitbox collider, it fires a callback when the AI is set up to catch.
As for the other 2 colliders, what those enable is you to have the box collider act as your general-purpose collisions, colliding with environment stuff, other players, etc, and leave the first hitbox collider to only react to weapon attacks. That has it's own callbacks so you can easily do locational damage gameplay and the like.
Wow, sounds spiffy. Seriously though, you're slower than my dead goldfish. Hurry up
I'm...I'm pretty sure you're supposed to flush those, not keep them as a chronological reference.
Either way, yes, It's taking a while, but I want it done right and hopefully you can see from the collider example above, when it's working and done right, you should be able to do some pretty insane stuff with it.
And this has been a (not) brief update on what the dealio is.
As always, feel free to level comments and questions at me. I'm more than glad to answer them.
About the author
#2
03/30/2014 (5:42 am)
Sure, I don't mind :D
#3
03/30/2014 (5:55 am)
Interesting stuff. Since you used T2D as an original source for your work, is there anything in the improvements/revisions you made now that might benefit flowing back into the T2D code?
#4
In short, in my perfect world, we wouldn't need to separate the engines out at that point.
That said, not exactly feasible, and since in the end it's currently massively overhauled compared to what it started as, there wouldn't be any simple patchfixes.
If T2D wanted components though, that could be rolled in easily enough.
03/30/2014 (6:20 am)
Well, my grand goal(not that it's likely to happen) would be pull out all gameplay classes, replace with components, and have components/behaviors to replicate T2D's stuff as well.In short, in my perfect world, we wouldn't need to separate the engines out at that point.
That said, not exactly feasible, and since in the end it's currently massively overhauled compared to what it started as, there wouldn't be any simple patchfixes.
If T2D wanted components though, that could be rolled in easily enough.
#5
Also, what's the difference between BehaviorObject and Entity?
Oh, that reminds me of why I like Component over Behaviour - because it's spelled the same way on both sides of the pond :P.
03/30/2014 (4:27 pm)
Cool stuff. Oh and I really like the template solution for getting different components! Have you been able to make the template type inference work in any situations, so you don't have to write the template instance? I like it when type inference works.Also, what's the difference between BehaviorObject and Entity?
Oh, that reminds me of why I like Component over Behaviour - because it's spelled the same way on both sides of the pond :P.
#6
<CraigFromSouthPark.jpg>
...I would be so happy.
03/31/2014 (8:25 pm)
If this means I can attach anything to anything without having to do anything hacky...<CraigFromSouthPark.jpg>
...I would be so happy.
#7
I'm not 100% happy with the interface stuff, but it's the best approach I could come up with offhand. Basic idea being you have an interface in a generic, easy-to-access file like, say, "/Physics/physicsInterfaces.h"
The behaviors that actually use and implement the above mentioned velocityInterface would inherit off it with their own so that you can do the behavior-specific actions involved(this means each behavior is free to have it's own 'getVelocity' function or whatever, based off of how it handles things since it may change.
Then you register the interface with the behavior owner when it's added to the owner.
So when you do mBehaviorOwner->getInterface<VelocityInterface>() it finds anything that could come from our generic velocityInterface and have a one-size-fits-all access without having to type the behaviors themselves.
Lemme know if that explains that well enough.
BehaviorObject is pretty much the 'heavy' class with the behavior/component logic. Entity is has more gameplay focused stuff, such as handling mounting and the like.
In terms of gameplay and scripts, you'd use Entity, but you could easily roll your own specialized component object by inheriting off BehaviorObject.
As for Behavior/our and Component. Well maybe if you guys would stop cramming extra letters everywhere... ;)
@Chris
You mean like:
Or
That kinda attach anything to anything?
03/31/2014 (10:36 pm)
@DanI'm not 100% happy with the interface stuff, but it's the best approach I could come up with offhand. Basic idea being you have an interface in a generic, easy-to-access file like, say, "/Physics/physicsInterfaces.h"
The behaviors that actually use and implement the above mentioned velocityInterface would inherit off it with their own so that you can do the behavior-specific actions involved(this means each behavior is free to have it's own 'getVelocity' function or whatever, based off of how it handles things since it may change.
Then you register the interface with the behavior owner when it's added to the owner.
So when you do mBehaviorOwner->getInterface<VelocityInterface>() it finds anything that could come from our generic velocityInterface and have a one-size-fits-all access without having to type the behaviors themselves.
Lemme know if that explains that well enough.
BehaviorObject is pretty much the 'heavy' class with the behavior/component logic. Entity is has more gameplay focused stuff, such as handling mounting and the like.
In terms of gameplay and scripts, you'd use Entity, but you could easily roll your own specialized component object by inheriting off BehaviorObject.
As for Behavior/our and Component. Well maybe if you guys would stop cramming extra letters everywhere... ;)
@Chris
You mean like:
new Entity(ThingOne)
{
Position = "10 23 1";
new Entity(ThingTwo)
{
position = "0 0 1";
};
};Or
ThingOne.add(ThingThree);
That kinda attach anything to anything?
#8
04/01/2014 (4:44 am)
@Jeff: Like attach particleEmitters to a vehicle and stuff.
#9
You could either attach a particle emitter component to your vehicle entity and it'd act AS a particle emitter.
Or you could take what I provided above to easily attach an entity with a particle emitter component to a entity that acts as a vehicle.
It also supports arbitrary offsets and in the event of the parent entity having a render shape component, whatever nodes in the shape as well.
so:
And that'll let you automagically spawn a car entity with the emitter entity pre-attached.
If you wanted to mount the particle emitter entity after the fact(using the same names from above):
04/01/2014 (5:22 am)
Oh. Yeah.You could either attach a particle emitter component to your vehicle entity and it'd act AS a particle emitter.
Or you could take what I provided above to easily attach an entity with a particle emitter component to a entity that acts as a vehicle.
It also supports arbitrary offsets and in the event of the parent entity having a render shape component, whatever nodes in the shape as well.
so:
new Entity(Car)
{
position = "0 0 0";
new CarComponent()
{
//car component stuff here
};
new Entity(ParticleEffect)
{
position = "0 0 0";
mountNode = "exhaustNode";
new PartileEmitterComponent()
{
//particle stuff
};
};
};And that'll let you automagically spawn a car entity with the emitter entity pre-attached.
If you wanted to mount the particle emitter entity after the fact(using the same names from above):
%shapeComponent = Car.getBehavior("RenderShape");
%shapeComponent.mountObject(ParticleEffect, "exhaustNode");
#10
Furthermore: https://www.youtube.com/watch?v=VoW9czgQBqE
04/01/2014 (4:18 pm)
Nice! Now I take it that vanilla Torque3D still requires you hack something together somehow, like hack up the engine code or use an empty weapon to use it's particle emitter or something dumb like that, right? This makes things not only easier, but better on a fundamental level!Furthermore: https://www.youtube.com/watch?v=VoW9czgQBqE
#11
04/03/2014 (6:46 pm)
Also, instead of doing something like a crowdfunding campaign with a large goal, you did something like Patreon? 
Torque Owner Kory Imaginism
innovative imaginations
Is it cool if I send you a email, I wanted to hear more about the AI ;)