What is a chair? Defining objects in video games

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
User avatar
cyboryxmen
Posts: 190
Joined: November 14th, 2014, 2:03 am

What is a chair? Defining objects in video games

Post by cyboryxmen » January 8th, 2019, 7:34 am

What is a chair?

If anyone asks you this in real life, you’ll just point to this and say ”This is a chair.”

Image

In video games however, the definition of a chair is not that straightforward.

A chair is something that you can see. It is a bunch of shapes that are folded and glued together to create the graphic of a chair you see here.

Image

A chair is something you can physically interact with. You can push it and the chair would move according to Newtonian laws of physics. If you drop a chair off a cliff, the chair would go downwards due to gravity.

Image

A chair is something that you can collide into. Periodically, the game would check if anything is colliding with the chair and if it finds anything, it’ll try to respond appropriately.

Image

A chair is an obstacle. The AI in the game can detect if there is a chair in front of it and if it finds one, it’ll try to move around it.

Image

A chair is a destructible. If it takes too much damage, the chair would be destroyed.

Chairs in video games can be all of these and more.

To make things more perplexing, a chair can "transform" into other kinds of chairs when certain conditions are met. A chair can be in two states: A chair that’s moving and a chair at rest. A chair that’s moving needs to have its position updated along with the map that records where objects are in the world. Most chairs however are just going to stay still throughout the game. The only chairs that will be moving are the ones that the player is throwing around and even then, they’ll eventually settle down and be at rest again. Once it does, it'll get transformed from a moving chair into a static one. This will allow you to only process the moving chairs and leave the static chairs alone. These transformations, while optimal, can make it hard to think about your chairs as a single kind of entity.

Video games also like to define different kinds of objects in a similar way. A table can be defined the same way a chair is defined. It’s something that you can see, something you can physically move, something that you check collisions with, something the AI needs to walk around and something that you can destroy. Trying to write separate code for chairs and tables is a waste of development hours. Instead of having a separate PhysicsChair and a PhysicsTable class, you can use a PhysicsObject class and use that class to define both objects. This however really blurs the line between the different types of objects as we think about them.

On top of that, different chairs in the game are not really individuals of their own. Video games like to reuse the same models over and over. It's common for a game to use the exact same chair model for all the chairs that they have. Most players are not going to care about this that much and it's a good way to reduce memory usage. Having parts of the chair be shared among all other chair instances really puts the individuality of each chair into question.

It seems that, as far as the game's code is concerned, there is no chair. Few games would ever write dedicated code to define a chair in their world. Instead of asking yourself what a chair is, ask yourself how the chair would behave in the game. A chair can be pushed around with physics. A chair acts as an obstacle to the AI. A chair will be destroyed if it takes enough damage. Based on this, separate your game into a set of unique tasks that takes in your chair's information alongside the information of other similarly behaved objects and returns an output. That output is then used to feed other tasks until eventually, you have an image on the screen.

For example, have a task that takes an array of objects in the game and checks collisions with them. It'll output an array of collisions which is then passed on to the physics task. The physics task would also take the same array of objects and moves those objects based on their physical value and the collisions that took place. After moving the objects appropriately, it sends the positions of those objects to the rendering task which then renders them onto the screen. Using this structure, you can create a great game about destroying sentient furniture!

If you want to add new objects to the game, and they behave the same way as the chair, try to batch them together with the chairs where they will be funnelled through the same set of tasks.

Say that you want to add a missile to the game. The missile behaves like the chair in every way(in the game; not in real life. Please don't try to sit on a missile.) but it doesn't move according to physics. Instead, it just tracks its target and moves directly towards it until it eventually collides with it. Simulating something like that would require creating a new set of tasks in the task chain. The missile however has the same collision checking behaviour as the chair. As a result, it'll also be batched together with them at the collision check stage making it easier to check collisions with the missiles and every other object in the game.

Overall, this is just a better way to think about implementing objects in video games. I've seen so many people start off by creating a chair class only to be completely stuck on what to do next. If you think in terms of the logic of the game and how chairs would behave in that logic, it becomes more clear on how you should implement it. Next up, I'll explain how to implement a game like this with multithreading by using Task Based Programming.
Last edited by cyboryxmen on January 8th, 2019, 11:53 am, edited 1 time in total.
Zekilk

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: What is a chair? Defining objects in video games

Post by albinopapa » January 8th, 2019, 10:41 am

Stop, you are displeasing the OOP gods!!!

No, just kidding, this is great advice actually. It's has more of a data driven design feel, though, you don't necessarily have to give up on objects.

I'm guilty of doing this, not really because of OOP, but because it allows me to specify that this class loads it's on chair sprite/mesh, dimensions and other properties. So instead of having a GameObject instance named chair that I then have to feed it's properties to it in the Game class for instance, I just create a Chair object and all initialization is done during instantiation of the Game or Level or Map class. This makes the constructors of those classes much cleaner. However, I realize that it would be much better to have this information probably loaded in from file instead of hard coded.

I for one wish I would get over OOP as I currently see it and embrace the DOD ( Data Oriented Design ) approach already.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
cyboryxmen
Posts: 190
Joined: November 14th, 2014, 2:03 am

Re: What is a chair? Defining objects in video games

Post by cyboryxmen » January 8th, 2019, 12:08 pm

Data Oriented Design was always just a vague collection of ideas that people have been using in the game industry for years even before the term was coined. Personally, I would have just called it DWTFYNTDTGTJDOP.
Do
Whatever
The
Fuck
You
Need
To
Do
To
Get
The
Job
Done
Oriented
Programming

Guess that'll be too much of a mouthful huh?

Also, do yourself a favour and stay away from ECS as it isn't that much better of way to think about your code.
Zekilk

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: What is a chair? Defining objects in video games

Post by albinopapa » January 8th, 2019, 6:24 pm

Also, do yourself a favour and stay away from ECS as it isn't that much better of way to think about your code.
Thanks for the tip, I never could figure out how it worked anyway.

My naive approach to ECS would have been way slower than any other naive OOP approach I would have come up with.

My approach was:

Entity: Entity class storing a vector of components
Component: Attributes defining an Entity; Health, Position, Velocity, Damange, etc
System: Logic for handling interaction between entities, MoveSystem updates position, HealthSystem takes Damage reduces Health

How to find an Entity, linear search through current System's Entity vector.
How to find a component, linear search through current Entity's component vector.

Surely this isn't the best approach to ECS, this is why I say I haven't figured it out or would be worse than any straight forward OOP approach I can think of.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
cyboryxmen
Posts: 190
Joined: November 14th, 2014, 2:03 am

Re: What is a chair? Defining objects in video games

Post by cyboryxmen » January 8th, 2019, 7:37 pm

The way I would describe ECS is that it's basically OOP but with no concept of object types.

An entity is pretty much an object; an object in the form of an index instead of a class but an object nonetheless. Not only that, it's also an object with no easily determinable type. An entity can be any type of object in the game. The only way to find out the "type" of the entity is to loop through its list of components and find the component(s) that you need. In an OOP implementation, I would keep all the chairs in a single array. That way, I know that everything in that array is a chair at compile time saving me from the runtime checks.

The components are just as bad. The idea is that you keep all data of the same kind in a single array regardless of the object type the data belongs to. The position data of both chairs and missiles would be mixed up into one array and there is no quick way to discern which is which. The idea behind this is that you can loop through data of the same type and process them all in one batch. This seems like a great way to go about things until you realise that the chair's position data is updated in terms of physics and the missile's position data is updated in terms of the missile's unique movement pattern. Just because two pieces of data are the same type, that doesn't mean that they'll be processed the same way.

You could make it such that the chair's position and the missile's position are all different types entirely. This just makes it harder for you to batch the chair and missile positions together when it comes time to check collisions with both of them. In video games, things are often batched together then separated apart based on what you are currently doing. It's the same problem that I have highlighted before. A component isn't just "a component". It transforms from state to state based on what you want to do with it currently. Rendering is another good example. The positions of objects that all share the same model, chairs in motion and static chairs, are batched together in a single array then rendered all in one go by the GPU.

Finally, you have the system. A system "performs global actions on every Entity that possesses a Component of the same aspect as that System". Of course, implementation wise, most systems don't just access a single kind of component. A system can access multiple components at once and multiple systems could make changes to the same exact components. This unrestricted global access that the systems possess make it incredibly hard to keep track of who is in charge of what. Private variables may be a pain to handle but it does prevent madness like these from happening.

You could fix the typing issue by tagging entities and components with a type. That's still unnecessary bookkeeping and runtime checks that you can avoid. I already know the type of object I'm working with at compile time in an OOP approach.

Overall, I find ECS to be a troublesome mess that's hard to figure out and not that much more efficient than OOP.
Zekilk

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: What is a chair? Defining objects in video games

Post by albinopapa » January 9th, 2019, 6:17 am

Good description, thanks.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: What is a chair? Defining objects in video games

Post by chili » January 11th, 2019, 12:59 am

This is pretty good advice. Not everything needs it own specific class. This becomes more and more true as you move away from specifying stuff in source code and instead specify it using descriptor files and scripts loaded at runtime.

This DOD fad annoys me. Not because there isn't any merit in the ideas, but just due to the zealotry of people who have watched a couple of Mike's vids. It's not like this is a new idea, SoA has existed for decades. But people who decry that "OOP is Dead" and proceed to setup a bunch of strawmen to "prove" their point are distasteful creatures.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: What is a chair? Defining objects in video games

Post by albinopapa » January 11th, 2019, 3:53 am

I'm starting to wonder if some sort of packet based design would be a better approach. The idea of DoD from what I can tell isn't just SoA, but focusing on data and it's transformation from raw input to useful output. SoA is just a way to structure your data and probably causes you to think more about the data rather than the objects the data represents, but isn't the end goal.

I would say DOD would be better represented as a pipeline or call graph, where data transformation is the key element or main goal of the design pattern.

That's my two cents anyway.

Man, as far as scripting goes, I tried integrating Lua into a project a while back and failed to grasp it's interface. It wasn't until I installed SOL2 I think it was that I was able to make it work. I think I'd end up making my own scripting language, I hate having to learn someone else's library.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply