Mixing Entity Templates and Parameters

Started by
4 comments, last by LorenzoGatti 6 years, 11 months ago

Hello Everyone,

I am finally getting around to creating an Entity Factory. Essentially, its a bunch of smaller factories dedicated to each specific component type grouped into one class. Templates would be read from a file, and each factory would store which templates matter to it specifically. Then I ask for that specific template and each factory handles it as needed. Seems simple enough.

Where I am a little lost on is the best way to add parameters to this system. For example, things like position, what team a unit may be on, any sort of buffs or nerfs that may come into play, etc. would be determined by gameplay scenarios, and could not be stored in a file.

The way I am currently going about it is having a struct which would contain that information, and passing that along to the factory. This is simple enough, but I could imagine this thing becoming kind of large depending on how many things can change, and not everything actually requires these parameters.

I could create separate methods for things that require these parameters, like units or projectiles, but this seems like I would be defeating the purpose of a central factory somewhat if I don't have a central creation method.

I could add the parameters after creating the templated version, but this would either limit me to creating one entity at a time, or require a means of storing which entities created in a batch need to be different.

All these options have their own pros and cons, and I am having a bit of analysis paralysis over it. What option would you guys recommend, or have tried in the past?

I'm sure I'm overthinking things, but I would really appreciate your help.

Advertisement

First question: why can't you just fix up these parameters after the factory has created the object? Whichever object has this information can probably work out where to put it.

Second question: you talk about defeating the purpose of having a central factory, but what is that purpose? Why expect one generic object to be able to create anything in any configuration?

First question: why can't you just fix up these parameters after the factory has created the object? Whichever object has this information can probably work out where to put it.

Second question: you talk about defeating the purpose of having a central factory, but what is that purpose? Why expect one generic object to be able to create anything in any configuration?

In answer to the first; I could but I think it could get a little messy to mange that information. Perhaps I am overestimating how messy that would be, but that is part of the reason I am posting here; to get me out of my own head so to speak.

In answer to the second... now that I think of it, I'm not entirely sure. It seems rational to want a unified means of creating anything, but that may be me stuck in my own headspace again.

So I take it you would recommend the post-make method?

When you say it could be messy to 'manage' that information, could you elaborate? Whichever function or object is creating the entity must already know what kind of entity it is making, and it must already have that parameter information in some form. Injecting the information into the entity can therefore be as simple as `entity.setValue(whatever)`. If your situation is more complex than that, then perhaps you could explain a bit more about it.

Here are the Unreal Engine docs for spawning an actor. It provides 3 important features:

  • the ability to specify a template that the new actor should copy default values from, because these are shared across instances
  • the ability to specify location and rotation, because they are commonly different across instances
  • it returns the spawned actor, so that you can perform further configuration yourself.

Here's the Unity equivalent. The syntax is a bit different, but it's essentially the same:

  • you pass in an 'original' prefab object, from which the new GameObject will copy properties;
  • you can pass in position and rotation, because it's common to need to specify those per-instance;
  • it returns the object that it created, so that you can customise it further.

What neither of these systems attempt to do, is to allow arbitrary parameters into this stage of the creation process. Arbitrary parameters are allowed in the template (or prefab, or class default object, or prototype, or whatever you want to call it) and these can be copied across, as copying is a fairly simple operation. Commonly varying parameters can be passed in, and because they're common (position/rotation especially), it's easy enough and useful enough to hard-code them into the creation interface. Finally, it's well understood that each character may have some further customisation necessary, but that it's not possible for the generic creation process to handle that - so it hands the object back to the calling code, which hopefully has enough context to perform any final configuration.

Is it hypothetically possible to have a factory which, given a lump of data, will do all this work for you, and configure any object to any specification? Sure. That's pretty much what your file-based templates are using, right? But you have that system because you need it. You need to translate from meaningless bytes on disk to meaningful objects in the game. You could do this for everything - serialise your in-game data such as position, team, buffs + nerfs all to bytes, then have some system 'load' it back in. But why bother? You have the information already - what do you gain from squeezing it through the serialisation process? Ultimately you're probably going to call Character.AddBuff(SomeBuff) (or equivalent) so you may as well just call it directly rather than fill some sort of structure or buffer which another object is going to have to parse in order to find the SomeBuff and then call AddBuff with it.

So I take it you would recommend the post-make method?

TL;DR - Yes.

When you say it could be messy to 'manage' that information, could you elaborate? Whichever function or object is creating the entity must already know what kind of entity it is making, and it must already have that parameter information in some form. Injecting the information into the entity can therefore be as simple as `entity.setValue(whatever)`. If your situation is more complex than that, then perhaps you could explain a bit more about it.

Upon reflection, it probably is not that complex. I was definitely overthinking it. Sometimes you just need someone to ask some simple questions and then you realize you were worrying over nothing.

Alright, you have me convinced. Thank you very much for your help!

Where I am a little lost on is the best way to add parameters to this system. For example, things like position, what team a unit may be on, any sort of buffs or nerfs that may come into play, etc. would be determined by gameplay scenarios, and could not be stored in a file.

It's the other way round: more advanced designs allow you to remove "parameters" of entity creation and turn hardcoded values in code into data from files or nothing at all.

The most basic, "stupid" factory would include methods that create entities and expect all data in the entity, with nontrivial code to deal with memory allocation, containers, assorted bookkeeping, etc.

A more opinionated factory could initialize data according to universal rules (e.g. set an entity creation timestamp to the current date) and offer special methods to initialize simplified entity variants (e.g. a method to create immovable objects, which doesn't ask for velocity and sets appropriate flags automatically).

Using named entity templates is the next level of sophistication, with the important benefit of making entity variants and their properties explicit and easily editable.

What you call "gameplay scenarios" is an additional layer of data-driven specification of your game levels, involving data that differs for each instance of an entity instead of being shared by entity types. At this point the entities that are created explicitly, rather than by telling the factory to create the entities specified by a set of level files according to a set of template files, would be a few singletons (e.g. the player) or none at all

Omae Wa Mou Shindeiru

This topic is closed to new replies.

Advertisement