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?
-
You could turn RenderObject into an interface.fstam– fstam2018年11月09日 16:28:34 +00:00Commented Nov 9, 2018 at 16:28
1 Answer 1
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.Taco– Taco2018年11月08日 20:59:26 +00:00Commented Nov 8, 2018 at 20:59
-
Having multiple properties for 2d vs 3d is better than having multiple classes for it.17 of 26– 17 of 262018年11月09日 13:01:50 +00:00Commented Nov 9, 2018 at 13:01