GPF Docs

Hello World Tutorial: part 1 - Implementing ServerObjects

Hello World Tutorial: part 1 - Implementing ServerObjects

In this tutorial, we will create a ServerObject (or SO for short) called HelloSO whose state is simply a string field called greeting. The client will send a message with the word "World" up to HelloSO, and as a result our UI will automatically update to say "Hello World".

Getting Started

If you haven't done so yet, go through the steps on the Quickstart page to get Game Plumbing Framework.

The starter package that you imported comes with the HelloWorld project featured in this tutorial. To start from scratch by delete these folders from your Assets\GamePlumbing\ folder:

  • ServerObjects
  • Example

Setup the ServerObjects folder

1.Create a ServerObjects folder in your Assets folder from the Project window.

2.Navigate to Edit->Project Settings->Game Plumbing Framework and set Project Path to Assets\ServerObjects using the file browser.

Write SO

1.Right click on the ServerObjects folder you just created within the Project window and select Create -> GPF -> Server Object and name it "HelloSO".

2.Open it and edit it so it looks like this:

using GPF.ServerObjects;
namespace HelloWorld.SOs
{
public class HelloSO : ServerObject
{
public string greeting = "What's your name?";
public class MyNameIs : ServerObjectMessage {
public string name;
}
public override SOID ID { get; set; }
}
}

Write SO Test

1.Create an Editor folder in your Assets folder

2.Right click on the ServerObjects folder you just created within the Project window and select Create -> -> GPF -> Server Object Test and name it "HelloWorldTest"

3.Open it and edit it so it looks like this:

using HelloWorld.SOs;
using GPF;
using GPF.ServerObjects;
using GPFEditor;
using System.Threading.Tasks;
using NUnit.Framework;
namespace HelloWorldTests
{
sealed class HelloWorldTest : ServerObjectTest
{
public override async Task Run()
{
// Create a syncer
var syncer = CreateSyncer("default");
//get an ID
var helloSOID = Registry.GetId<HelloSO>();
// get reference to helloSO
HelloSO helloSO = await syncer.Sync(helloSOID);
// Let's tell the SO our name so it can say hello to us.
// Note await syncer.SendUpdateWait doesn't return until the SO is updated.
await syncer.SendWait(helloSO, new HelloSO.MyNameIs { name = "World" });
// Now let's check to see things went as planned.
Assert.That(helloSO.greeting, Is.EqualTo("Hello World") );
}
}
}

Developing HelloSO

To run the test:

1.Open Test Runner in the Unity Editor by clicking on Window-> General -> TestRunner.
2.Right Click on HelloWorldTestinside of Test Runner and select Run.
3.Observe that the test fails with the message.

System.Exception : You need to register type ServerObjects.HelloSO with the [Register()] attribute

4.Every ServerObject needs to be registered with a string that allows the system to associate IDs to Server Objects. Let's insert a line to do that on line 7 of HelloSO.cs so it looks like this:

namespace HelloWorld.SOs
{
[Register("hello")]
public class HelloSO : ServerObject

5.Now re-run the test and observe the Exception in the test console:

Syncer.GetServerObject Trying to sync not non-Syncable: hello/wPCpG8wXg99Y-59ZXbUOD3ftuf6EwJCQqBkCy2pvDMQ_ with type HelloSO

This occurs because on line 18 we called this code

await syncer.Sync(helloSOID)

6.Here we are attempting to sync to a HelloSO. By default, the client can not sync to SOs. Enable this functionality by adding the [Syncable] attribute to the class, so it now looks like this:

namespace HelloWorld.SOs
{
[Syncable]
[Register("hello")]
public class HelloSO : ServerObject

7.Run the test and observe the Exception:

Expected: "Hello World"
But was: "What's your name?"

8.This Exception is being thrown by the NUnit test framework and occurs because we haven't implemented the logic to set greetings yet. Add a Handler on line 14 of HelloSO that looks like this:

void Handler(MyNameIs message)
{
greeting = "Hello " + message.name;
}

Now, this line of code from the HelloWorldTest:

await syncer.SendWait(helloSO, new HelloSO.MyNameIs { name = "World" });

will cause the new SO handler to be triggered and greeting to be updated.

9.Run the test and observe the Exception:

at HelloWorldTests.HelloWorldTest+<Run>d__0.MoveNext () [0x00125] in Assets\Apps\HelloWorld\Editor\HelloWorldTest.cs:25
--- End of stack trace from previous location where exception was thrown ---
...
---
Connection 1 open with connect time: 00:00:00.0739987. backlog: 2
hello/EtcuCK5qwl...:Method with params ServerObjects.HelloSO+MyNameIs not allowed to handle messages from WSS_CLIENT.
...

this test still doesn't pass and this line in the list of exceptions tells us why

ServerObjects.HelloSO+MyNameIs not allowed to handle messages from WSS_CLIENT.

It's because, by default, SOs don't handle messages from the client, so our handler was never run. 10. Enable this ability by adding the [FromClient] attribute to the method. Once you do that, your test will pass and the full class will look like this:

using GPF.ServerObjects;
namespace HelloWorld.SOs
{
[Syncable]
[Register("hello")]
public class HelloSO : ServerObject
{
public string greeting = "What's your name?";
public class MyNameIs : ServerObjectMessage {
public string name;
}
[FromClient]
void Handler(MyNameIs message)
{
greeting = "Hello " + message.name;
}
public override SOID ID { get; set; }
}
}

Run the test again and it should turn green.

Deploy SO

ServerObjects are made to be developed using a mock cloud, until they work, and at which point they should be deployed and ran remotely. In order to demonstrate this, we must now deploy our SOs.

Simply go to the Unity Menu GPF -> Deploy Server

Test SO Remotely

1.Now that the SO is up, switch to remote mode: In the Unity editor, go to GPF -> Settings and set Backend Type to Cloud.

2.Clear the DB: in the Unity editor, go to GPF -> Clear Remote DB

3.Run the unit test again and observe it turn green on the server.

Congratulations! You've just built and deployed a ServerObject.

© 2023 Launch It Labs INC