Monday, July 15, 2013

Radical Changes

I'm making some radical changes to the development path I'm on.  I've had an increasing number of small but extremely irritating and time consuming problems with the game client.

I've decided that I just don't have enough time to work a full rendering engine as well as the back end servers, database and game administration projects.  So I'm taking a new path with the most troublesome, the game client.

I've decided to port the client over to Unity.  I'd been playing with Unity a bit lately as my daughter was doing some 3d modeling and animation.  She wanted to put her creations in something and use them.  At first I thought about compiling them into a cut-down version of the Step2GameEngineWithoutAName.  But that'd take time, and would be fragile, etc...  So I downloaded Unity, and away we went.  It's an extraordinarily slick package, everything my game engine wanted to be.

I noted a lot of similarities, they're both data driven entity/component systems at heart.  In both cases there is an abstract 'game object' that has various components attached to it which define its behavior.  There is some divergence there, however.  The Step2SimEngine uses the Artemis entity system and maintains a pretty pure separation of data (components, data with zero logic) and logic (systems, which have the logic work on components).  Unity munges this all up in the components, more or less.  I don't know if that is better or worse.  Really with the nice visual editor and the ability to edit data right in the components, it isn't bad.

So I've given myself a few days to move things over and prototype things in Unity.  If it works, I'll go with it, if not I'll have only lost a few days.

Thus far it is going quite well.  I was able to move the Naginata client networking component over and get a test Unity level connecting and logging in to the servers in about twenty minutes.

A day later I had a MasterControl, SceneControl and CustomSceneControl set of classes written that talked to the network client and controlled the flow of the game (level/scene loading, etc).

After about two days I am almost back where I was with the XNA client.  I've got the Login screen, then the 'Temporary Hanagar' screen where you can pick a ship type and a battle to join.

At that point you can join a zone, but I discovered a problem.

What was happening was that the client would send a REQUEST_JOIN_ZONE to the server system, which would join the player to the requested zone and reply with success/failure.

The client, on getting the JOIN_PLAYER_REPLY would start the next scene and reply with ZONE_READY_ON_CLIENT, and begin processing.

The subtle bug in here was that when the Zone Server got REQUEST_JOIN_ZONE and everything was fine, it flagged the player as belonging to that Zone Server, and its outbound JOIN_PLAYER_REPLY(success) told the Border Server in question to route between the client and the Zone Server.

The problem is that the Zone Server immediately flagged the player as belonging to it, and then fired off the 'ok' reply.  Meanwhile, the client has NO IDEA that it succeeded or failed, and is still hanging in it's old zone, waiting.  It hasn't been told that it has moved successfully yet.

The Zone Server sees this new client on the next update and says 'Oh, a new client joining, let me do a data dump to him of all my applicable simulation entities...'.  Thus the poor client gets a (maybe) deluge of entities which don't actually belong to the scene it is in.  Well, these arrive more or less simultaneously with the JOIN_PLAYER_REPLY message telling it to advance to the next scene.

Now, this doesn't break anything, but it does cause objects to briefly spawn and appear that don't belong.  Generally very rapidly the client processes the JOIN_PLAYER_REPLY  and move to the next zone.

However the zone loading takes measurable time, during which these incorrect entities briefly pop into existence and display.  They are killed almost immediately, but it is still noticeable.

I suppose due to the way the scene handling was done on the XNA client I simply never noticed it.  On the Unity client it holds the old scene in memory while loading the new one, so you would briefly see the two co-exist.

In any case this was wrong, so I dove back into the server code.  Now both the ZoneServer and BorderServer sort of provisionally store the user's zone request and don't actually consider them added until they receive a ZONE_READY_ON_CLIENT, which is only sent when the first scene is purged and the second fully loaded.  That seems to have completely solved it.

No comments:

Post a Comment