G
G
Georgy Pelageykin2016-03-21 23:01:08
OOP
Georgy Pelageykin, 2016-03-21 23:01:08

How to link two class hierarchies?

Perhaps expressed in one sentence, the question sounds wild. I'll try to make it clearer.
The game is divided into some kind of model and presentation. There is a base class for all material objects in the game: SpaceObject, it has descendants: Planet, Star, Ship, Asteroid, etc. As long as it all "lives" inside this very model, everything is fine. But as soon as there is a need to display an object, problems arise.
So, if an object appears in the same location as the player (there is a corresponding event), it is necessary to create its "alter ego" in the form of a GameObject of the game engine. The problem is in this code:

void InitializeSpaceObject(SpaceObject spaceObject)
    {
      if (spaceObject is Star)
        InitializeStar(spaceObject as Star);
      else if (spaceObject is Planet)
        InitializePlanet(spaceObject as Planet);
      else if (spaceObject is AsteroidField)
        InitializeAsteroidField(spaceObject as AsteroidField);
      else
        throw new UnknownSpaceObjectTypeException("Cannot initialize SpaceObject of type " + spaceObject.GetType().ToString() + ": unknown type.");
    }

Of course, such a code, at least, violates the Liskov substitution principle, but in general it is simply inconvenient to use and expand. But you can't just add a reference to some object initializer in the SpaceObject class - the model should not know anything about the engine and all the visualization logic.
How can you get rid of this string of if's, or at least automate the process of finding an initializer for the desired type of object?
Below I will try to outline a couple of options that came to my mind - perhaps they are viable?
1)Declare a table "Type" - "Initializer". What to be an initializer - a method delegate or a full-fledged class, is a secondary question. Slightly better than if's, but still somehow cumbersome
2) Unity-style. Create a regular MonoBehaviour script for each type of object. Everyone listens to the event of the appearance of an object in a location. Inside the signed method - one check if (spaceObject is ThisScriptHandlingType) {initialization code}. What can you say about this option?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Stanislav Makarov, 2016-03-22
@ArXen42

If you have to live with the separation of architectural layers that you mentioned and cannot change anything: the first option "type" - "initializer" I see as the most convenient. You still have to add mapping when adding a new type of object.
In general, of course, you can continue the perversion and use reflection and make auto-mapping of the "model" classes onto the GameObject heirs. For example, look for all "model" classes in a certain namespace and look for the same ones in another (which, in turn, will be inherited from GameObject).
In general, in a sense, you go against the architecture of the engine itself, because. GameObjects are not only a "view" but also a model. I understand that you probably don't want to create heavy GameObjects when they don't seem to be needed yet (i.e. not in scope), but it's possible that if you don't add them to the scene, they won't load the engine.
In general, I have my doubts that such a separation into model and view when using Unity is a good practice.

A
Andrew, 2016-03-22
@byte916

Why not add an abstract Initialize method to the parent SpaceObject class, which you override in each child class, and then your code will be reduced to

void InitializeSpaceObject(SpaceObject spaceObject)
    {
spaceObject.Initialize();
    }

And they also say that it is better to pass interfaces in parameters, that is, it should be like this
void InitializeSpaceObject(ISpaceObject spaceObject)
    {
spaceObject.Initialize();
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question