"Generic" achitecture

Hi !

I have a somewhat simple problem (at least, easy for me in c++ with pointers and classes aggregation, but not with c#)

I need, in order to optimize my classes, to have a class like this:

class Object_Default
{
	public Vector3 _Pos3D;
	public Texsture2D _TexChannelA;
	... (other mandatory properties)
}

and I need some versions of this class to be “specialized” with more properties:

class Object_OnlyColor:Object_Default
{
	public Vector4 _Color;
    //Other props
}

class Object_LightnShadows:Object_OnlyColor
{
	public bool _IsReceivingLight;
	public bool _IsCastingShadows;
	public bool _IsCastingLight;
	public bool _IsReceivingShadows;
    //Other props
}

How can I have a generic array of one of these types, without having to test the type each frame with:

if(_objectsarray is Object_OnlyColor[])
{
//Do something according to this type: set values to be used with the effect, etc.
}
else
if(_objectsarray is Object_LightnShadows[])
{
//Do something according to this type: set values to be used with the effect, etc.
}

Is there anyone with a good architecture, with fast performances ? I don’t think creating a “object” type array and casting it each frame would solve this. And I’m not sure an abstract class is the solution. Since aggregation is not possible with C#, how to achieve this ?

Use virtual functions in the base class then override them in each of the “specialized” class. If a given specialized class has no implementation for said function then just leave the override function empty. Loop through the entire list and call every function needed (regardless of type).

My guess is that you are concerned about the overhead for calling empty functions though. I’m not sure how to code it so that it automatically knows the type of object and calls the appropriate function(s). I’m honestly not even sure if that is possible.

Thanks, I’ll find some doc about virtual methods in c#.

I think this is automatically resolved by the linker, a same name for different functions with the parameter type changing, the right method should be called.
But I’ll have to override as many methods as I need types, which is better for me (unless I have 10s of types :confused: )

If you keep the same method names across types, but just have different parameter lists, then yes, that will work just fine and there will not be a need for empty override functions in the specialized (child) classes :slight_smile:

You can actually do this with basic inheiritance and dropping in virtual methods as desired.

I made this as a simple console example for reference.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InheiritanceAndBaseDerivation
{
    class Program
    {
        static void Main(string[] args)
        {
            AnimalLover me = new AnimalLover();
            me.Draw();
            Console.ReadLine();
        }
    }
    public class AnimalLover
    {
        List<Animal> animals = new List<Animal>();
        public AnimalLover()
        {
            animals.Add(new Animal());
            animals.Add(new Cat());
            animals.Add(new Dog());
            animals.Add(new Lizard());
        }
        public void Update()
        {

        }
        public void Draw()
        {
            foreach (Animal item in animals)
            {
                item.Draw();
            }
        }
    }
    public class Animal
    {
        public string objectTypesName = "Animal";
        public string noise = "...";
        public string growl = "grrrr";
        public virtual string Speak
        {
            get { return noise; }
            set { noise = value; }
        }
        public virtual void Update()
        {
            
        }
        public virtual void Draw()
        {
            Console.WriteLine(objectTypesName + " " + Speak);
        }
    }
    public class Cat : Animal
    {
        public Cat()
        {
            objectTypesName = "Cat";
            Speak = "Meow";
        }
    }
    public class Dog : Animal
    {
        public Dog()
        {
            objectTypesName = "Dog";
            Speak = "Ruff";
        }
        // because dogs are very vocal
        public override string Speak
        {
            get 
            { 
                return growl + " " + noise; 
            }
            set
            {
                noise = value;
            }
        }
    }
    public class Lizard : Animal
    {
        public Lizard()
        {
            objectTypesName = "Lizard";
        }
    }
}
// Output as follows
//
// Animal ...
// Cat Meow
// Dog grrrr Ruff
// Lizard ...
//

Note that the Cat the Dog and the Lizard All are all collected and called by the AnimalLover. When we call Draw on the AnimalLover Instance he asks them all to speak.

Each speaks differently in its own way even though the AnimalLovers List is only a list of animals.

Cats call to their base.Draw and then that calls to the Cats derived Speak.

Conversly.

Dogs will call to there own Overridden Speak from there animal inheirited Draw.

Where lizards use the base of calls (animal), with the exception that only the derived objectTypeName has been set and it is shown in the output.

You don’t want to cast were its avoidable (IS AS (type)T) because you don’t want the overhead or garbage associated with boxing and unboxing to occur. As you can see by the output and code, calling directly on the Generic Collections items allows you to avoid that.

The typical cost to the above is that at least most of the required data references across the classes or arbitrarily named data variables be declared in the base class. but not specifically that they be instantiated or allocated data which is very much design specific.

However as shown in the output the objectTypeName has been set literally by name in the constructor of each Type at instantiation and you could if absolutely neccessary, cast a Animal from the AnimalLovers list into that specific Type directly with a switch case statement based on the objectTypeName variable.

var a = animals[0];
string s = animals[0].objectTypesName;
switch(s)
{
case(“Lizard”):
var n = (lizard)(a);
n.TailWhip();
Break;
}

Note with TailWhip() we do something only a lizard can do, that is not callable for some specific reason from update or draw, or some other basic, animal decendant purposed base bridging method. WARNING! this basically could cause boxing unboxing of animal and could generate garbage so you want to avoid having to call TailWhip() by overriding Lizards update and calling it from there when required. A second base Update is also possible say one that takes a string as a command from the animal lover to the animals :slight_smile:

1 Like

Try it, profile it, question it. Be careful though, object inheritance can become an anti-pattern.

An AntiPattern is a literary form that describes a commonly occurring solution to a problem that generates decidedly negative consequences. The AntiPattern may be the result of a manager or developer not knowing any better, not having sufficient knowledge or experience in solving a particular type of problem, or having applied a perfectly good pattern in the wrong context.

The problem with object-inheritance for games is virtual tables and how it can cause CPU cache misses and CPU pipeline stalls. However, reader beware! We should forget about small efficiencies and only tackle the large problems which become evident by profiling; premature optimization is the root of all evil. What does that mean? It means optimizing before we know that we need to is a waste of everyones time and money.

Well to be honest i couldn’t tell you what pattern this would be off the top of my head or if its any at all.
You can look up the Gang of Four or find a full list of patterns to see if you can find one that fits perfectly.

The above does compile and work and it is simply a conceptual reference for virtual method and inheirtance usage.

While i leave lithium’s warning for you to consider on its own wisdom.

I would critically add that improperly understanding how boxing and un-boxing can occur when tackling a problem like this. Combined with not understanding which patterns were this can be a concern for the garbage generation and garbage collection that can occur from them. That could (definitely) be a serious and noticeable problem for a game to say a standard programming pattern could be anti-pattern for a game.

Keep in mind that most patterns were not explicitly designed to avoid generating garbage in a video game.

The problem is I really need to take the right way BEFORE coding, I don’t want a class holding all cases with this:

Object_Default[] _default;
Object_OnlyColor[] _onlycolor;
Object_LightnShadows[] _LightnShadows;

This is ugly, and maintenance will really be a pain with a lot of "if"s which I want to avoid.

This inheritance should be ok with VMTs (at least in my case) as there is only one type of item in the array, and types will be less than 5 I think with at most 2 levels depth inheritance.
Only the loadcontent method should be different by type, with some parts of update (effects settings), draw will be common to all.(Crossing fingers and toes, answer will be available after a profiling session)

You might be able to do this with interfaces as well its basically the same idea.

You could i suppose also keep all the basic data in a single class with static methods that return structs that are built out of only the data you require for just that type. Other non static methods that accept only that type of struct could assign only to the data members that are relevant to that corresponding type.

You would waste a little memory for a dictionary or list of those base data objects and might run the risk of cache hits if it got to bloated… but it would be simple. Though i guess that’s a alternative closer to your original example.

Here are a couple links to basic design patterns.

http://www.dofactory.com/net/design-patterns
http://www.dofactory.com/net/adapter-design-pattern

http://gameprogrammingpatterns.com/contents.html

I would choose a simple Base classes over Abstract classes or interface in this scenario ^ _ ^ y

    public class BaseMaterials
    {
        internal virtual void __Update()
        {

        }

        internal virtual void __Draw()
        {

        }
    }


    public class MatDefault : BaseMaterials
    {

        internal override void __Update(...)
        {
            // do your stuff
        }

        internal override void __Draw()
        {
            // do your stuff
        }
    }

    public class MatColorOnly : BaseMaterials
    {

        internal override void __Update(...)
        {
            // do your stuff
        }

        internal override void __Draw()
        {
            // do your stuff
        }
    }

    public class MatLightShadow : BaseMaterials
    {

        internal override void __Update(...)
        {
            // do your stuff
        }

        internal override void __Draw()
        {
            // do your stuff
        }
    }

////////////////////////////

    public class Entity
    {


        public BaseMaterials Materials;


        public void Update()
        {
            Materials.__Update();
        }

        public void Draw()
        {
            Materials.__Draw();
        }

    }

EDIT : I’m pretty sure Virtual function will not be the bottleneck on games application mostly it’s the rendering parts : - D

Welcome to software engineering.

You are approaching the limits of the C# language for games. C# 7 has neat stuff which might help you out, but even then there is a wall. For example MonoGame won’t adopt C#7 right now (for good reasons) so either you have to hack yourself or wait. I ran into similar problems when working on Entity Component System for MG.Ex. Stepping back and reflecting on this, I have some hunches why Microsoft “extinguished” XNA and told developers to use C++, but now only to “embrace” MonoGame (XNA) again. I also have some insights from studying Computer Science at university that give me this intuition that maybe Microsoft’s plan with open source is that they can evolve C# into the language to rule them all with instant feedback from smart people all over the globe who study compilers, A.I. philosophy, mathematics, language theory, etc. Maybe the short term goal is to evolve the language to one that is better suited for game development and web development. Sounds plausible, but who knows, that is just my opinion.

So your options are:

  1. Stick with MonoGame as is, learn software engineering, live with price that your game might not be highly efficient right now, and pray that advances in technology will make all your efficiency problems in the future disappear. You can find a lot of resources online but one I like a lot and that is free is Game Programming Patterns.
  2. Hack MonoGame for your needs to perhaps use C#7.
  3. Write parts of your game in C/C++ and interop with C#.
  4. Abandon MonoGame altogether and use C or C++ or some other language that better suits your requirements.

Honestly I think you should try option 1 first.

What exactly do you think would make C# better for programming games? I disagree with this design being an issue because of C# limitations. I do hope mixins make it to C#8 though.

Also, it’s not because MG itself is not using the latest C# version that you can’t use it in your game project (or libraries like MG.Ex for that matter).

Na there are a lot of ways to do it.
Just not a lot of ways to do it to were it both looks pretty and is efficient.

Your question is sort of a catch 22 because on one hand your optimizing. On the other hand your asking about making it prettier and simpler by condensing out these arrays.

However were you have separated the classes to optimize this originally. That has now caused a complexity a non optimization else-were or rather later which is now.

I think this is a case of (as Anders Hejlsberg might put it) “Simplexity” in that it can be either simple/pretty or complex/fast but not both in the same place. Then again Encapsulation is good for wrapping up complex ugly things in a pretty package.

Personally id stick the data for all 3 into a single struct that has generic data type names like Vector2 v0, v1, v2 int i0, i1, i2; ect… Id have a separate class or methods within it that grabs or places data as needed for each instance. Depending on a type id variable in each data struct. Even if all the data wasn’t needed for each type. Make a list of the structs or object instances use the id to switch case gets and sets. Provided this isn’t going to use a huge amount of memory. Problem solved pretty it up later move on.

Though i don’t know how big all that data is combined.

If the data was big and it was mostly not type dynamic data.

List manager = new List();
Class Manager
{
int typeID = -1 // not yet set -1 set on instantation or setting a object in;
Object_Default a;
Object_OnlyColor b;
Object_LightnShadows c;

// getters setters for each;
// problem solved
//
}

There are other ways to do it as well that are really ugly and fast basically make it all a struct or set of structs.
Again after it was wrapped you could make it look elegant to use.

Alternatively the really complex yet fast efficient route when the data really could grow very large. Encapsulated into a manager for ease of use with special methods. You could basically keep each object optimally sized and keep it fast. The cost is a lot of mental work and wrapping it later to be easy to use.

You could keep all 3 arrays for each type wrapped in a Manager class.
Make a tracking struct{ aWhichArrayID and Index }
put in a static list of them in the manager.
put one in each object;
put in a private static int indexCounter in the manager as well.
Each time you Added a object thru the manager or create a object thru the manager of a specific type
Increment the counter
Create a tracker.
Get the array Count for the trackers Index;
Assign the counter to the trackers ID and drop a reference to it into a self registering list of tracking structs.
As well when a type object is added to the manager add a tracker to the corresponding object to be inserted into the corresponding correct array.
Each object knows were it belongs in each array and you have a list of were each object is that you can iterate (little more to it, but that is the jist).
Ugly complex to look at on the inside of the manager but also fast and efficient.
Basically you create your own MultiType Non Generic Container
From the outside as seen from calls to the manager Prettied up with nice calls written as you go as needed to be perfectly practical.
Done problem solved but… that structural set up needs to be tested before implementation it needs quite a bit of thought and so it takes more time to code.

Support for data oriented design in C# beyond the reason of “legacy COM / PInvoke” is probably a good start. You can see Microsoft introducing some language support with this by ref returns in C#7. My point is that game developers / architects have different requirements and needs for a language then web developers. Game developers want or even need control over how memory is filled / layed out. Web developers not so much. Games have timing requirements. Web applications to some degree but usually are much more relaxed. Games are real-time applications, web applications not to the same degree. Sometimes garbage collection just gets in the way, sometimes that complexity is better handled by an A.I. My point is C# is nice language but there are definitely some pain points for game developers who have performance requirements. Take Nez for example: @prime31 toke the decision to not use C# properties (syntactic sugar for methods) at liberty because of performance requirements he wanted for his engine. I disagree with him however because it breaks the code guidelines we all come to agree upon which make it easier to read code (one of the philosophies we inherited for MG.Ex). Also as compilers get smarter they can inline most properties methods making the argument pretty moot, even debatable for reasons why getters and setters have been introduced in the first place. So yes, over time C# will probably become easier to work with for game developers, but until then…

C# as a RAD tool for desktop apps is amazingly efficient, and I understand some things must by locked under the hood to avoid “common” mistakes (malloc, destroy etc).
But I don’t want to abandon Monogame, as C++ with directx has a slower curve of development I think: just the initialization of the window is boring to code, models importation like it is done in MG’s pipeline tool is a big work, etc.

My problem is more a transposition of what I can/would do in C++ to C#. If we had pointers everywhere (not only on some types), class aggregations (in my case, classes with dedicated properties, which would be combined by aggregation to a complex object) etc, it would be easier. At least for me.
With C# I hesitate between a way using virtual methods, or choose a complete another way with delegates. And here I don’t want to spend 1 month testing one or another, I have little spare time to work on my engine, or else I’ll publish it with MG v7.0 and dx14 :confused:

On a side note, I avoid properties too, I don’t see the advantage but to permit other devs to only get a value or only set or both when sharing code/libraries. I saved about 5fps by removing them (over 280fps, it is minor but the gain exists)

If you are asking how you would set up a collection to simply use it to move through each element without using an array structure, simply put your objects into an ArrayList. ArrayList elements simply assume the type of object being stored in them.

With ArrayLists however, you can use multiple types but you will have to use a little reflection to extract information from each of the elements.

The sample code shown above that looks at this problem from the inheritance point of view is an excellent way to go if you like using this type of paradigm. However, inheritance has its drawbacks in that it is probably as inefficient as using reflection to any extent. And the more complex\heavy your objects are, the more inefficient inheritance becomes. In addition, anything beyond simple inheritance hierarchies often become unmanageable over time and this has been well documented over the years. Most large projects that use extensive inheritance have often become maintenance nightmares for its developers.

I am not saying do not use inheritance but just to be careful if you do.

The code I put together for you rather quickly below provides a somewhat primitive but simplistic method to do the same thing but using reflection. Reflection’s inefficiencies come from the need to for casting objects, which as other posters have rightfully stated forces the boxing and unboxing of objects.

Despite the inefficiencies of both paradigms, such inefficiencies are often not noticeable to the developer or user of an application until you begin working with large numbers of objects. Too often developers prioritize performance over common-sense coding techniques for small numbers of processes involved. The result is that a lot of effort is wasted on finessing internal efficiencies that often provide little advantage. Further, today’s compilers are so highly optimized that they will often make up for such optimizations no matter what paradigm you eventually decide to implement.

So for the code… I hope it helps… :slight_smile:

C# Main Class

using System;
using System.Reflection;
using System.Collections;
using System.Threading.Tasks;

namespace ArrayListOfObjects
{
class Program
{
static void Main(string args)
{
ArrayList ObjectArrayList = new ArrayList();

        Class1 loClass1 = new Class1();
        Class2 loClass2 = new Class2();
        

        ObjectArrayList.Add(loClass1);
        ObjectArrayList.Add(loClass2);


        foreach (object loObject in ObjectArrayList)
        {
            var loObject1 = loObject.GetType();

            switch (loObject1.Name)
            {
                case "Class1":
                    Class1 loNewClass1 = new Class1();
                    loNewClass1 = (Class1)loObject;                        

                    Console.WriteLine("String ID: " + loNewClass1.STRING_ID);        
                    break;

                case "Class2":
                    Class2 loNewClass2 = new Class2();
                    loNewClass2 = (Class2)loObject;                        

                    Console.WriteLine("String ID: " + loNewClass2.STRING_ID);        
                    break;
            }    
        }

        Console.ReadLine();
    }
}

}

C# Class1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArrayListOfObjects
{

internal class Class1
{

    internal Class1()
    {

    }




    string csStringID = "1";

    internal string STRING_ID
    {

        get { return csStringID; }
    }


    internal string Get_String1()
    {

        return ("my string1");
    }

}

}

C# Class2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ArrayListOfObjects
{

internal class Class2
{

    internal Class2()
    {

    }




    string csStringID = "2";

    internal string STRING_ID
    {

        get { return csStringID; }
    }


    internal string Get_String2()
    {

        return ("my string2");
    }

}

}

This may not be the correct solution for your problem or the best one, but give it a try and see if you can use anything from it. With a bucket you can even create typed buckets to avoid weirdness casting back, and only have to work on your Add to make sure everything goes in the correct bucket. You can also make it a Queue instead (all depends on your requirements).

class Program
{ 
    public abstract class BaseEntity
    {
        public string ClassId { get; set; }
    }

    public class ColorEntity : BaseEntity
    {
        public string Color { get; set; }
    }

    public class PlayerEntity : BaseEntity
    {
        public string Position { get; set; }
    }

    public static class EntityBucket
    {
        private static Dictionary<Type, List<BaseEntity>> _collection =
            new Dictionary<Type, List<BaseEntity>>();

        public static void Add<T>(T entity) where T: BaseEntity
        {
            Type t = typeof(T);

            if (_collection.ContainsKey(t))
                _collection[t].Add(entity);
            else
                _collection.Add(t, new List<BaseEntity> { entity });
        }

        public static List<ColorEntity> GetColors()
        {
            var t = typeof(ColorEntity);
            if (_collection.ContainsKey(t))
                return _collection[t].Select(s => s as ColorEntity).ToList();

            return null;
        }
    }

    static void Main(string[] args)
    {
        EntityBucket.Add(new ColorEntity { Color = "Red" });
        EntityBucket.Add(new PlayerEntity { Position = "X,Y,Z" });
        EntityBucket.Add(new ColorEntity { Color = "Black" });

        var colors = EntityBucket.GetColors();
        Console.ReadKey();
    }
}

I’m currently working right now on a Entity Component architecture for Monogame.
Unity is based on this architecture also.
This is an alternate approach to class hirerachy, where each component has its own state and behavior.
Surprised nobody mentionned it

1 Like

It’s essentially what I did by creating a base entity.

public abstract class BaseEntity

And every other entity inherits from it. It will weight on system communication and iteration, but that’s up to the architect and requirements to determine.

Just because you name a class ‘Entity’ doesn’t makes an Entity Component architecture :slight_smile:

With this architecture you are not supposed to inherit.
Here is couple article on the pattern:
http://www.randygaul.net/2013/05/20/component-based-engine-design/


http://www.chris-granger.com/2012/12/11/anatomy-of-a-knockout/

1 Like