GameServices

Hi, could someone please explain simply how to turn a GameComponent that I've written into a GameService that can be accessed by any GameComponent. i.e. What class needs to implement IMyGameService What should it expose How do I go about registering my service with the Game. A link to a thread/article or a new explanation that explains this would be great. I've seen a few half-explanations around, but nothing full. Still, a concise but thorough summary would be the best. Thanks a lot...

Answer this question

GameServices

  • Ravi Nidhonkar

    That's alot of code to accomplish what should be a simple thing. I don't use the provided services architecture, since I have my own scene graph, but here is how any component that needs the camera service can find it in my code:

    ICamera camera = this.Directory.Find<ICamera>();

    If you have to write two or more extra classes and several methods for every service you wish to use (CameraService, CameraProvider ) then you will end up doing more "plumbing" then programming.


  • dotnetorjava

    A GameService is a GameComponent that needs to expose functionality that other GameComponents need to use.

    Take a look at this: http://www.openxna.net/node/60



  • Chaseman

    Thanks very much for all your answers - leclerc and Kris especially. I'll take a look at it all asap.


  • PiGuy

    In my component model, all components are added to the "graph", and then the graph is "Initialize()'d" and begins running. Only after initialization are components allowed to try and get a reference to another component (or service) that they are dependent on. If a service they need is going to be available at all, then it will usually be available at initialization time. This gets rid of the need for any "ServiceCreated" type of event (like your CameraCreated event). If the camera (or any other service) they are dependent upon is removed or replaced, then the object will be disposed. The consumer of the service is expected to check for disposal and re-acquire before using any retained reference. I use this pattern for that:

    ICamera camera; // retained reference.
    ICamera Camera // property used internally to get the service
    {
         get
         {
             if (this.camera == null || this.camera.Disposed)
                 this.camera = this.Directory.Find<ICamera>();
            return this.camera;
        }
    }


    Doing this removes the need for any "ServiceChanged" type of event, and therefore gets rid of the whole need for a "ServiceProvider" interface. The Service IS the Provider.

    Furthermore... what happens when you run a split screen game, and there are suddenly two or more cameras How does a component find the right camera using the simple one level deep service model you are using In the model I'm using, you will find the first ICamera implementation that is registered with your component, or any of your ancestor components. So components can find the appropriate services based upon where they are defined in the scene graph.

    Hope this answers your question. Like I said above, I'm not using the built-in service model.

    (Once again, whenever a service (any component) is removed, it's disposed.  Since consumers check this before usage, it handles the critical "referenced changed" issue you mentioned, and without requiring an intermediate class.)

  • Byenary

    Maybe this article will help you: XNA GameComponents and GameServices.

    It's a short crash course to the GameComponents/GameServices concept and explains how the GameServices work to let GameComponents interact with each other. At the end of that article, there's some example code containing a GameComponent that publishes a custom GameService.

    -Markus-



  • Jacob Pettersson

    I'll give you an example from my engine for creating a camera service since the linked example leaves a couple of important things out. One method for adding a camera to components that use one  would be to make public properties for each component and hook the camera to each of them in the component design view.  However, this can get tedious if you have many components that use the camera.  A cleaner method is to create a service that provides the camera and updates components when the camera changes or is created.

    Here is my camera class that is used by many components:

    public abstract partial class Camera : GameComponent
    {
        public abstract Vector3 Position
        {get; set;}
        public abstract Matrix ViewProjection
        {get;}
        public abstract Matrix World
        {get;}
    }

    The world matrix is nullable because most cameras don't change the location of objects they look at.

    Next, I need to create an interface for a service that tells camera-using components when the camera is created, when it is changed, and gives a way to access the camera.

    public interface ICameraService
    {
        event EventHandler CameraCreated;
        event EventHandler CameraChanged;
        Camera Camera {get;} // null if the camera has not yet been created
    }


    Afer defining the means by which components will access and receive updates about the camera, we need to create a class that provides the service:

    public class CameraProvider : ICameraService
    {
        private Camera cam = null;
        public event EventHandler CameraCreated;
        public event EventHandler CameraChanged;

        public void AddCamera(Camera cam)
        {
            if (this.cam == null) && CameraCreated != null)
            {
                this.cam = cam;
                CameraCreated(this, new EventArgs());
            }
            else
            {
                this.cam = cam;
                if (CameraChanged != null)
                    CameraChanged(this, new EventArgs());
            }
        }
            public Camera Camera
            { get { return cam; } }
    }

    Before I go on, I'll say that there are a number of ways deciding on how objects are added to your service and when to add the service to your game.  Should we add the service to the game in the constructor   Should the game add cameras to the service, or should each camera add itself to the service when created   You will have to answer these questions yourself, but I prefer to create the service in the games constructor and add each camera to the service in the Start() method of the camera.  Note that if you ever want to change cameras, you will have to do that outside the Camera class since Start() is only called once.

    So, in the Camera class, we can add this:

    public override void Start()
    {
        base.Start();
        CameraProvider provider = (CameraProvider)
                                   Game.GameServices.GetService<ICameraService>();
        provider.AddCamera(this);
    }

    And in the Game constructor:

    public MyGame()
    {

        CameraProvider camProvider = new CameraProvider();
        GameServices.AddService(typeof(ICameraService), camProvider);
        InitializeComponent();

    }

    Now, we have created the service and added it to the game before it starts.  One question is left: how do we use the service   Here is a simple class that just prints the position of the camera every frame:

    public partial class CameraUser : GameComponent
    {

        private ICameraService cam;
        public CameraUser()
        { InitializeComponent(); }
        public override void Start()
        { cam = Game.GameServices.GetService<ICameraService>(); }
        public override void Update()
        {
            if (cam.Camera != null) // could also subscribe to service events and store reference to actual camera
            {
                Console.Clear();
                Console.WriteLine(cam.Camera.Position);
            }
        }
    }

    I could create a whole variety of cameras that inherit Camera, and they would automatically be added to the games cameras ervice for use by any component that needs a camera (model viewer, grid, etc.). 
                


  • rwbogosian

    Ok, it's a way of doing things, but I was modeling my service after the IGraphicsDeviceService that is shipped with XNA, because I agree with the principle that adding a layer of abstraction to certain services is beneficial.  The built in IGraphicsDeviceService has events for when the device is changed or when a new device is created.  I feel strongly on the advantages of adding an extra service provider class in this case, since it adds no plumbing (once the class is created, I'll never have to look at it if I don't want to change the implementation), and the events can certainly be useful (i.e., i can choose to later add tags to cameras that determine what objects should use them., and are without a doubt more powerful than forcing each client to keep track of the camera (in my engine, I have a class that changes its state when an arcball modelview camera is loaded).  I believe that these 13 lines of code do far more good than harm.  Unfortunately, any further discussion on this subject will stray too far from the post subject, but I feel it is necessary in this case to point out that my example follows standard protocol for services, and exemplifies a way to make a similar component to the commonly used IGraphicsDeviceService.
  • Alex Stevens

    @leclerc9

    Very nice example. Thanks.



  • terryhohoho

    ICameraService is an interface, not a class.  Camera provider implements this interface.

    The camera class is the class that is being provided to clients, and you can't directly add that as a service since it is not guaranteed to exist at all, and the reference can change.

    I'm not sure what you are getting at here, this seems to be the min-threshold to achieve what game services were intended for.  I have one class for the service provider and one class for the object that the service provides.  All you need to do to get the service in my example is call:

    GameServices.GetService<ICameraService>();

    I'd be very interested in seeing your simpler version.

  • GameServices