Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Invisible Bunnies That Power World of Warcraft (2017) (kotaku.com)
123 points by cpeterso on Dec 11, 2023 | hide | past | favorite | 100 comments


In a similar vein, WoW has become a lot more dynamic and stateful over the years, and the somewhat-hacky solution used to track what the current character has actually done is invisible quests. It's the exact same system behind the scenes as the more-visible "kill ten rats" quests that NPCs give you, just hidden away so you're not told about them and tracking things like "you've looted this treasure chest in the open-world, so it won't appear for you again" or "you've listened to this ambient NPC conversation".

You can even install an addon that'll show you the quests getting completed in the background, which can occasionally be handy as it basically notifies you "what you just did will be remembered". https://www.curseforge.com/wow/addons/questschanged

Amusingly, these quests still count as completed-quests for the in-game achievement system, so new characters will confusingly get achievements like "10 daily quests completed" despite never having actually completed a visible daily quest.


Wow thanks for this! I have sometimed wondered how I get 50 quests completed! achievement on a new alt even though I barely did 10 quests


The burst of quests is, last I checked, mostly stuff about unlocking battle pets and allied races.


Reminds me of how, for a very long time, almost every effect in league of legends was invisible minion(s) under the hood: https://technology.riotgames.com/news/taxonomy-tech-debt


The only thing that bugs me about this is that they used bunnies rather than making a specific "spell effect/scripting" NPC. (I mean just one type to be used everywhere rather than bunnies, not a new one for each use.)

It's common enough of a pattern in other games, and the #1 bug is that someone forgets to click the "invincible" checkbox somewhere, your scripting 'bunny' dies, and then the game just breaks. If you create a NPC type just for scripting, you can have it default to invincible & invisible (or no model to begin with.)


I recall a story where the camera kept "dying" from explosions but I can't find it.



This bug actually kind of added to realism :).


Perhaps the most famous time this happened in an MMO was the assassination of Lord British.

https://en.m.wikipedia.org/wiki/Lord_British


Building custom maps in WarCraft3 also involved a lot of invisible units to create unique spells. Creators generally used toads or sheep for these effects.

I've created a custom map turning the system a round, where you played the invisible critters instead of the hero :D


I wonder if this was the inspiration for the name of the creator of DotA mod, icefrog


oh that map was you? I was completely baffled as a kid whatever that map was about


> Sometimes you don’t know designers need a kitchen until they’ve made ramen in a flower vase with an iron

Wonderful


The problem in my opinion is that many game-engines are to focused on the "PerFrame view of the world" statically imagined by the designer and do not architecture for persitent but changing effects or long causal chains that constantly change and are capable of reusing behaviour. Good news though is that most by now, outsource that to scripting languages capable of providing better ways to implement this, but then you end up with parallel implementation of basic behaviour & services like pathfinding or targetting.

Imagine a late-game added lightspell, that is expected to behave like a ball lightning walking ahead of the player. The temptation to reuse the pathfinding, collission and other systems that controll figures will be enormous. But this behaviour needs a sort of CBipedal class to inherit all the behaviours. Voila - enter the hack.

Of course the clean solution would be something like a thrown stone on a lake, it exists as running code only when it changes (certain frames or events). It holds a composition of behaviours without the other ballast (datastructuress for aiming, inventory) etc. and also does not need a pool allocation to the monster/npc pool. (Basically you either have many peasants or many lightballs in the hypothetical as tradeoff).

Cause it aint a object, its a entity with a collection of behaviours, with a minimal data container bound to each behaviour seperatly, that may evaporate at a moments notice, should the player look away or its time run out.


In developing mods for Warcraft 3 using its World Editor, we'd often have to create invisible dummy units for the same reasons, like to cast a spell as part of a more complex custom hero ability. Always felt like a hack, but it's funny, surprising, and validating to learn that Blizzard essentially does the same thing in WoW.


I really need to sort out adblocking on my phone, there are so many half the time it doesn't even show all the content, it's probably ran out of resources.


Seriously. This was the most abusive reading experience I’ve come across in a while. I also only got to read a couple of paragraphs before endless ads.


For Android, Edge and Opera both have ad blocking built-in. It's comments like these that remind me what I'm (not) missing.


uBlock Origin on Firefox mobile is enough to not be bothersome. Even if it's not your preferred browser, it could help with ad-riddled sites at least.


The battleground, Strand of the Ancients, was originally started using two invisible NPCs that were hostile to each other; one on each faction's boat and dock. The first boat/NPC to reach the dock would trigger a spell/script when in proximity, starting the first round. [1]

[1] BlizzCon 2016 - WoW Engineering Panel https://www.youtube.com/watch?v=W1y2fdDeSbU&t=227s


"Why is WoW a front for a morally questionable bunny labor operation? The short version is, programmers’ time is limited, and NPCs’ time is not. Programmer time is extremely valuable, and most of the ‘stuff’ that can be done in a game can be done by NPCs,” said Chapman. “NPCs already have to support things like pathing, casting spells, using weapons, doing various actions to other NPCs, etc. So, while you could in theory have a programmer separately implement every ‘effect’ you wanted in the game with some minor benefit, if you already have a class of thing in a game that can solve your problem, it’s a better use of time to use the existing system.”"

I am sorry, but it still is just bad design, if you have to missuse a different class. So strictly economically speaking yes, after the system was already running, it might have been cheaper to go with it than redesign - but the initial design flaw is still a flaw. But they still made lots of money this flawed system, though, which is a good reminder, that the most important thing for any product is usually, does it work?


Honestly, I see it as accidentally good design. Take the "laser turret pointer" mentioned earlier. If you're not doing an optics simulation, but engage in the magical thinking (usual in storytelling) and treat the impact point as the entity of interest, then... making the impact point another actor on the scene suddenly makes perfect sense. Between the article and the comments, a lot of things bunnies/spectral cats/minions are known to be used for make perfect sense, and I'd consider explicitly planning for it when designing a new game.

Still:

> But they still made lots of money this flawed system, though, which is a good reminder, that the most important thing for any product is usually, does it work?

That is a very good point, especially in videogames/entertainment. Reminds me of the "first law of 3D game graphics" I read somewhere - "if it looks good, it's good - no matter the amount of cheating going on".


Back in the day (late 90s), I was heavily into the Marathon series and game engine. The trilogy box set came with a whole bunch of 3rd party levels, including one inspired by Myst. As Marathon was only one step up from Doom and (before getting open sourced and turning into Aleph One) had no actual scripting language, the level creator had to fake lots of things the hard way, one of which was by spawning NPCs to shoot at other NPCs, with weapons whose shots were marked as "can toggle switches" and some switches between shooters and their targets.


OOP at it's finest! I wonder if they have BunnyFactoryFactory.


Bunnies reproduce just fine without factories :)


This feels like a badly implemented homegrown ECS pattern.

ECS is kind of like lisp. Every sufficiently complex game will implement its own bug ridden ECS framework (unless it uses one already)


Reminds how in one of the Bethesda Fallout games, they needed a subway train car. Solution? Make an NPC with a train car head that runs really fast.


Blaine, is that you?

Also, reminds me of the Princess Donut book series.


This always became really interesting to see when you had a private server and could view invisible NPCs.

The “bunnies” usually used the default infernal NPC graphic


Are those bunnies leaked or datamined "official" Blizzard bunnies, or where they reimplemented by private server providers?


Datamined probably. Thousands of them can be found in the game files: https://www.wowhead.com/search?q=bunny#npcs


Reminds me of the subway trains in Fallout 3 being hats on NPCs that walk the track so the trains can move.


Invisible creatures have been a hack to make a lot of channeling spells work since Warcraft 3


Can anyone point to a better source for this so I can't share it with people? Kotaku is the TMZ of gaming and I never share it, but underlying content is good on this article.


This is the original source, reporting on a conversation between the writer and someone involved in the design being described. There can't really be a better source than that. Kotaku's uniquely bad reputation among gaming websites is only a result of people pushing a false agenda.


I understand that you would think that given the assumed context on this website but I'm not even American and the gamer gate thing was very distant from me, something foreign I read about in the news. I have absolutely no issue with this website's politics or any kind of agenda. Kotaku took a turn for the worse specially after the departure of Jason Schreier. I've read Kotaku for years, and I largely agree with Kotaku's political views and I was never part of any ridiculous gamer gate movement.

It's just a shallow website that is largely made of reposts, low effort sensationalism, poor journalism, and articles that could have been a Tweet. I do not repost it because it is extremely low quality even when it is the original source. But that subject was interesting so I wanted to find another source to share.


Jason Schreier left in 2020, and the title on this post indicates it's from 2017. So even if all of that is true, and none of your negative perceptions were absorbed due to gamergate, this article still came out in the period before the point when you think Kotaku took a turn for the worse.


Oh Kotaku was a low quality website long before that.

And of course I'm being truthful why would you just assume otherwise? Do I need to send you my Brazilian RG and CPF? The internet is so tiresome. Just open the website, read it. It's really bad. This is not a fucking narrative.


Kotaku has always been, and remains, fine. On opening it now, it's basically indistinguishable from any other gaming news outlet. That's why I'm skeptical of your claim that your opinion isn't influenced by gamergate; it has always been an unremarkable video game outlet, neither notably fantastic nor notably terrible.


If you believe that's a good website, I disagree but that's fine by me. Just don't fit my dislike into some crazy American narrative. I truly and genuinely believe it's a bad website solely due to what I perceive to be consistently terrible and cringeworthy reporting I'm not willing to share. This has absolutely nothing to do with politics.


Specifically Kotaku's bad reputation primarily stems from GamerGate.


Not at all in my case. I have no beef with their politics. Kotaku is just a terrible website due to its shallow reporting and almost all its content has a better source that is often linked in the article. They are also needlessly inflammatory and not at all careful in their journalism. Again, this is 1000% not about politics.


Yeah but that was never a distinguishing property. All gaming journalism was pretty bad at the time and continues to be bad. This is why the fig leaf of "ethics in games journalism" was so attractive to anyone not paying close attention to GG: it was an open secret that many game reviews were either outright paid by publishers or written by journalists held on a tight leash with exclusive early access privileges implied to be contingent on positive review scores. I grew up in the 90s and 00s and I very much recall the boiling hatred for EA for buying out successful developers, restructuring them and leaving empty husks that churn out infinite sequels until the IP ran dry. People used to make fun of games like Call of Duty for boiling down all narrative mechanics to quick time events while railroading you through a third rate movie.

Kotaku ended up being singled out over the allegations regarding Depression Quest where it pretty much became ground zero for GG. The allegations themselves were mostly fueled by a cultural backlash of "true gamers" against "walking sims", the derogatory label for projects using games as medium for interactive narratives and experiences, which they saw as a threat to traditional gaming and gamer culture (which makes more sense if you compare it with the Great Replacement conspiracy theory and see it as a precursor to the Cultural Marxism conspiracy theory especially popularised by Jordan Peterson).

Heck, even the affiliation was shaky at best: a person claiming to be the ex of the person who created Depression Quest accused a journalist writing for Kotaku to have given Depression Quest positive coverage while they were in a relationship. So at worst the argument was that the developer used a friend to create attention for the game by writing about it without disclosing their (at the time non-romantic) relationship. Compared to what every major gaming journalist was doing with triple-A publishers at the time this was a nothing burger - except GGers disliked what the game represented (i.e. progressives using games as a medium for interactive art pieces) and who was behind it (women and queer folk, i.e. people with "political" genders/ethnicities/orientations rather than straight-passing white-passing cis-passing men).


I feel that you wrote about a lot of things that are nothing to do with anything I wrote. I don't live in a alternate reality where Kotaku has great content. I'm not sure why you do. I read other websites that are equally "woke", but with good content. Polygon is one, just to give an example.

As a leftist Black progressive from Brazil, I don't need to pretend I like a shitty website just to appease to crazy American prejudices.


Kotaku was a joke for me and my gamer crew way before that.


I definitely read about this on wowinsider at some point. sadly it has been really annoying to search the stacks since it got turned into just an engadget tag so that AOL could turn their wow.com domain into a failed coupon venture


the more interesting article is linked in the first paragraph, where spectral kittens power radio stations in Fallout 4


> “The cat acts like a settlement radio receiver, and its role is to keep alive the inactive radio station so it continues to the next track even if you’re listening to another station. Just like if it was a settlement receiver somewhere near the player. In normal circumstances the cat doesn’t make sound. It is silenced, it is invisible, and it is deleted from the game world after three seconds.”

What I don't understand there is, why are those cats deleted after 3 seconds? Does it mean the inactive radio station only continues playing the next track for 3 seconds, and then freezes? If so, that sounds like an unfortunate limitation.


Probably a cat needs to press next, but then the cat doesn't need to listen to the full track?


I assume the cat counts as an in-proximity listener to the radio, which makes it initialize. Having initialized the radio, the cat can be garbage collected.


I think the prevalence of these sorts of issues is why ECS is such an appealing architecture in game design. OOP seems to always devolve. A new feature is needed for the game, the feature breaks some well established design rule, it's challenging/slow to refactor everything to make sense while considering the new feature, and so a kludge is implemented where existing objects are forced to be more flexible than planned.

Of course, this can happen with ECS, too, but it feels easier to avoid. Systems which are coupled to individual components of entities, rather than whole objects, provide an extreme degree of flexibility as long as the components stay small.

(bonus: another example of this occurring in Fallout 3 - https://www.pcgamer.com/heres-whats-happening-inside-fallout...)


I had to look that up. From Wikipedia: Entity component system (ECS) is a software architectural pattern mostly used in video game development for the representation of game world objects. An ECS comprises entities composed from components of data, with systems which operate on entities' components.

ECS follows the principle of composition over inheritance, meaning that every entity is defined not by a type hierarchy, but by the components that are associated with it. Systems act globally over all entities which have the required components.


Since ~2007: https://blog.berniesumption.com/software/inheritance-is-evil...

Jedi "has dark powers", not Jedi "is dark jedi".

That way R2D2 can "has dark powers", as well as can "has light powers".


For what it's worth, I'm not aware of anyone who believes inheritance "ontologies" was a good idea, nowadays. Interfaces sure, but composition is just better for this reason. ECS is a formalization of that, and probably even perpetuated the idea, but it's everywhere I look now.


Inheritance works for essential things and composition for accidental things. Use both together to get the full Aristotelian deal.


Except of course for all the ontologies in your language's standard library that you don't even notice. Your IO hierarchy, exception hierarchy, your collections hierarchy.

As long as you don't kingdom of nouns everything any repeat the mantra: "classes are just interfaces with code reuse" you'll be fine.


This is factually correct, but misses the point I was trying to make. I'll fall on my sword there.

What I mean is: For library developers, inheriting an interface makes some sense. But throwing in an ontology that is meant to mimic human-like classification (esp just for the sake of it) is a disaster in all the code I've seen. There really isn't any reason for a Shape: Circle hierarchy. The better abstraction is around what can be done: a PrintableList<Point>, or whatever.

std:: takes the second approach (Type trait-like interface_-level decisions. There was (for a time) a huge push for the first approach of "is-a" relationships which makes zero sense almost any time.

IMHO ECS is a sane "has-a" relationship which is effectively a redo of "is-a" interface-level interactions, b/c each entity "has-a" list of objects that form it's interface with the system.


You're correct here. I see this as a - still too common[0] - lack of understanding of what classification/ontology/taxonomy is. Categories are made for humans. They're arbitrary and judged only by one thing - are they good enough for the problem being solved. In this sense, reflecting a real-life ontology in your code is usually doing things backwards - it's the code that should invent it's own ontology that's maximally convenient for the problem being solved[1]. Real-life ontologies all have their purposes, but they usually don't include making it easier for you to write software.

--

[0] - Is tomato a fruit or a veggie? Is a whale a fish or a mammal? Etc. The answer to that is just "either, none, whatever - it's you who are confusing culinary, economic and genetic taxonomies".

[1] - Which is some combination of code thinking and domain thinking. It's never just purely one of them.


> I'm not aware of anyone who believes inheritance "ontologies" was a good idea, nowadays.

like, all of anything you could program, ever? for any purpose?


ECS is a kind of Data Oriented Programming / Data Oriented Design. In Data Oriented Programming data and code are separated (no encapsulation). This makes changes much easier to do and helps a lot with managing state.


Sounds like it would have the same problems during refactoring if many different entities relied on the same data. You would have to make sure none of the entities’ behavior changes when you’re modifying your data. It also sounds very verbose where you have to compose each entity all over again instead of inheriting and adding an additional property. But that being said, I would take being verbose over weird hidden layers of abstraction any day.


That just sounds like OOP but without subclassing.


I asked ChatGPT 4 for an explanation and came up with this analogy,

Imagine all in-game characters have their data in a database. The database might have one or more tables representing an objects ID or another reference, its position, its health points, and image data representing how to draw the object. These three things are "components" and the IDs and references are "entities."

A system is anything that manipulates one of these components. Thus, a function that manipulates a component is a system.


ECS is IMHO a logical consequence of observing that game worlds are not object oriented (as it is taught in schools, so class hierarchies etc.) Add a sprinkle of performance requirements and you get what is understood as ECS frameworks.

…but it turns out that the ‘world is not made of class hierarchies’ observation is not limited to games, hence Rust’s and go’s approaches to OOP: ditch inheritance at the language level.


ECS makes sense in games because OOP enforces lots of rules downstream in your inheritors, which is good for GUIs, but bad for games when producers keep asking for that one npc or boss to do something special that breaks the rules. ECS is just so much more flexible which is good for some design systems and bad for others.


E.g. react does just fine with functional components; I'd say it does much better than with the old class-based ones.

Inheritance works well enough in exception classes, e.g. I can catch OSError and specifically handle FileNotFoundError differently on a language level, but it's nothing composition couldn't handle, either.


I disagree re: React.

To me, class-based has one advantage over functional. A component is an object and therefore perhaps ought to be represented by a class.

That being said, functional maybe is a bit simpler.


> A component is an object and therefore perhaps ought to be represented by a class.

That's what those who ditch inheritance altogether when designing languages challenge and it turns out not much of value is lost :) 'Component is an object' is something you'd hear from an OOP practitioner which isn't exactly convincing to people thinking functionally.


I actually use a little bit of both OOP and functions.

What I don't understand, I suppose, is if a Component isn't an object that acts, then what is it?


The world isn't, but some things are. Doesn't Rust have a problem with GUI frameworks because they heavily use inheritance?


I don't think it does, I think Rust GUI frameworks have the same problem as Rust game engines, there's more people making frameworks than people actually making applications. They mostly seem to be going in the same direction as web UI frameworks though, which don't use much inheritance either.


Ah, ECS. The most ill-defined software pattern since IoC/DI. Everyone seems to have their own understanding of it, usually somewhere on the spectrum between "what if we kept the game state in a relational database"[0] and "what if we put any individual type of information into its own big array, so it's CPU-cache-friendly"[1]. I wrote several such systems for my own toy games, at various points of that spectrum[2], and I still have a bunch of open questions I can't seem to get my head around.

The biggest such question is: how the hell do you handle "cross-cutting concerns" in an ECS architecture, especially in the data-oriented programming version, where "cross-cutting concerns" are basically any kind of logic ("system") that needs to access more than one component of an entity at the time, especially if it does so conditionally? Like e.g.:

- Physics, rendering, animation, and game logic all need to access some subset of the same position, orientation, dimensions, velocity, acceleration, mass, tensor of inertia, etc.

- Any kind of logic that goes like "IF something(component 1) THEN doSomethingTo(component 2) ELSE doSomethingTo(component 3)".

How are you supposed to preserve data locality in such cases? Is it even theoretically possible?

I may have some fundamental misunderstanding about the definitions here[3], but I haven't found any clear answer to the questions above, whether theoretical or practical. Back when I last looked, couple years ago, I couldn't find any non-toy game written ECS-first and with source available to study. Maybe this has changed now.

--

[0] - Which, as far I recall, was the original idea behind the pattern. It's also a very interesting one in general - if you squint, a lot of code all of us write for our projects is just half-baked attempts at setting up specific indexes and hand-rolling queries to a bunch of vectors, hashmaps, or (gasp) object graphs.

[1] - AKA "data-oriented programming", in this case mostly preferring "Structs of Arrays" over "Arrays of Structs".

[2] - One of them was literally just "let's store all game state in an in-memory SQLite database, because guess what, it's actually fast enough to be queried at 60 FPS!".

[3] - In my defense, most of the guides, tutorials and articles I read back in the day were themselves confused between "SQL approach" and "SoA approach" (see [0]), or worse, mixed in "whatever abomination Unity passed as ECS back then" and even something semi-related from .NET world. It took me a lot of time to understand that everyone's using their own blend of all those ideas, and this left me unsure about what one's really supposed to do.


I think the answer is that ECS isn't supposed to solve those problems directly. It's just a framework that makes a certain class of problems very easy to solve. But big picture complexity is still up to the developer's skill and wisdom. Knowing which parts of the game should go into ECS, and which parts go somewhere else. Which systems flow from another system. Which system is allowed to manipulate the data directly and which systems are only able to read data reasonably, but not write. And how your design of the game may need to change to suit the limitations of your computer and your ability to program.

ECS is like any other framework. It is a tool or system, for organizing your efforts. Be very liberal with using it in its intended scope. Be judicious when its at the edge of its scope. Be very skeptical when its outside of its scope.


You seem to be coming from somewhere closer to "like SQL" than the data-oriented end of the spectrum.

On either end of the spectrum, there's much less flexibility. The "SQL side" is optimizing things for bulk operations[0] and flexibility coming from composition[1]. The "data-oriented side" is optimizing for performance, and it so happens that stuffing data that's processed together into arrays you can just scan in a cache-friendly way, also yields a component-like division of data.

Both those approaches are quite inflexible. They do kind of meet in the middle, as they yield similar data organization, but I'm increasingly convinced this is a surface-level, entirely incidental similarity. Philosophically, the two extremes of "ECS" are entirely unlike.

--

[0] - Again, AFAIR, ECS originally came from MMO world, where they do use relational databases for storing game state.

[1] - Also reason to use databases if you're making an MMO, as relational tables are known quantity, while serializing polymorphic object graphs is plain annoying.


The performance side is a bit overblown, in that of course performance strongly depends on access patterns and the access patterns strongly depend on what you're actually simulating. ECS can help with performance but it can also hurt: e.g. the devs of factorio, who have a very large simulation, based on their profiling, have found the game is almost entirely memory bandwidth limited, and so an ECS SoA system like is often touted would not work very well, as it's far better to run every system on each entity than it is to feed each entity through each system, and when inevitably different systems care about the same components, the first will almost certainly find the component data in the cache, while the latter almost certainly won't be and results in the same data being loaded from RAM multiple times.


> Any kind of logic that goes like "IF something(component 1) THEN doSomethingTo(component 2) ELSE doSomethingTo(component 3)"

What's the problem here? You write a system that queries these 3 components and then call regular functions. In bevy (a rust ECS framework) it would look sth like this:

    fn complex_system(
      query: Query<(&Component1, &Component2, &Component3)>,
     ) {
      for (c1, c2, c3) in query.iter() {
         if condition(c1) {
           doSomethingTo(c2);
         } else {
           doSomethingTo(c3);
         }
      }
     }
I think there's no need to deconstruct everything into smallest possible systems, this level of granularity is ok. You could also make the condition into something that can be selected by the query and remove the if.

    fn complex_system2(
      query: Query<&Component2, With<ConditionFullfiled>>,
     ) {
      for c2 in query.iter() {
           doSomethingTo(c2);
      }
     }
     fn complex_system3(
      query: Query<&Component3, Without<ConditionFullfiled>>,
     ) {
      for c3 in query.iter() {
           doSomethingTo(c3);
      }
     }
But that's only possible if you can make the condition be simply existence of some component in given entity. Could be improved with systems that query based on values of components and indexing could be added, of course, but I haven't seen that kind of ECS yet).


You seem to be coming from the "it's more like SQL" end of the spectrum.

Yes, in that design, my questions aren't hard - but then, this design doesn't give you all the touted performance benefits, since in a data-oriented ECS, you're supposed to iterate over arrays of values directly (Rust may be doing some magic here I don't understand, though).

> Could be improved with systems that query based on values of components and indexing could be added, of course, but I haven't seen that kind of ECS yet).

I tried to implement exactly that the other day, including with conditions on values; my overall approach to that was that each Query/Condition had its own array of entities, and all the Query/Condition array of entities were updated on operations like adding/removing components, so the checks are done only when their outcome could changed - which is less frequent than "for every entity, every frame".

It is at that point I realized I'm just reinventing database indices and materialized views, and papering them over with Lisp macros to remove boilerplate - which led me to ditch that ECS implementation, and go for "let's just move all game state data to in-memory SQLite database, and see how it works".


Even before hearing about ECS I wanted some kind of in-game in-memory database for game objects (preferably with history) so I could write quests and dialogs conditions in general way.

Like "If player seen this kind of a monster already and there's at least 4 people in the room and someone there has this kind of weapon equipped - enter this branch in dialog and progress the quest".

Traditional solution seems to be hardcoded special cases for all conditions which probably has better performance but sucks so much when you're implementing quests and dialogs. You tend to avoid writing quests that require new kinds of data so you end up with fedex quests and murder quests and that's it :/.

How well did this SQLite idea worked out for you?


You seem to have deep fundamental misunderstandings about ECS systems.

You can absolutely access multiple components in a system, for some reason you think a component and a system must have a one to one relationship, when really it’s many to many.

The only caveat is that you have to think carefully about the order that some of your systems are executing in the game loop, since you want to make sure component data has been updated appropriately for later systems to act on.

ECS is really the best way to make games. It lends itself well to rapid iteration and experimentation of new game concepts.


> ECS is really the best way to make games.

A little bit of nuance would go a long way.

Even in games where ECS is a good match, having to implement a boss with ECS is wasteful in terms of dev time and performance: You have to create components and matching systems unique to the boss, where with a traditional approach you just have to create a single Boss class.


A boss is nothing special it is just an entity, also after you beat up the boss you can have later enemies use components from the boss to reflect the players progress in killing enemies using similar mechanics as the boss, until you reach a final big boss.


On the other hand, the classical approach lets you treat the boss as the one-off actor of an one-off scene, which it really is. This narrows the scope of your work (and associated testing). Integrating it into your overall ECS means you either make all aspects of a boss fully generic, working everywhere, or risk someone at some point adding "SpecialLaserCannonHelmet_Boss1" component to a random mook and breaking the game.


It wouldn’t break the game, it just probably wouldn’t render correctly since a boss works with certain graphics.

Having a one off actor is really limiting. You can create several boss components and build entire permutations of bosses just by mixing and matching them up, without writing specialized code. Designers can put together the entities without developer input.


I suppose it depends on how the ECS is coded.

You could create a database table called "Boss," that contains all the Boss components. Then for each system, you create a function that operates on a Boss.


> Physics, rendering, animation, and game logic all need to access some subset of the same position, orientation, dimensions, velocity, acceleration, mass, tensor of inertia, etc.

I wish I knew the solution to this exact problem. IMO this is the central issue that stops pure ECS from being useful.


You seem to be coming from the data-oriented end of the spectrum.

I spell that out to highlight the part about ECS being a very ill-defined programming pattern - I already see three parallel replies representing three different points on the spectrum :).

Beyond that, thanks - I'm relieved to know I'm not the only one with this problem.


As for your DB remarks, I've recently read an interesting blog post [1] about using SQLite as a cache in the context of web frontend. Apparently it works Well Enough™.

[1] https://sqlsync.dev/posts/stop-building-databases/


Thank you for this. I've been waffling on just using SQLite to store all the game state. I will give it a shot. I know it will break down for larger scenes, but I don't think I have those yet. Simplicity is probably way more important than anything else for a solo dev custom engine experience.


I believe Space Station 14 is implemented using an ECS engine. It's open source but quite impressive regarding scale and features. It's also a multiplayer game which brings some extra questions to the usual ECS ambiguities.


Another recent example is from Starfield, where shops inventories are handled by a physical chest hidden underneath the shop. You can use noclip to loot the chest and get shop items for free.


That kind of makes logical sense, though. Physical hidden chests are, after all, how almost all real life shops implement inventories. Those are typically inaccessible to players, too.

(There is a part of shopping experience where the player grabs items and puts them in their own chest/basket prior to purchase. This works thanks to the security scheme of law enforcement NPCs dragging your ass to jail you can't save-scum your way off, should you steal something. But this is too complex to implement in a game, unless you're making the next GTA.)

Hell, even the bunnies and spectral radio cats make sense, to a degree. This reminds me of the ol' Flash games or Klik&Play/The Games Factory-made games. In all of them, you'd find yourself placing support objects on the scene but outside the screen boundary. I used to laugh at it, but eventually realized it kind of makes sense, if you think of the game as a theatre play - there's lots going on at the edges of the stage, just beyond what the audience can see.

Or think back to RAD tools from Borland (Delphi, C++ Builder) - they had a notion of abstract objects like "Timer" as invisible UI controls that could be placed in the window you're designing. On the one hand, this makes no sense - an abstract timer doesn't have "position" or "size", not at runtime. On the other hand, it was intuitive and convenient at design time.


The recent Pokemon games also had a bug where the various support objects placed on the map for cutscenes were made visible during battles.

Since they lacked a model, they'd default to the first model in the games object list, which was a PokeBall, but then also loaded up every single texture onto it, resulting in various maps getting random multicolored PokeBalls in the floor (usually at their 0,0 point).

The approach to me also makes sense if you think of these support objects as "directors" for the gameplay. They usually track a specific bit of state to then act on once it's met. It's a pretty clever technique for rapid development (you can usually do what support objects do without them but it'd take a lot more effort in the game engine to do it that way) that can sometimes backfire in entertaining ways.


The jail mechanic is not too complex to implement, depending on the kind of game. It sounds pretty similar to the Keystone Kops in Nethack. Like Dwarf Fortress, it exchanges graphical detail for complexity.


> Nethack

> Dwarf Fortress

Ah yes, the two most complex videogames ever created :).

I do appreciate the remark, though. The mechanics may not be impossibly complex, it's just prohibitively complex for vast majority of the games.

(Which is a sad thing to me; I love games with lots of internal complexity.)


I love them too. I'm hopeful LLMs may eventually help fill in the details and lead to complex generative mechanics like this.


That's been the case with Creation Engine games for decades, it's also present in Oblivion, Skyrim, and Fallouts 3/4 (and maybe others, that's just all I have experience with). It's amusing that it still works the same even through the iteration of the engine they made for Starfield.


(Off topic to ECS) This description is kind of funny to me. If you’re using noclip, who cares about how much things cost? You’re already cheating.


Well one of the bugs was the very small corner of the chest poked through the ground and at the right angle you could loot it without no clip.


Been like this since at least Skyrim, maybe earlier


I'm not really sure this is an OO vs. ECS vs. any other design architecture thing, as evidenced by a lot of your other replies. I think it's just a general programming pattern that it's very tempting to take a large dependency on in order to get some small bit of functionality. Then, Hyrum's Law takes over [1], and you end up with a few more bits of dependency on the massive bit of code you pulled in. And you pull in a few more massive dependencies for just little bits of functionality, and organically grow a few more attachments to the huge code base. And before you know it, you've got 10 massive dependencies, and you only use vanishing fractions of their functionality, but extracting any of them is a huge pain.

It's true that OO design pushed game engines in this direction; if you need something that only the last "full on NPC" node in the inheritance tree provides, which is very believable, then your designers are going to use it, even if they don't need most of the rest of what it provides. But I think this is something your designers are generally going to do anyhow. They aren't professional programmers and they aren't sitting there worried about long term code quality (especially not in the games industry), they are worried about getting their job done, and under any design it's going to be easier for them to reach for a large stick and pare it down than to reach for the small stick and then laboriously figure out how to attach the extra bit it needs. It doesn't matter how easy it is to attach the extra bit, it's going to be easier for them to grab the big, all-in-one provider. They're going to figure they may need the other stuff later anyhow, and they're reasonably likely to be right so it's hard to even call that irrational.

You can see this pattern all over in programming. I know of multiple codebases where I work that suffer from this pattern without any games being involved. Developers could implement new subsystems either as independent subsystems that they minimally connected into the main product, but have relatively few services provided by default to those subsystems, or they could start from day one fully integrated into the rather massive monolith with all the services it provided, even if it wasn't great with those services. And generally they would choose the latter, making the monolith even larger and the crossing mishmash of dependencies on the large services even bigger and more complicated. Maybe they were even right at the time, but now we've got some fairly large and complicated balls that can't be replaced in a big bang, but also can't hardly be replaced incrementally, because everything depends on everything. Upgrading any portion is a nightmare. They reached for the super complicated, relatively powerful objects that provided all the services even if they just needed a couple things, and now they're all in a spaghetti pile. And there's hardly any OO in sight, this is all really just procedural despite the occasional OO island.

You can see this in the still-growing general understanding in the programming community that dependencies are not free. The benefits you can obtain from a dependency are enormous, immediate, and easy to see. The costs are subtle, to the point that you can be mocked by developers for thinking they even exist (though I see this particular attitude fading, fortunately), but it's easy for them to grow into at least the order-of-magnitude of the benefits, and sometimes exceed them.

[1]: https://www.hyrumslaw.com/




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: