Friday, May 27, 2016

VR

Well, it's been a while since I've posted anything.  The primary reason?

My Vive finally arrived.  It is quite amazing.  I have to say that it definitely lived up to the hype.  Also I'm glad that I spent the extra on the Vive rather than a Rift.  I think the 'room scale', and especially the hand controllers add a lot to the experience.

Besides playing lots of VR games and whatnot, I've been experimenting with SteamVR in Unity.  There are a lot of difficulties around locomotion and motion sickness, though you can pretty well mitigated them, it seems.

I'm fiddling with a bit of a branch of Jumpship, more oriented to piloting a single ship ala World of Warships.

Thursday, April 21, 2016

Avoiding Code Coupling: Messaging Systems

A pretty common feature of, well most any game, is clicking on some object to select it or get information about it. Or mousing over it for a tooltip, etc. In whichever case there needs to be some connection between the visual game object displayed, and the behavior and data behind it.

Tuesday, March 29, 2016

Unity Project Organization: MasterControl and SceneControl

As I said in the previous post the way I design my scenes revolves around the MasterControl and SceneControl classes.

The MasterControl is the omnipresent 'god object'; it will persist through every scene in the game.

A SceneControl object is the controller for a single scene.  This is where you'll find the logic for setup/teardown of the scene, as well as data that needs to be centralized or persisted during the scene.

Thursday, March 17, 2016

World of Warships

I've gotten pulled into playing World of Warships with some friends.  Pretty enjoyable, and I've always had an interest in naval history.  As a kid I always had those big picture books 'Battleships of WWII' and the like around, so it is right up my alley.

I'm considering recording some games and throwing them up on YouTube.  I have a channel where I've occasionally put demo videos for projects I've worked on.

Or, I could just play and not bother doing any actual work.  Hm.

Tuesday, March 15, 2016

Unity Project Layout, Part Three: Logical

Apart from having discreet scenes, Unity pretty much has no 'opinion' on the logical organization of your program.

There isn't a lot written on this that I can find (ok, online, maybe there are print books).  Most of the advice is general, but sound: Separating interface from game logic (I'd go further and say you should separate game-state from game logic as well).  Name things clearly.  Etc.

There's a lot on folder structure, but not on game structure.  I'm not necessarily talking about the gameplay code (platformer vs real-time-strategy vs RPG, etc).  What I'm going to ruminate about is the structure around that; handling startup, state,  game data, save data, etc.

And, as always, everyone has there own way that (probably) works for them.  This is simply how the manner I've deal with these issues has evolved.


Tuesday, March 8, 2016

Unity Project Layout Part Two: Physical

Unity, when starting a project, creates a bunch of folders in the root project directory.  The only one we typically concern ourselves with is the Assets folder.  That's the folder where all of our, err, assets go.  Scripts, models, textures and so forth.

So really when we are talking about how a Unity project is laid out on disk (which seems an odd archaic reference, since I'm using an SSD these days), we're talking about the Assets folder.


Monday, March 7, 2016

Unity Project Organization Part One: N+1 Different Answers

I believe there are two topics at the root of a discussion of Unity project structures.  These are:  file organization and game (code) organisation.

Note that this is all simply my opinion, mostly based on a slow evolution through several projects.  That, and many years of general software development practice.

You'll find as many opinions on this are there are people offering them (someone posted on the Unity forums that "If n people reply to this thread, you're going to get at least n+1 different answers. ;-)").  As an aside, here is a decent article that has some opinions on the subject:  50 Tips for Working with Unity (Best Practices).

Sunday, March 6, 2016

JumpShip

So:  JumpShip.  A crunchy space empire game inspired by Starfire, Aurora and perhaps a bit of MOO and its various descendants.

I've spent quite a bit of time over the last month or so laying the groundwork.  My Mercurial repository shows the first commit 5 weeks ago.  Pretty steady work until the great-food-sickness struck myself and my daughter (hereafter known as the Stainless Steel Brat) down for about three days each.  Not fun.

Anyway, I'm pretty pleased with the progress I've made.  Its still pretty rough, and missing a lot, but the basics are there.

Over the next serveral days I intend to do a series of posts detailing the hows and whys, of what I've done.  This will be for my own future reference, as well as (hopefully) useful material for anyone who might want to undertake the same sort of project.  Possibly just generally useful programming and design tips.

I think I'll proceed in something like the following order:

  • Structure:  How I lay out a Unity project.
  • Planets-A-Go-Go:  Star, planet and moon orbits in a thousand star systems without meltdown.
  • Setup Data:  Or:  How DO we keep all our setup data out of the executable?


Well, I can think of a dozen other interesting things, but I'll start with those, I think.

Saturday, February 13, 2016

So It Has Been A Long Time...

...since I posted anything here.

Quite a lot has gone on; moving, various work adventures, my daughter graduated from college and moved in, etc.

For quite a few months I stopped doing any work on my side projects (Retrograde, etc).    That said, I have done a few things, and have started back working on a new project.

Thursday, February 19, 2015

Combat And Problems Therein

CombatMover Components
I finally worked my way through a problem that I'd been skirting around.  This had to do with combat, ship statistics, and the links between those two.

Ships exist in the general game structure as Ship objects, which have a Class (which describes size, item loadout, hit points, etc) and a Pattern (describes the actual 3D model used and thus turret and item placement).

Meanwhile, in the combat scene there was an extensive set of prefabs spawned for each combatant.  This was a prefab loaded up at runtime that included the following components:





Component Use
Box ColliderVery tiny, needs to be on root object in order for collision events from colliders on model to bubble up
Rigidbody Sets the physics system mass of the unit
Base Combat MobDerived from BaseCombatObject.  This is pretty much the basic info needed to exist on the board.  BaseCombatMob extends BaseCombatObject, adding thrust/speed/etc. ...Object would be a largely static object
Selectable ObjectHandles clicking or drag selecting of the unit.  Also highlighting on mouseover
Highlightable ObjectFrom 3rd party Highlighting system.  Makes the visual effect work
Orderable Objectllows a unit to receive commands.  Requres BaseCombatMob and SelectableObject.  Without this a unit could do things, but not get external input.  I.e. it could be a mine or a missile or automated turret
Base Combat ExecutiveMain decision maker.  Given a target decides what to do.  Friendly?  Follow and fire on it's target.  Enemy?  Move toward it and attack it, etc.
Area Target Tracker 3rd Party TriggerEventPro item.  Vastly superior replacement for my original target detection code.  Basically detects, sorts and categorizes targets that have...
Targetable 3rd Party TriggerEventPro item. Component lets target trackers know this is (or may be) a valid target for the system
Ignore ModifierTriggerEventPro again.  May hold a list of targets that will be ignored
Base Fire DirectorGets targets from BaseCombatExecutive, or if none chooses available targets.  Direct individual weapon mounts to track individual targets.  Note that I may make a variant of this a Defense Fire Director, that will work only on point defence type weapons and ignore all else

So, that's quite a lot of moving parts. That isn't even counting the code for, say, turrets rotating and tracking their targets.  Or ship movement behavior (to targets, to waypoints, etc.) or local avoidance for ships (i.e. don't run into other ships, or static objects like asteroids etc.)  Oh, and all the visual effects and particle systems for the actual weapons fire.

Anyway.

All of that worked smashingly.  The Combat scene generated all the ships it was told, you could click them and move them around, and they'd target enemies and fire nicely.

However this was really just window dressing.  Sure the turrets tracked the enemy objects and sent out projectiles and laser shots.  But none of it had any actual effect... the actual ship stats were in no way linked with the live objects being spawned (other than ship name, owner and number of ships).

This was where I bogged down for a couple of weeks.  There was a lot needing to be done connecting the dots.  When ships objects were spawned, it needed to look at the linked game-data-ship and get the appropriate info.

The first item I addressed was choosing the right model  I'd just been using a default hard-wired one at first (well, just cubes and capsules at the VERY first).  Now you needed to look up, based on the ship's class and find it's Hull Pattern (for each size of ship, destroyer, heavy cruiser, battleship, etc there may be multiple Hull Patterns, which determine the model and weapon layout.  So two ships might both be battleships, but look and behave slightly differently).  The Hull Pattern has a path to another prefab, this being of the model to load.  The model prefab also includes markers for where weapons and equipment are mounted on the hull.  These can be bones from the 3D modelling program used (i.e. Blender), or empty game objects tacked on later.  I started with the former but have switched to the latter largely.   They both amount to the same, but the latter is easier.

Hull Pattern editor screen.  Ignore the funny gun on the front;
the missile launcher item there simply isn't defined yet.


So now we have the physical model with the orientation and location of item mounts.  Note that orientation is important.  Think of a sea-going battleship.  Some turrets point forward, some aft, some even to the sides.  So like I said, you have to track starting orientation as well as position.

 Now comes a tricky part.  You need to link up SPECIFIC weapons on the ship with SPECIFIC objects on your model. That's to say that specific weapons go on specific turrets, and are limited by the turning arc and speed of that turret.

When a ship class is made (the in-game editor for that isn't done yet, thus far starting ship classes are ginned up by code), each 'module' of equipment the ship gets has a mount point.  I named this 'WeaponMount', but that's a bit of a misnomer as it could be any item, not just a weapon.

The trick to all of this is that in the database (static game data is stored in a in-proc SQLLite database) there's tables HullPattern, WeaponMount and ShipPartResource.  HullPattern is basically just a list of the available HullPatterns, plus stat modifiers, etc.  Oh, and the resource path to load up the model associated with this HullPattern.

WeaponMount entries are keyed to a specific hull pattern.  WeaponMount covers the item's display name, the ModelBoneName (which must match the empty gameObject marking the position on the model), min and max fire arcs, turret turn speed, etc.  It also has a reference to ShipPartResource.

ShipPartResource is basically a name and a resource load path.  It might point to a specific turret, or radar antenna model, etc.

Combat screen. Three on three battle.
So knowing the ship Class you know the HullPattern.  Then you can iterate all the equipment modules on the Class and find the matching WeaponMounts.  Then get the ShipPartResource for that mount and bingo, you can now attach a certain turret model to a certain location of the ship model.  Oh, and then knowing the type of weapon you select a specific visual/audio effects emitter and stick it on the barrel of the turret and link that to the Fire Controller.  The ship's Fire Director component also needs to be informed about every weapon mount created so it can tell it where to target.

There is another component that gets added here, CombatShip.  Basically this is the realtime combat information for the game-data Ship entity. This is where the connection between a specific equipment item in the ship's class and a specific gun turret are made.  Not only physical position, but things like fire rate, accuracy, etc. are calculated here.  For example crew quality affects accuracy.  Weapon quality also affects accuracy, etc.

To it took a lot of work to connect all the dots.  But now ships move around based on their data, and their weapons fire at the correct ranges and rates, doing the correct amount of damage.

It's really pretty to watch.  The movement, weapon effects and sounds are really good so far, I think (note though I have a lot of work in the future on pathing and movement behavior)

Lighting in Unity 5 is very nice.  I'm really liking PBR, even if the texture setup is a bit more work.



Thursday, February 5, 2015

Retrograde

So, no posts in an awfully long time.  I have been working on things, though.

As summer (2014) rolled around, I'd more or less stopped working on Rogue Moon.  I came to the conclusion that 'World of Tanks in Space' was just way, way too much for me to bite off on my own.  It just wasn't ever going to happen, or at least not with any quality.

After a bit of thinking, I decided to take on something far less ambitions.  So I came up with the idea for 'Retrograde', which will be a 4x space empire building type game.





First, why 'Retrograde'?  Well, it is kind of space-y, the opposite of your orbital direction.  Also, it represents kind of a step backwards from an overly ambitious project to something accomplishable.

 My initial idea for the game is to give a space 4x empire builder the same sort of treatment that XCOM:Enemy Unknown gave the... well XCOM genre.  Clean and approachable, simplified down to it's important elements (but no simpler!).  Every decision should be important, and there shouldn't be too many moving parts.  Ideally you'd have no more than 20-30 units

Too many strategy games confuse 'complicated' with 'deep', I think (and sometimes 'frustrating' with 'difficult'.  IMHO this was one of the things that sank Sword of the Stars II, for instance.

I'd like the game to be a bit story driven, and have a lot of character.  Too often games in this genre feel more like spreadsheet/bureaucracy simulators.  I can never spell bureaucracy right the first time.  Or the second, it appears.

Style wise I intend to pull heavily from 30's serials.  Flash Gordon, Buck Rodgers, etc.  I'd like the artwork to have a very stylized Art Deco sort of look (though right now it's very simple and clean, something I'd like to keep, too).

I've been working away quietly on Retrograde, and have made good progress.  The framework of the game has really taken shape, and I'm pretty pleased so far.

Tuesday, September 10, 2013

Server Updates

Temporary Login/Title Screen
So, after having good success moving the client to Unity, there were still some issues.

My primary concern was that there were now two physics engines involved:  BEPU on the server, and an old version of PhysX which Unity was running as the client.

Now, I wasn't certain that this would cause problems, but I'd done some fairly deep dives into the quirks and behaviors of BEPU, so it seemed pretty likely.

It would have been really nice to be able to use the Unity engine from the Zone Server.  If there was some way to simply include it as a DLL and run it, that would have been fantastic.  This is a familiar refrain you see all over the Unity forums, particularly the networking on.

Sadly you can't, of course, and I'm not surprised.  So, one would think that-would-be-that.

Tuesday, August 13, 2013

New Posts Soon

I've just finished moving, and let me say that if I don't do that again in a long time it will be too soon.

Anyway, quite a lot of interesting dev work has happened in the last week or so, but I've been too busy packing and moving to write anything.

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.

Monday, July 8, 2013

A Tiny Slice of DLL Hell

So I've begun preparing for a little ultra-pre-Alpha.  No real gameplay, just a test of the networking and physics.

In order for this to proceed, though, I naturally had to test to make sure the client would work on other machines.  Also I wanted to run the servers on another machine as well.  Everything worked fine together on my Dev box... but you know how that is.

Saturday, June 1, 2013

Physics Mismatch... of Bepu Physics and Small Rotations

So I've been working on syncing the physics between the client and server implementations.  It's been... a bit painful.

Varying Update Rates Hertz a Lot

One of the first things that tripped me up was the different update rates.  The client is running at the regular 60 fps, i.e. updating every 0.016ms.   The server is running a much more sedate 10 updates per second, or every .1ms.

I had assumed that passing the delta time into the physics simulation would deal with the difference.  I.e. it would know either one sixtieth of a second or one tenth of a second had passed, and simulate that amount of time passing:

physicsSpace.Update(elapsedMilliseconds);

First, this was WRONG, and a very common mistake!  Turns out Bepu wants the time in seconds, so really I'm telling it to simulate x1000 speed!  This is correct:

physicsSpace.Update(elapsedMilliseconds/1000.0f);

Why didn't I notice this right away?  Well, it turns out Bepu has a default timestep for its simulations, which happens to default to 1/60th of a second.  And it will only perform a certain amount (default three) physics steps per update.  So by default Bepu will simulate .005 seconds of time (3x0.016), maximum, per Update call.  Mind you, these are quite sensible numbers for defaults.

So really when I was passing in weird values like 16 (16 milliseconds, 1 frame at 60fps) I was actually asking it for SIXTEEN seconds.  In return it gave me 0.05 seconds, which is near enough to .16 that by the naked eye I couldn't tell the difference.  On the server it was getting 100 (100 milliseconds, the update period at 10 fps), so it though I was asking for a bit over a minute and a half...

So, problem number one was I was passing milliseconds rather than seconds.  The defaults were ok for the client, but clearly the server running at 10hz would still be wrong.  Each update would need to simulate 100 milliseconds of time, but by default Bepu would only step 50 milliseconds.

Easily fixed by a bit of reading through the docs and forums, however.  You can change the maximum number of timesteps simulated:

physicsSpace.MaximumTimeStepsPerFrame

... though I did not change this.  Really you want a one-to-one normal ratio, with the ability to simulate extras if for some reason the simulation falls behind.

More importantly, you can change the expected simulation step temporal duration:

physicsSpace.TimeStepSettings.TimeStepDuration = timeStepDuration

where physicsSpace is the Bepu object, and timeStepDuration is set in the simulation engine initialization call.  So the client and server both pass in their expected update tempo, and the physics engine deals with it.

Velocity Mismatches

That fixed some of the differences I was seeing between the client and server, but there was still one bothersome one.

For small accelleration values (angular or linear) despite the fact that I had set the entity's AngularDamping and LinearDamping values to zero (this is a space simulation after all) the AngularMomentum and LinearMomentum values were still damping down to zero over a short time... but only if they were very small.

I was deeply confused and verified again and again that the damping was zero, and kept looking for where I had gone wrong.  This was throwing off the client and server sync, ans the client seemed to damp down quite a bit quicker (which seemed like a useful clue, as I knew it ran more, but shorter, simulation steps.  So it had to be some sort of per-step, rather than per-time-unit effect).

I finally found the answer. On the Bepu forums, someone poses basically the same question, and Norbo answers:
That's caused by the deactivation system. It will attempt to stabilize and disable very slow objects. You can prevent it from freezing entirely by setting the object's IsAlwaysActive property to true. However, stabilization will still be applied. You can disable stabilization separately by setting the Space.DeactivationManager.UseStabilization to false.
Stabilization is nice to have on in the general case, though, particularly if you have complicated interactions like large stacks or constraint systems.
You can also tune the Space.DeactivationManager.LowVelocityTimeMinimum and Space.DeactivationManager.VelocityLowerLimit. Stabilization only occurs under the velocity limit, and deactivation will not occur until an object is below the velocity limit for the time minimum.
By default the velocity lower limit is .026f.  Thus I added:

physicsSpace.DeactivationManager.VelocityLowerLimit = .001f;

Well, that solved a lot of problems.

Tuesday, April 30, 2013

Outlining Post Process

I've been working on the (temporary simplified) screen where you select a ship.  Currently when you click a ray is cast into the scene's physics space and the first entity hit is pulled back.  That's the one you clicked on, basically.

To visually implement this I had simply tinted the selected entity red when it was drawn (from the model rendering shader):

 if (isSelected)
  output.Color.r = output.Color.r * 2;

Clearly that was a bit... simplistic, though it was enough at the time and it worked.  But now I needed something a little better.

Sunday, April 28, 2013

Temporary 'Hangar' Screen

In working towards something vaguely playable, I've fleshed out the screen you get after logging in, the 'Hangar' screen.  Here you'll pick a ship type, then you'll be able to move on to actual gameplay.

When a client connects to the Hangar 'zone', the server gives it the entity list.  For now, there are three items (well, one is a group):  a destroyer, a corvette and a fighter squadron.  These are all synced from the server, so this list can easily change without any changes to the client.

Wednesday, April 24, 2013

Further Client Server Syncing

So last night I got basic synchronization between the client and server working.  Basically I had the server starting a zone, creating a single entity (a small spaceship) and forcing it to slowly rotate.



When the object was issued a command that updated it's attributes that data was then sent to any clients connected to the zone (GAMEOBJECT_UPDATE_MESSAGE).

Friday, March 29, 2013

Server Work

I haven't posted much in the last week or two.  I have been making progress, but largely I've been integrating the game client and simulation engine with the server system I'd written last year.  So, nothing glamorous, just a lot of 'oops!, I shouldn't have done it that way' sort of restructuring going on.

There are som interesting bits.  The simulation engine references XNA in order to use the various types (vectors, matrices, quaternions, etc,) as well as being able to load models.  Per triangle hit detection is one of the requirements, so I definitely have to have the model data and account for animation movement on the server.  So I figured I'd just reference and use XNA there, though definitely not actually running via the Game class of course.

I quickly realized that there was a serious problem.  Loading a model with XNA not only loads the data in the model file, it loads the textures and puts the model's vertices and indices in VertexBuffers and IndexBuffers as well.  Texture2Ds, VertexBuffers and IndexBuffers live on the video card.  There's definitely no guarantee that whatever machine the server is running on would have a DX9 video card; likely they'll be virtual anyway.  Plus it's just a waste.

Unfortunately there's no way to modify that loading behavior.  I considered looking up the format of the XNB files (the binary format XNA compiles resources to) and reading them directly, but then I realized that MonoGame does that already.  MonoGame is an open-source implementation of XNA.  It isn't entirely complete yet, so I can't use it on the front end, but for the server it should be entirely enough.

Even better, since it is open source, I was able to go into the ContentManager class and add some hacky code that allows to you instantiate a ContentManager and load a model without loading any shared resources (i.e. those that would reside on the video card).  Exactly what I needed!

There were some sticky problems with integrating this, however.  Since the SimulationEngine project was referenced from both the client and server, and both XNA and Monogame reside in the Microsoft.XNA.Framework namespace.... yeah, it really blew up at first.

Initially I wrote some interface code that did a bunch of casting and conversion between the two, but that was just ugly.  In the end I refactored the base SimulationEngine, making two additional projects, SimulationEngineClient and SimulationEngineServer.  Both these projects actually link to the files in SiimulationEngine, making them exact duplicates (though each overrides a few files).  Then SimulationEngineClient links to XNA, SimulationEngineServer links to Monogame.  Since they reside in the same namespace, nothing need change.  Boom, problem solved.

Anyway, each of these is inherited by RogueMoonSimulationEngineClient and RogueMoonSimulationEngineServer, which implement Rogue Moon game specific logic.

It is a bit twisty, but the code is pretty clean, and so far it hasn't presented too many problems, now that I have this all worked out.  It took me a while to get here, though!