I am currently working on a game engine for work and have hit a wall on my idea. I have multiple objects (called prefabs) that have very common properties such as Position, Rotation, and Scale. There are more, but let's just focus on those for this particular issue.

The idea was to create a base class called RenderObject in which these properties will live; however, there's an issue. Some objects in our engine can be rendered both in 3D and in 2D. I want to have a singular Render method for each object that handles both cases. Now, this was simple to solve as I can just create two virtual methods:

public virtual void Render() { }
public virtual void Render(CameraMode mode) { }

This makes it easy to render the objects the right way. Say for example I have a collection of 2D only objects; I can simply call Render for these objects and their 2D render code is executed. If I have a collection of objects that can be rendered in 2D or 3D mode then I just call Render(CameraMode) instead.

The issue lies with the properties; with DirectX 11 most 2D specific methods (such as DrawLine) require Vector2 objects for the positions. This is an issue for simplification if the base class only has Vector3 objects for the positions. I then have to grab the X and Y properties of the Vector3 and create a new Vector2 object every draw call. Instead, I went with the idea of creating a secondary base class called RenderObject2D that hides the Vector3 by returning a Vector2 instead. However, this is still an issue as this doesn't cover objects that can be rendered in 2D and 3D. I can implement the multiple Render method option and just render differently for the object, but then I have 2D objects that have unused 3D fields and properties such as the Buffer objects that aren't used in 2D.


Code Example

The current code isn't the route I want to go as I'm not a fan of hiding underlying properties. Typically you add to a base class, not take away.

// Currently 3D is perspective and 2D is orthographic.
public enum CameraMode { Perspective, Orthographic }
public class RenderObject {
    public Vector3 Position { get; set; } = Vector3.Zero;
    public virtual void Render() { }
    public virtual void Render(CameraMode mode) { }
    ...
}
public class RenderObject2D : RenderObject {
    public new Vector2 Position {
        get { return new Vector2(base.Position.X, base.Position.Y); }
        set { base.Position = new Vector3(value, 0); }
    }
}
public class Tree : RenderObject2D {
    // Can be rendered in 2D as a sprite and 3D as a model.
    // Current structure does not support this.
}

Is there a smarter way to accomplish this in a simplistic manner or am I stuck implementing the two different methods and just deal with the trade-off?

New contributor
PerpetualJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • You could turn RenderObject into an interface. – fstam Nov 9 at 16:28

Changing the type of a property in a derived class is going to be a maintenance headache. It's very confusing.

You also haven't saved yourself from creating Vector2d objects. Every time you retrieve RenderObject2d.Position, you're instantiating a Vector2d.

I would just do this:

public class RenderObject {
    public Vector3 Position3d 
    { 
        get => _position3d; 
        set
        {
            _position3d = value;  
            Position2d = new Vector2(_position3d.X, _position3d.Y);
        } 
    };
    private Vector3 _position3d;

    public Vector2 Position2d { get; private set; }

    public virtual void Render() { }
    public virtual void Render(CameraMode mode) { }
    ...
}
  • This is what I initially thought of doing, but wanted to avoid having multiple properties for different dimensions. I'm looking over documentation for other popular engines to see if I can find a consensus amongst them. So far it seems like most are focused on 3D and require the user to convert to 2D. – PerpetualJ Nov 8 at 20:59
  • Having multiple properties for 2d vs 3d is better than having multiple classes for it. – 17 of 26 Nov 9 at 13:01

Your Answer

PerpetualJ is a new contributor. Be nice, and check out our Code of Conduct.
 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.