3 ms·
Inheritance is very useful in domains like game engines, where it is very common to have a base object such as "Node" that has some properties that every object
by jeremyjh 3y ago
Inheritance is very useful in domains like game engines, where it is very common to have a base object such as "Node" that has some properties that every object in the scene graph must have, which all share the same implementation. For example they should all have a parent property and a collection of children, and ways to modify those properties. They'll also share methods such as "render" which probably must be overridden in every subclass. Its not impossible to solve this with interfaces and composition but those solutions are sub-optimal.
An example you might be more familiar with is the DOM of a web browser - every element has some basic properties and methods that all share an implementation.
- yellowapple 3y ago> Its not impossible to solve this with interfaces and composition but those solutions are sub-optimal. The growing popularity of ECS and data-oriented design in game engines suggests otherwise: keeping components separate from entities enables both performance enhancements and separations of concerns that are much more difficult to achieve with the traditional inheritance-based approach. To illustrate a bit: > it is very common to have a base object such as "Node" that has some properties that every object in the scene graph must have, which all share the same implementation. For example they should all have a parent property and a collection of children, and ways to modify those properties. You don't need subclasses for that; you just need a table of entity IDs (where both the things to render and the scene itself are entities) and parent IDs, which you can then recursively walk to get the entities you want to render: WITH RECURSIVE entity_children AS ( SELECT id, parent FROM entities UNION ALL SELECT ec.id, ec.parent FROM entity_children AS ec JOIN entities AS e ON ec.id = e.parent ) INSERT INTO scene_entities (scene, entity) SELECT $scene_entity_id, id FROM entity_children WHERE parent = $scene_entity_id; (Obviously you probably won't actually be running SQL queries in a game engine's rendering loop; this is just to illustrate the logic.) Once you've got that list... > They'll also share methods such as "render" which probably must be overridden in every subclass. You don't need subclasses for that; you just need a table of entity IDs and things to render, which you can then query and send to the GPU: INSERT INTO some_buffer_in_GPU_memory (entity, mesh, texture, position) SELECT se.entity, em.mesh, et.texture, ep.position FROM scene_entities AS se JOIN entity_meshes AS em ON se.entity = em.entity JOIN entity_textures AS et ON se.entity = et.entity JOIN entity_positions AS ep ON se.entity = ep.entity WHERE se.scene = $scene_entity_id; (Again: you probably ain't actually using SQL for this; this is also overly simplified, since most modern game engines use all sorts of other stuff besides a mesh, texture, and position when rendering something. Note also that "em.mesh", "et.texture", and "ep.position" need not be actual meshes/textures/positions, but could instead be indices into buffers already on the GPU.) The key advantage in both of these cases is that the parent/child data and the render data can live where they make the most sense, and can be processed by independently-running systems with minimal contention. This is critical for processing game logic in parallel - something which the game industry is learning the hard way with legacy engines that can't fully exploit multicore hardware.
- feoren 3y agoQuite the opposite: game engines are one of the few places where the sub-optimality and fundamental problems with object inheritance became so overwhelming that people starting abandoning their deeply ingrained CS 101 models of Dog : Animal and invented Entity-Component-System architecture, which at its extreme uses no object inheritance at all and is a deeply "relational" model. Game engines which don't do this were either mostly developed before ECS was invented/popularized (Unreal) or are specifically targeting beginners who have little more than a CS 101 understanding of OO programming (and also following Unreal's lead). DOM elements are a better example, but just because that's how they are done doesn't mean that's how they should be done. Does a <script> element really need a "focus()" method? It has one. Does a <br> element need an "innerHTML" property? It has one. Does a <head> element need an "offsetHeight" property? It has one. If you look at the history of the development of HTML and JavaScript as a shining ideal of software engineering, you're certainly in the minority (this is all before TypeScript, which is a shining ideal of type systems!). The HTMLElement class has 134 properties, most of which make no sense for most elements. It has a long history and a lot of excuses for becoming what it is today, but I would not recommend you follow that lead in your own designs.
- whstl 3y agoNot really. Composition has been the preferred technique for a long time already. A lot of Games and GUIs that use inheritance worked in spite of that inheritance. In more complex object graphs there were always things like override boolean DoNotActuallyRender() in one or two children of the RenderableNode class to account for special behaviour. ECS is just the nail in the coffin of inheritance in game engines. And it's not even new anymore, it has been fashionable for what, almost 15 years now?