13. GameObject<T…>

  04. Features No Comments

The generic GameObject structs are builders that can be used to initialize a GameObject and upto three components in a single line of code.

If you want a GameObject with a single component to be build, initialize a new instance of the GameObject<T> struct and specify the type of the component you want attached to the GameObject as the generic argument.

new GameObject<Camera>();

Optionally you can customize the state of the created GameObject, such as its name, parent, active state, position, rotation and scale.

new GameObject<Camera>("Camera", transform);

To finalize the building process you also need to call Init() on the GameObject<T> instance or cast it into a GameObject or the type of the created component.

Camera camera1 = new GameObject<Camera>("Camera 1").Init();
Camera camera2 = new GameObject<Camera>("Camera 2");
GameObject camera3 = new GameObject<Camera>("Camera 3");

If one of components being initialized derives from a MonoBehaviour<T…> base class or implements an IArgs<T…> interface, then it is also possible to pass dependencies to the component as arguments of the Init function.

For example, let’s say we had we had the following IInputManager interface and class that implements the interface:

public interface IInputManager
{
   Vector2 Input { get; }
}

public class InputManager : IInputManager
{
   public Vector2 Input
   {
      get => new Vector2(Input.GetAxis("X"), Input.GetAxis("Y"));
   }
}

And let’s say we had the following Player class that can be initialized with IInputManager and Collider arguments:

public sealed class Player : MonoBehaviour<IInputManager, Collider>
{
   public IInputManager InputManager { get; private set; }
   public Collider Collider { get; private set;}

   protected override Init(IInputManager inputManager, Collider collider)
   {
      InputManager =  inputManager;
      Collider =  collider;
   }
}

Then we could create a new instance of the Player component and initialize it using the following syntax:

IInputManager inputManager = new InputManager();

Player player = new GameObject<Player, BoxCollider>("Player")
                                .Init1(inputManager, Second.Component);

The Init1 function tells the builder to initialize the first added component, i.e. the Player component, with the provided arguments.

The Second.Component token instructs the builder to pass the second added component, i.e. the BoxCollider, as the second initialization argument.

In this case you can skip calling the Init2 function of the builder, since only the first added component accepts initialization arguments.

If the generic arguments were reversed the syntax to build the same GameObject would look like this instead:

IInputManager inputManager = new InputManager();

Player player = new GameObject<BoxCollider, Player>("Player")
                                .Init1()
                                .Init2(inputManager, First.Component);

You always have to invoke all the Init functions in the same order as the component types have been defined in the generic arguments of the GameObject builder. Because of this you now also have to call the Init1 function to initialize the BoxCollider component, even though it does not accept any arguments.

Leave a Reply

Your email address will not be published. Required fields are marked *