Posts Tagged ‘unity’

Unity Game Project – some thoughts

July 17, 2016

A few months ago I revisited my Unity Game project, and re-examined the feasibility of having the ability for a dungeon master to modify a level in real time while players were running around.  The idea was for it to be quite minimal, in terms of the fact that there would be no combat mechanics, unnecessary animations, or fancy character progression / skill development / special moves etc.  Just a world in which people could wander around, with static NPCs / monsters and objects like houses and trees.

Denis Lapiner’s multiplatform level editor looked promising to me a while ago, so I looked into the mechanics of it at the aforesaid juncture.  The way it actually works, it turns out, is to create a terrain object, serialise it, then save it as a blob to local memory, which is then reloaded as a second scene.  Hence my immediate hopes of doing everything in one scene were readily dashed.

However I’ve thought a bit more about this problem more recently, and I have renewed hope that something interesting might still be possible.  I think, with some skill and cunning, it might be possible to modify the level editor scene so that two or three times a minute, a snapshot of the terrain is taken, and then the diff is applied to regenerate a preview scene – wherein also the players and everything else is pushed (as appropriate network objects) – also viewable by the dungeon master.  So, in essence, the DM would see two copies of the level (two subscreens on their screen) – one, being the level they are editing, and the second, being a non-interactive snapshot of the scene (an ‘autosaved’ version, if you will), where they can camera pan around, or even avatar into, but not interact with via the level editor.  The second screen would be updated several times a minute (or, if one had a truly powerful device – maybe not now, but at some point in the future – several times a second, so one could have a refresh framerate).  One could also imagine the DM being able to ‘minimise’ the editor portion so that they could focus on DM’ing in the ‘player’ or ‘viewer’ subscreen.

The viewer subscreen need not be totally toothless, however, as prefabs might be instantiationable within the level using the standard unity mechanics.

The players themselves would see a separate scene that just shows the current snapshot of the DM level, like the ‘viewer’ subscreen for the DM, but this would be their entire world.  They might also be able to instantiate prefabs as well, but they would not be able to sculpt or modify terrain like the DM.

In terms of the desired experience for a player, they should, one every 10 to 20 seconds or so, see the level shift around them to reflect the latest changes that the dungeon master has made.  Something that would need to be caught, however, would be the idea of where the ground is.  The player z coordinate, therefore, would need to be constantly remapped as relative to the difference in their height above the terrain at the (x, y) position they are located at.  Players would also need to be able to reposition their avatar via a third person perspective if they get stuck in a wall or an object that has suddenly appeared, too.

The interface that I plan to use to manage the networking will still be Photon Bolt, with Zeus as a server running somewhere on amazon ec2.

So that actually starts to seem like it would be vaguely doable.  And maybe, at some point in the future, with breakthroughs in personal computing, one might be able to ramp up the frame refresh rate, as well as maybe enable the experience for VR.  Possibly game engine improvements might also enable one to increase the scene refresh rate as well.

Advertisements

An open source in-game unity editor

November 15, 2014

I’ve been continuing to think about my aspirations for my Unity game, in particular, empowering players to build dungeons and function as a live ‘gamemaster’ / ‘dungeonmaster’, where rooms can be placed while players are in the game, and monsters / spawns can be dragged and dropped into the game. Also I’m keen to build an application / game where dungeon states can be saved or persisted. Regardless, as I mentioned back in this post, that seemed like an awful lot of work if I sought to build such from scratch, and on further reflection I have since come to the conclusion that it would be far handier to be able to adapt some resource that someone else had built to my purposes, or use some tool that another group had constructed in order to accomplish my objective (rather like I did with SmartFoxServer for enabling multiplayer in my game, with its quite user friendly API and accessible examples).

Hence I was quite excited today to discover that someone seems to have done just that, or at least built the germ of an idea that I and others can use. The project is OpenEd, and it claims to be essentially an open source in game Unity editor. Very cool! The github repository is here.

Certainly the task I have set for myself seems slightly less impossible now. I look forward to a time when I can dust off my old project and start trying to introduce this new functionality, hopefully around Christmas or the new year. I’ve already done a bit of work in simplifying the project structure; what I need to do now I think is to clean up the assemblies (there are about 4 or 5 weirdly named projects when looking at the scripts in MonoDevelop) / or build the scripting again from scratch, and also probably consider switching from MonoDevelop to Visual Studio, the flagship Microsoft IDE, which, in other good news, is now free for developers to use, and which has a Unity plugin for facilitation of Unity game development therein.

Experiences at the Unite Australia conference in Melbourne, 2014

November 8, 2014

Hi folks,

I thought I might write briefly about my experiences at the Unite Australia conference that was held recently at the Melbourne Convention and Exhibition Centre – right next door to the building known affectionately by locals as ‘Jeff’s shed’.

Broadly speaking my first impressions were rather wet. It had been pouring like crazy the night before, and there was an amazing thunderstorm. The trains also were running late. By the time I had made it to the convention centre, I felt mildly drenched, and doubly regretted my choice of formal attire when I noted that all the other folk there – mainly students and young rapscallions in the games industry – were dressed more casually.

It was a fine day. I think the event was sponsored by a few notable players, including the local branches of Intel and Microsoft. Swinburne also made an appearance – they had a booth set up. And there was some graphics card manufacturer as well.

Soon it was time to witness the keynote address, and it all looked quite interesting. Mainly the discussion revolved around the upcoming changes in Unity 5, and the big improvements from Unity 4, mainly due to the new and improved light maps and the way that sound was managed. There was a preview of the new unity user interface system, and it was mentioned how there were performance improvements with that over OnGUI for some reason. There were also a few hints as to the future, with a preview of an evolving prototype slated for the ‘5.x’ release cycle of the Unity engine – this was a feature called ‘Director’ (I think that was what it was referred to as) where one could essentially generate some form of workflow for a game, and things would appear in sequence via some form of state machine, demonstrated by a 2D runner with crates spawning, buildings moving in the background on loop, and various obstacles appearing in a pseudorandom fashion. Other than that, there were a few figures bandied around, such as that the Australia – New Zealand games industry actually does seem to generate a respectable chunk of GDP ($80MM I think), and roughly 70/80% of developers use Unity. And also references to the phenomenal growth of Unity itself over the ten years since its inception, and the responsibility that places on the key developers.

Following the keynote I attended a talk upstairs on UNet, the upcoming multiplayer functionality that I’m quite excited about. The fellow there provided a ‘hack-and-play’ demo where he demonstrated migration of a game written without multiplayer to a game with multiplayer. The philosophy was, that, contrary to the generally accepted wisdom in the games industry where ‘adding multiplayer ‘at the end’ of the release cycle means that you really are only about 50% done’, the new workflow for UNet using Unity really does allow relatively easy migration of a game from single to multi user usecases. However, I guess the questions that I had (that I probably should have asked then, but didn’t really think to at the time) were as to whether UNet allows for a centralised messaging server (like SmartFoxServer or many of the other offerings), or whether it was merely a peer-to-peer / failover type multiplayer shared game. Which is fine, but I like the idea of having a server, as it allows one to control other aspects of a game or application, such as data.

Next I attended a talk on best practices for Unity. This was quite useful to me, in many respects. Performance was a key area of focus, namely the warning to avoid using ‘find’ functions in the ‘update’ part of a unity application, as otherwise things can slow down quite a bit. In particular, calling expensive or clunky code for every mob on every frame can really cause performance issues. Another hint was making use of garbage collection oneself, dependent on whether one wanted to regularly do garbage collection or only rarely, depending on how the game flows.

Other aspects were kind of obvious but often not managed properly. For instance, having one folder for sprites, one folder for sounds, etc – ie a logical structure to the project. Also having logical naming conventions. I guess for me, this is something I still need to get right since my project is a bit of a mess with assets and namespaces not really aligned properly – particularly from multiple migrations from earlier versions of unity.

Finally another best practice was limiting scope in order to ship – in terms of the ‘triangle’ of project management – scope, resources and time. I guess in my case, it might be instructive to put aside my megaproject at some stage and focus on just shipping something, to gain an idea of what is involved.

After lunch, I attended a talk on ‘Unity for Architecture’ – a fork of the Unity game engine that is designed for architects and is a work in progress. It was a fairly impressive demo, wherein they demonstrated import of terrain map files to generate terrain – based on real geodata – and then imported a house from google sketchup next to the grand canyon. But the most impressive part of the demo was the ability to hold the camera / viewport still and iterate for a polished view / preview of a house / home. The resulting images were quite realistic and would definitely be brochure worthy. In fact, I was so impressed with this talk that I attended a follow up talk upstairs afterwards. One person asked whether one might be able to pre-render a path and then ‘fly-through’ a building with the photo-realistic images, and it seemed to me that that was quite an interesting question, although potentially extremely computationally expensive and maybe even impractical with even top-end modern machines.

The last talk I attended was one given by a graphic artist who was not a Unity employee, but still had some amazing experience, having worked on animated sequences for Saints Row 3, Civilisation 5, GTA LA Noire, and Darksiders 2. It was quite interesting to hear about the experiences that the fellow had had working on particular examples, and how he had managed his time and delivered to schedule. Also to hear how at one stage he had run a studio that built 2-D iOS games was fascinating. For me, it was a rare window into the industry.

All in all, I found it quite an interesting conference. Talks that I didn’t go to included one given by a Google engineer on ‘the new world of advertising / monetisation’, there was a talk on the new partnership between the windows store and unity, and there were talks on the new sound system, on the new user interface for unity, on xbox/ps4 game programming using Unity, a talk on the future of Unity, and a few other talks that all sounded fascinating. Unfortunately, I couldn’t go to them all.

I didn’t end up talking to many people in person, maybe a little silly considering that part of the allure of these events is ostensibly to have the chance to network with likeminded souls, but there is certainly always next year. Maybe next year I’ll remember to dress down a little, too.

Unity project – what to do next, part 1

August 31, 2014

A while ago, I had a bit of a think about what I should do next, subsequent to completion of my initial foray into using mysql and a smartfoxserver extension to handle persistence in a unity game world.  So in this post I will outline these ideas, however, this is not what I intend to focus on next in my project based on my current thinking.  That will instead be the focus of part 2.

Database considerations – inventory, equipment, etc.

Certainly it would be good to implement an inventory table in the database and an inventory manipulation interface in the game client.  Then, once this was done, I would like to create an “equipped” table, and allow a player to equip items, and for the state of what is equipped and what is not to persist.  Furthermore, I would like the appearance of various items to be displayed on the character, and for this to be transmitted to other players in the game via the smartfoxserver extension, so that the appearance of the player to themselves, and to others, was consistent with their current equipped / non equipped status.I think this would be a good next step to take this game project, albeit a rather conventional one.  Doubtless later on I will be able to do certain things that are a bit more surreal and slightly off the beaten track.

In terms of obtaining models, etc, to use as inventory, I learned from this video that there is a site, turbosquid, that specialises in 3D models, and many of the resources there are free.  So this is an additional resource of items in addition to the Unity asset store that I could use.

Character customisation / appearance of models

In terms of character customisation, there is already a certain amount of information and discussion on the web regarding how to modify the mesh of a character and swap in / out various items / armours etc, rather than clipping them all on the same model and merely hiding the ones not in use.  It is possible to do this, of course, but is not recommended – in an environment where one has say even a moderate amount of players running around, a game world will take a considerable performance hit.

In particular, there are these discussion threads, all on the Unity forum message boards:

In particular, the last thread points to an out of the box character customisation system for Unity, albeit for Unity Pro, which is by no means a cheap or ready to hand solution.  But nonetheless interesting that the solution exists – maybe in a year or two, Unity free might support something like this?

In terms of criticality of getting something like this working, though, although fascinating and definitely somewhere I’d like to get to eventually, this is not really what I’d like to target next.

Interface and gameplay

The third subfocus I had was to start working on the user interface, as well as gameplay, in particular:

  • health bars
  • skill bars / skill & spell books
  • equipment and character equipment slots
  • icons for skills and equipment, and empty character equipment slots
  • a skill system for skills, spells, etc
  • an action system for combat / player movement
  • better avatars / monsters
  • a minimap
  • gameplay
  • access to local events only on the client – though the server should keep track of all events (albeit, as representative data, of course)

For all of these, save the last two (the second last which is contingent on sensible synthesis of many of the rest), I identified assets on the Unity Asset store I could (and can) use / adapt to my purposes.  I’ve also found another site that sells quite interesting character and monster models (including a dragon!), which has also piqued my interest .  This will probably be a good next step.  Furthermore, I could in particular work to tie in of all these features to

  • a sensible database schema and messaging system, both in the local game client and on the server ( I already have solutions that exist for this and work quite well – C# messenger extended locally and smartfox for the client server messaging)
  • full multiplayer functionality

Abstract / surreal environments and game logic

The fourth idea that I thought would be interesting to focus on was incorporating a heavy surreal element into what I am trying to build.  This is something that I think is good to aim for in games, since it is in such that there is this tremendous opportunity to suspend the laws of reality and physics as we understand them, and flip them on their head.

Gameplay is also quite important, so I also had in mind looking into combat (magic & melee).

And then, consequent to this step, and prior to doing advanced project work on meshes / customisation of characters, I thought it would probably also be good to focus more on multiplayer functionality, eg, grouping, chat.  And maybe minigames, as well as some sort of quest system.  This is probably where I’d like to start diverging from the standard, and start exploring a somewhat more abstract and idiosyncratic game world and game logic – like Another World, or Abe’s Oddysee / Oddworld, or even, more prosaically, the Link games / Super Mario World universe.  Something a bit unusual.  I’d also like the gameplay to allow for a certain degree of freedom in terms of actions / animations, eg, dodge and roll, etc.

Artificial intelligence frameworks and embodiment

The final discarded item in the string of ideas I thought would be interesting to consider (and which I may eventually return to) is artificial intelligence.

In particular, I’d be very interested at some point starting to look into using OpenCog for embodiment of intelligent agents in a Unity game world, and somehow also incorporating that into the game.  This would be an extremely interesting thing to do – not least of which is that it seems that the community team behind that project seems to be starting to get some traction with their ideas.  Certainly at the very least I’m interested to see how things progress on that front over the next few years – as, if their current roadmap is even to be half believed, there could well be some fairly interesting behaviours one could instantiate in agents within a game world circa 2015+ or so, through use of the OpenCog framework.   Something that would be worth doing by someone on that project in particular might be to write tests; certainly, if I had unlimited amounts of time and energy I would do so myself, but I consider this extremely unlikely at the moment given my current priorities.

The future of Unity networking, and some investigations with Cocos2D

May 17, 2014

I’m very interested and slightly excited by the recent announcement on the Unity blog that there would be potential implementation of multiplayer capability into Unity.  In particular, this seems to me to be excellent news, for a few reasons:

  • although Photon and SmartFoxServer are under active development still, I suspect that the codebase of either hasn’t been significantly altered within the last ten years.  This leads to concerns about code rot (particularly with the ongoing / various updates) and also whether or not they are suited to modern game development.
  • the cost of licenses to use most of the multiplayer server technology (beyond the basic plan) in terms of CCU (concurrent users) for the most accessible and easiest to set up and run technologies out there.  SmartFoxServer in particular will hit your wallet hard if you want to move beyond the 20 CCU (unbranded) or 100 CCU (branded) free license.  To be more specific, were one to want to have a 500 user license on 5 servers, say, one would have to pay for 5 licenses, one for each server, which would set one back 750 british pounds per license.  Which is ok for established game studios, but perhaps not suitable for the indie developer, or hobbyist programmer / developer.  And these prices seem relatively standard across the industry, currently, for this sort of out of the box capability.  UNet has the potential to change all of that.
  • the people who are working with Unity to make this happen have previously worked on some of the most recent hugely successful game titles in the industry, such as World of Warcraft, Ultima Online and Lord of the Rings Online.

So I’m certainly quite looking forward to this development – in particular the potential for uncapping the user limit on my experiments, which seems like a relatively likely outcome.

One consequence of the announcement is that I will, at least for now, cease my initial investigations into uncapping the user count through looking into coupling Unity with Multiverse, a project that was originally a commercial undertaking instigated in 2004, but which is now owned by the Multiverse Foundation.

In other news, I did some investigation recently regarding Cocos2D, a game development engine for writing 2D games suited probably most for phone or tablet.  In particular I looked at Cocos2D-x, the port to C++ of the original Objective-C based engine, and Cocos2D-js, the wrapper of Cocos2D-x that allows one to write applications in javascript.  I found that this, or rather this, helped me immeasurably with getting things set up and configured.  Like Unity, it appears that Cocos2D supports deployment to many different environments – such as Android, iOS, Windows and OSX, or even to the browser.

Anyway, I haven’t forgotten my promise to complete my series on setting up MySQL-SmartFoxServer-Unity – to be more precise, how to use stored procedures in MySQL to support data persistence etc.  I’ll probably eventually write that post.  But currently, my main goal is to figure out how to deploy what I’ve done to Amazon-EC2 via RightScale.  That will most likely be the subject of my next journal entry.

MySQL, Unity, and SmartFoxServer – location persistence in the game world

January 24, 2014

(In this penultimate of a four part series of posts I will complete my sketch on how I built a working implementation of simple database persistence in a Unity MMO type game, leaving the final post for afterthoughts and other meanderings.)

Greetings,

In this post I continue from the previous two posts:

I will first describe my attempts to read a login location for a player from the database I am using, and then I will describe my attempts to write a new login location when the player exits the game / the smartfoxserver instance is terminated.

First of all, I found that I was able to modify the standard extension jar (not the login extension jar from Part Two) with the following scripts:

package com.spinningcat.mysql.access;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.List;
import java.util.ArrayList;

public class TransformMySQL {
private Connection connect = null;
private Statement statement = null;
private PreparedStatement preparedStatement = null;
private ResultSet resultSet = null;

public List<Float> getTransformFromDataBase(String username) throws Exception {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/rpg_mmo_smartfox?"
+ "user=root&password=");

// Statements allow to issue SQL queries to the database
statement = connect.createStatement();
// Result set get the result of the SQL query
resultSet = statement
.executeQuery("select x_position, y_position, z_position," +
"                x_rotation, y_rotation, z_rotation" +
" from rpg_mmo_smartfox.player where name ='" + username + "';");
resultSet.next();
String x_pos = resultSet.getString("x_position");
String y_pos = resultSet.getString("y_position");
String z_pos = resultSet.getString("z_position");
String x_rot = resultSet.getString("x_rotation");
String y_rot = resultSet.getString("y_rotation");
String z_rot = resultSet.getString("z_rotation");

float x_position = Float.parseFloat(x_pos);
float y_position = Float.parseFloat(y_pos);
float z_position = Float.parseFloat(z_pos);
float x_rotation = Float.parseFloat(x_rot);
float y_rotation = Float.parseFloat(y_rot);
float z_rotation = Float.parseFloat(z_rot);

List<Float> result = new ArrayList<Float>();

result.add(x_position);
result.add(y_position);
result.add(z_position);
result.add(x_rotation);
result.add(y_rotation);
result.add(z_rotation);

return result;

} catch (Exception e) {
throw e;
} finally {
close();
}

}
}

And, in the main class called on instantiation of the player in the game world:

package dk.spinningcat.fps.simulation;

import java.util.List;

import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.spinningcat.mysql.access.*;

// Player class representing an individual soldier in the world simulation
public class CombatPlayer {

public CombatPlayer(User sfsUser) {
this.sfsUser = sfsUser;

//used to determine where to spawn the player based on their location in the database
String username = sfsUser.getName();

//extracts the player position, based on their username, from the database
TransformMySQL mysql = new TransformMySQL();
List<Float> result = null;
try{ result = mysql.getTransformFromDataBase(username);}
catch (Exception e) { e.printStackTrace();}

//sets the value of combatplayer to the corresponding position rotation information from the
//database, so that the player is spawned at said position and rotation when instantiated
this.transform = new Transform(result.get(0), result.get(1), result.get(2),
result.get(3), result.get(4), result.get(5));

//this.transform = new Transform(850, 10, 1054, 0, 0, 0);
/*this.transform = Transform.randomRPG();*/
/*this.collider = new Collider(0, 1, 0, 0.5, 2);*/
}

}

Initially, I tested this general functionality by checking that I could access passwords in the database when I fed the program a username string “bob”.  Next I checked that I could access bob’s transform and rotation information.  Finally I made a minor tweak to the above script so that the program used as username the player’s username on login.

Ultimately, these actions were successful.  The end result of these efforts is documented in the following clip, where I demonstrate for two users, “bob” and “charlie”, both with password “alice”, that their spawn locations are dependent on their transform information in the database.

This leaves as a final step in this exercise to determine how to update information in the database on logout.  Consequently the game world should then experience true persistence of player location information.

I was not able to implement this on exiting play mode of the client application, since the username information was no longer accessible to the extension and therefore the correct row in the database could not be written to.  As a quick fix / kludge, however, I determined that writing to the database each frame would do the trick for the time being.  However this is ultimately unwieldy, particularly if there were, say, 100 players accessing the server concurrently – which is possible under the permissions of the free SmartFoxServer 2X license I am using.

Consequently ultimately I will need to do one of two things – either implement a quit button, or to modify the on player exit event, to write the transform of the player (stored as a temporary variable in the CombatPlayer class on the server) to the database – this will be in part 4 of this series.

In the mean time, though, you can see for yourself the successful implementation of my original goal for this mini series in the following video:

The code required to get this to work was, on the client side:

    /// <summary>
/// Send local transform to the server on logout
public void SendTransformDatabase(NetworkTransform ntransform) {
Room room = smartFox.LastJoinedRoom;
ISFSObject data = new SFSObject();
ntransform.ToSFSObject(data);
ExtensionRequest request = new ExtensionRequest("sendTransformDatabase", data, room, true); // True flag = UDP
smartFox.Send(request);
}

and on the server side:

public class RpgExtension extends SFSExtension {

@Override
public void init() {
// Subscribing the request handlers
addRequestHandler("sendTransformDatabase", SendTransformDatabaseHandler.class);

And the handler:

package dk.spinningcat.fps.handlers;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;

import dk.spinningcat.fps.simulation.Transform;
import dk.spinningcat.fps.simulation.World;
import dk.spinningcat.fps.utils.RoomHelper;
import dk.spinningcat.fps.utils.UserHelper;

import com.spinningcat.mysql.access.OnLogout;

import java.util.Date;
import java.util.List;

public class SendTransformDatabaseHandler extends BaseClientRequestHandler {

	@Override
	public void handleClientRequest(User u, ISFSObject data) {
		// The transform we received from player
		Transform receivedTransform = Transform.fromSFSObject(data);
		String username = u.getName();
		OnLogout onLogout = new OnLogout();
		try{ onLogout.updatePlayerPositionInDatabase(receivedTransform, username); }
		catch (Exception e) { System.out.println("Username and password combination incorrect.");
				//e.printStackTrace();
		}

	}

}

And the java mysql code:

package com.spinningcat.mysql.access;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;

import dk.spinningcat.fps.simulation.Transform;

public class OnLogout {

private Connection connect = null;
private Statement statement = null;
private PreparedStatement preparedStatement = null;
private ResultSet resultSet = null;

public void updatePlayerPositionInDatabase(Transform transform, String username) throws Exception {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/rpg_mmo_smartfox?"
+ "user=root&password=");

// Statements allow to issue SQL queries to the database
statement = connect.createStatement();

Double x_pos = Math.floor(transform.getX());
Double y_pos = Math.floor(transform.getY());
Double z_pos = Math.floor(transform.getZ());
//System.out.println(transform.getRotx() + "," + transform.getRoty() + "," + transform.getRotz());
Double x_rot = Math.floor(transform.getRotx());
Double y_rot = Math.floor(transform.getRoty());
Double z_rot = Math.floor(transform.getRotz());

// PreparedStatements can use variables and are more efficient
preparedStatement = connect
.prepareStatement("UPDATE rpg_mmo_smartfox.player SET x_position = ?," +
"y_position = ?, z_position = ?," +
"x_rotation = ?, y_rotation = ?, z_rotation = ?" +
"WHERE name = '" + username + "';");

preparedStatement.setDouble(1, x_pos);
preparedStatement.setDouble(2, y_pos + 0.5);
preparedStatement.setDouble(3, z_pos);
preparedStatement.setDouble(4, x_rot);
preparedStatement.setDouble(5, y_rot);
preparedStatement.setDouble(6, z_rot);
preparedStatement.executeUpdate();

} catch (Exception e) {
throw e;
} finally {
close();
}

}

// You need to close the resultSet
private void close() {
try {
if (resultSet != null) {
resultSet.close();
}

if (statement != null) {
statement.close();
}

if (connect != null) {
connect.close();
}
} catch (Exception e) {

}
}
}

Finally, some more code on the client side to instantiate the player rotation properly:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Spawns player and items objects, stores them in collections and provides access to them
public class PlayerManager : MonoBehaviour {

public GameObject playerPrefab;

private GameObject playerObj;

private static PlayerManager instance;
public static PlayerManager Instance {
get {
return instance;
}
}

public GameObject GetPlayerObject() {
return playerObj;
}

public void SpawnPlayer(NetworkTransform ntransform, string name, int score) {
//instantiate the player and move the camera
playerObj = GameObject.Instantiate(playerPrefab) as GameObject;

//adjust the camera to point in the right direction
Camera.main.transform.eulerAngles = ntransform.AngleRotation;

//edit the player position and euler angle coordinates
playerObj.transform.position = ntransform.Position;
playerObj.transform.eulerAngles = ntransform.AngleRotation;

playerObj.SendMessage("StartSendTransform");
}

There were another couple of client side fixes required.  One was to do with the third person controller not functioning correctly – essentially it did not register on spawn that the player was always falling slightly (I needed to delta the y coordinate that player position was stored / persisted at so at respawn the player would not fall through the world).  Anyway, this led to a puzzling difficulty in persisting euler angles of rotation for the player; finally, after debugging by force setting the height of the player to 400 on spawn, I figured out that it was something to do with the OnGrounded() function call in the third person controller.  Long story short, it was an easy one line code fix job, and it would serve no real educational purpose to provide the code itself.

Hence this concludes the bulk of this series of posts.  In the fourth and final post, I will perform some minor fixes.  One will be to delete the waypoints that the guard uses to patrol; for some reason these spheres are not disappearing in my mini multiplayer rpg, though they did disappear in my guards vs skeletons example!  So some investigation is required.

The second fix, mentioned already, will be to either implement a quit feature, or alter the OnUserGoneHandler to write the last known transform of the player to the database; the latter is simpler to implement and therefore is the preferred solution, if possible.    In particular, I will only be writing to the database once on exiting the game, rather than writing certain information to the database constantly – something which, I am sure, would put severe load on the database were there a large number of users accessing the server.  Furthermore, since, ultimately, I am potentially interested in running this server on a small cloud instance – whether that be Amazon EC2 or whatever else – it is unlikely that such is likely to have huge amounts of computational resources to spare.

Finally, I am interested in investigating stored procedures in MySQL, and calling these from the server when certain events occur.  Stored procedures offer various advantages, many of which are documented here.  The main ones of interest to me, however, are security and performance.  Security, since stored procedures allow one to more finely control who has access to do what in the database.  Performance, since a stored procedure lives in the database, and hundreds of lines of SQL code can be called by a short command of the form “Run [stored procedure name] with [specified variable values]”.

MySQL, Unity, and SmartFoxServer – implementing the functionality

January 9, 2014

(In this second of a four part series of posts I will aim to continue to develop my remarks on the foundations of simple database persistence in a Unity MMO type game.)

Hello again,

If one recalls where I left off last time, I had placed both client and server side code under subversion, and also created a simple database, with a single row of data.

The next step is to do something like what is mentioned in this forum post, which is targeted to SFS2X and MySQL specifically.  More broadly, the specifics of this post seem also like a good place to start trying to learn how to interact between the SFS2X extension jar and my MySQL database, or, also, perhaps, this post.

Subsequent to completion of this task, in terms of tidying up and improving upon my implementation, I think it might also be good practice to assign another user other than root to access to the database I created; in practice I’d probably not want to have the root user connecting all the time!

First, however, there is the matter of setting up elementary communication between an sfs extension, running on the server, and the client program written in unity.

In such vein, I followed the instructions in the tutorial by Lars Vogel (linked above), namely:

  • I created a new schema “feedback” in my default instance and a table within that schema, “comments” with the specified data structure
  • I copied the code in Lars’ tutorial to a new eclipse project
  • I downloaded the platform independent version of the connector-J driver from the mysql site, and linked it as an extension jar to the project
  • projectstructure
  • I then adapted the code but so that it would work with the location specific information in the table I created in Part I.
public void readDataBase() throws Exception {
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/rpg_mmo_smartfox?"
+ "user=root&password=");

// Statements allow to issue SQL queries to the database
statement = connect.createStatement();
// Result set get the result of the SQL query
resultSet = statement
.executeQuery("select * from rpg_mmo_smartfox.player");
writeResultSet(resultSet);

// PreparedStatements can use variables and are more efficient
preparedStatement = connect
.prepareStatement("UPDATE rpg_mmo_smartfox.player SET x_position = ?," +
"y_position = ?, z_position = ? WHERE idplayer=1;");
// "myuser, webpage, datum, summary, COMMENTS from FEEDBACK.COMMENTS");
// Parameters start with 1
//preparedStatement.setString(1, "0");
//preparedStatement.setString(2, "0");
//preparedStatement.setString(3, "0");
preparedStatement.setString(1, "850");
preparedStatement.setString(2, "10");
preparedStatement.setString(3, "1054");
preparedStatement.executeUpdate();

preparedStatement = connect
.prepareStatement("SELECT * from rpg_mmo_smartfox.player");
resultSet = preparedStatement.executeQuery();
writeResultSet(resultSet);

} catch (Exception e) {
throw e;
} finally {
close();
}

}

Everything worked perfectly well; I found that I was able to edit and update information in my database perfectly well from this script.

So, with that done, I saw the next step as to figure out how to get a username and password type communication happening between Unity, SmartFoxServer, and mysql.  There is a post here that I found useful in this regard.  Further information regarding programming client side is here (search for OnExtensionRequest); server side programming is covered here.

First of all, as I discovered, it is necessary to set the room in question on the server for SmartFoxServer to use a custom login – so that the extension handler is used rather than the system handler.

Consequently, there is a need to write a secondary extension jar for handling the custom login – on top of the existing extension jar for the game itself (there may well be a way of having both in one jar file, but this has stumped me for the time being).

To set things up, one needs to add an event listener in Init() for the server extension:

public class RpgLoginExtension extends SFSExtension {

@Override
public void init() {

// Subscribing the request handlers
addEventHandler(SFSEventType.USER_LOGIN, LoginHandler.class);
//might not be necessary but maybe necessary when deploy to server online and
//room does not already exist
//addEventHandler(SFSEventType.ROOM_ADDED, RoomAddHandler.class);

trace("RPG Login extension initialized");
}

}

Next, one needs to write a LoginHandler script.  Note: this discussion proved quite informative regarding security for a custom login.

package dk.spinningcat.rpg.login.handlers;

//import dk.spinningcat.fps.RpgExtension;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Statement;

import com.smartfoxserver.bitswarm.sessions.ISession;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.core.SFSEventParam;
import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.exceptions.SFSLoginException;
import com.smartfoxserver.v2.exceptions.SFSErrorData;
import com.smartfoxserver.v2.exceptions.SFSErrorCode;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

import java.util.Date;

public class LoginHandler extends BaseServerEventHandler {

public void handleServerEvent(ISFSEvent event) throws SFSException
{
String username = (String) event.getParameter(SFSEventParam.LOGIN_NAME);
String password = (String) event.getParameter(SFSEventParam.LOGIN_PASSWORD);

ISession session = (ISession)event.getParameter(SFSEventParam.SESSION);

//get crypted password from client login request
String cryptedPass = (String) event.getParameter(SFSEventParam.LOGIN_PASSWORD);

//get plain password from database
//String plainPass = SomeDBManager.getPlainPassword();
String plainPass = null;
try {
plainPass = getPasswordFromDataBase(username);
} catch (Exception e) {
e.printStackTrace();
}

trace("Plainpass is: " + plainPass);

//after compare them via api:
if(!getApi().checkSecurePassword(session, plainPass, cryptedPass))
{
//trace("passwords do not match");
SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
data.addParameter(username);
throw new SFSLoginException("Login failed for user: "  + username, data);
}
else
{
trace("passwords match! hooray!");
}

trace("username and password: " + username + "," + plainPass);
trace("Login successful, joining room!");
}

private Connection connect = null;
private Statement statement = null;
private PreparedStatement preparedStatement = null;
private ResultSet resultSet = null;

public String getPasswordFromDataBase(String username) throws Exception{
try {
// This will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// Setup the connection with the DB
connect = DriverManager
.getConnection("jdbc:mysql://localhost/rpg_mmo_smartfox?"
+ "user=root&password=");

// Statements allow to issue SQL queries to the database
statement = connect.createStatement();
// Result set get the result of the SQL query
resultSet = statement
.executeQuery("select password from rpg_mmo_smartfox.player where name = '" + username + "';");
resultSet.next();
String password = resultSet.getString("password");

return password;

} catch (Exception e) {
throw e;
} finally {
close();
}

}

// You need to close the resultSet
private void close() {
try {
if (resultSet != null) {
resultSet.close();
}

if (statement != null) {
statement.close();
}

if (connect != null) {
connect.close();
}
} catch (Exception e) {

}
}

}

Then, subsequent to compiling the jar (NB: it must have a name of the form [yourfavouriteprefix]Extension.jar) one needs to log in to the server (localhost:8080/admin, user/pass “sfsadmin”), then click on the modules, goto the zone configurator, and make sure that custom login is checked.  Consequent to this, select zone extensions, and select [yourfavouriteprefix] from the allowable extensions.  You will also need to select the main class of this extension (in the above example, RpgLoginExtension).  More on this process can be found here.

selectextension

(An alternative approach to all this might be to directly modify the smartfoxserver xml files, but I’m not sure where to copy files to update the version of the login extension jar that the server sees as the ‘current’ jar).

Also, one needs to copy the mysql connector j jar file to the library folder of the smartfoxserver application (since otherwise the server will not see it).  An alternative approach would be to add this jar to the classpath.

Also, too, every time one recompiles the jar file, it is essential to refresh its instantiation in the sfs administration panel as above.

But after these adventures, one should finally obtain something like the following (evidently with your own custom print statements):

smartfoxlogin

Consequent to this, it is a matter of simplicity to disallow login if the username, password combination provided does not match a user in the database.

This wraps up this post.  To summarise, I have learned how to communicate between Unity, a SmartFoxServer login extension, and a mysql database, in order to validate login information.  Hence the foundation is laid for further work, namely, persisting user location in the game world – as a first step in using databases.To possibly reiterate what I’ve mentioned before, naturally one could do many other things with the techniques I’ve started to cover in this post, and will continue to cover in the next – such as inventory, experience, talents, specialisations, reputation, equipped items, friend lists, etc.  Not to mention databases for monsters, storekeepers (limited amount of items in stock, with limited respawn rate, and things like auction houses, or simply shops that keep track of what players have placed on the listings or sold.

In the penultimate part of this series for this mini-project, I will break the task into two pieces.  The first will be, building on the above, to learn how to set the player’s default starting position to the (x,y,z) coordinates in the database that are assigned to the player’s name.

Secondly, it should then be reasonably straightforward to adapt the code to allow one to persist the player logout position (by writing to the database) and then use the final step of this part to read the player’s position on login.  In this part, I might also try and see if I can set up a different server-side user for the database other than root.

Experiments with WatiN

August 14, 2013

Hi folks,

So recently I decided that it’d be a good idea to get slightly up to speed with WatiN since I’ve gathered that it might come in handy to have an idea of a good automated testing framework, compatible with a decent development language, like C#.  It was certainly interesting learning how to use it.  After installing Visual Studio, I found this video, which seemed quite straightforward.  However I was stymied by my lack of resharper – a tool which costs about $200 for the latest version.  I decided to try the trial period for the tool, but then found out that I needed a license for Visual Studio (full release) as well, which would be at least another $800! So too much (even though resharper looks like a most excellent tool to have at one’s disposal, if say one was a hardcore .Net developer).

Luckily however I then found this video, and managed to run my first “Hello WatiN” script.  That was quite satisfying.

Naturally, of course, there are other testing frameworks out there, such as Selenium.  In particular, I installed the Selenium IDE for firefox 22 as a plugin, but didn’t really get around to playing with it before I became distracted by WatiN.  However WatiN seems more advantageous to a commercial organisation because it is inherently a plugin for Microsoft Visual Studio via the .Net framework, and the Microsoft .Net framework is built to run with the Microsoft office suite.  But being more or less still completely ignorant of Selenium (apart from the fact that scripts in Selenium can be recorded ? by actions in the browser ? and are recorded in a unique scripting language called “Selenese”) I will have to defer judgement until I have a better look at the tool.

In other news, I’ve started reading up on R.  A while back I downloaded R as well as R Studio, but for some time now they’ve been sitting on my machine, consuming space, waiting for me to eventually get around to learning how to use them.  So now I finally have, and am starting to get across such elementary ideas as vectors, booleans, dataframes, file i/o, and other basic commands in the kit.

My eventual goal is to become sufficiently competent with R that I can do linear regression, then implement additive/generalised linear models, and also be comfortable with various forms of hypothesis testing with the framework.  Ultimately I’d like to be at the frontline of work in computational statistics / data analysis / whatever the kids are calling it these days; but I anticipate this will likely take some time.

Simultaneously I’ve started to haunt kaggle.  My philosophy with kaggle is that it is a good way to cut my teeth on some elementary data problems, and build some legitimate skills (and maybe even some street cred in the process).   While on the site in particular I noticed a plug for a python package built by some Londoners called scikit-learn, so dutifully I’ve set up a virtual environment for it and have essentially playtested it to the point of completing my first “hello scikit-learn” script.  Apparently the strength of scikit-learn is that it is a great python library for machine learning – not sure how it compares to R though, particularly with R’s extraordinarily established community and extensive set of libraries.  But scikit-learn builds on numpy, scipy, and matplotlib.  And of course there are vast numbers of other python libraries.  So until I know more, or have had more time fooling around with the tools, I won’t know for sure if one toolset is definitely superior to the other – or whether they each have strengths in certain situations.

Finally, I thought I might share something really neat I learned of today (from the Unity blog).  Some of you have probably heard of the Oculus Rift – part of the renaissance in wearable computers / virtual / augmented reality that has been underway now for perhaps the past year or two, and largely facilitated by such enterprises as Kickstarter which itself was founded only in 2009.  There is a similar device too, called the Leap motion controller / detector.  Both are still largely alpha – Leap motion certainly is – however these developments, although groovy, are not the key development I wish to bring to the attention of this forum.

No, rather it is a recent development emerging from the labs of Columbia University, New York.  The meta is an augmented reality headset with a gesture driven interface, combining aspects of both the Leap and the Oculus.  They have some big names backing the project including Steve Mann, the father of wearable computing as chief scientist, and James Knight, head of performance capture on Avatar (the recent blockbuster movie with blue people).  So really, really interesting.  And the project is designed to work with Unity, too.

As for my Unity project, that is currently on the back-burner for the time being.  I’ve certainly not forgotten my aspirations to implement data persistence in the game world in question.  As for now, however, I have several other demands on my time and attention which I think I should give precedence to.

Unity, Git, and other meanderings

August 2, 2013

My Unity projects have been starting to become a bit large and in need of a good pruning / refactoring / reorganisation.  However, I am loath to do so with abandon, since I am afraid that I might break something irretrievably!  So, I’ve started to develop an interest in version control systems.  Indeed, with the release of Unity 4.2 I was interested in what could be done with the new version control system that is built to work well with it.

My initial best guess was that it would be Git – instead, it is a different animal, namely, Perforce.  Perforce, apparently, is supposed to be uniquely suited to dealing with teams working on very large (100s of MB, if not upwards of 1 or 2 GB) projects, offering the “best of Git” together with the “best of Subversion”.  Merging is apparently done on the server, rather than on individual machines (terminals?) of users – as opposed to Git, where the merges must be done locally.  Interestingly, it appears that it is possible to obtain fairly reasonably priced plans with the tech – in the cloud – for a reasonable amount of storage, too!

So I had a bit of a poke to see what the story was with implementing a setup of the thing.  Largely speaking, however, I found the profusion of products, terms, and other general goobledegook on the main perforce website a bit too confusing, and difficult to navigate to find, well, the main perforce VCS (maybe it is P4? not sure).   Indeed, even then, I’m still not convinced that it suits my purposes – since I am still working largely by myself with Unity, and therefore am just after a VCS where repositories can be locally managed.  This does not mean that using Perforce isn’t ultimately the best option for VCS with Unity – I’m sure that there may well be some logic to the whole thing – but I’m currently interested in a quick fix.

So, since I already understand Git – and have never version controlled a Unity project before, anyway – I decided to have a poke around the web for ways to get started directly using Git with Unity.  A post on the Unity forums led me to this series of posts, which is essentially more or less a comprehensive ‘how to’ of using these technologies together.

In other news, I’ve been starting to work on my first opensource collaboration.  This has been quite interesting.  I’ve been learning about Oauth for google and twitter, in terms of “logging in” to a service from a website.  Fascinating stuff!  Also some deep and interesting things about python, too.

While I was ferreting around on StackOverflow, moreover, and trying to understand the structure of the project in question, I came across another goldmine of useful information regarding things pythonic – a series of three posts written by a fairly knowledgeable chap.  They were:

There is also an extremely useful post / discussion about *args and **kwargs here.   The top two comments there clarified matters for me on these terms no end.

Regardless, I’m currently up to the stage with the project where I’ve managed to, sort of, get twitter authentication working.  The main roadblock I’m encountering now is a ‘pickle error’ (yes, another pythonesque thing I’ve never encountered before this point).  It turns out that in certain circumstances Python encodes objects (like functions or classes) as a bytestream (this is ‘pickling’), which is sent somewhere, and then decoded (this is called ‘unpickling’).  However certain things cannot be pickled.  For instance, if one function calls another function that is not instantiated within a base class object (as I have done), then that is a no-go.

So basically the plan to eliminate the pickle error is to consolidate a few functions, hopefully in a relatively sensible manner, into an authentication class.  That should be interesting.

Guards vs Skeletons

June 4, 2013

Hi folks,

So I’ve done a little more work on my project.  This time I’ve sandboxed the progress in a new scene, with a road and some buildings.  The main aspects of experimentation have been Unity 4.1’s new MecAnim animation system, patrol pathing, and basic AI for recognition, attack, retarget, knockout and respawn.

TL;DR – here is the video:

As you can see the combat behaviour is not totally optimised but the general idea is there.

In terms of working materials, I have used a couple of assets from the asset store (one purchased – the guard and associated mecanim animations, the other free – the skeleton model and animations), and also some AI scripts following a bread trail starting  here.  Working with the AI scripts was quite interesting.  Amongst the key learnings I gathered (or rather, the key bugs), I discovered that quite a few were simply due to the fact that I had transforms in the wrong location.  Making extensive use of Debug.Log statements to check that the flow of the script was working as I expected was very useful and helped guide me to avoid various pitfalls.  I also found that simply defining obvious booleans (eg, Engaging, Attacking, Friendly) was helpful for debugging.

Basically what I wanted to implement was the following – a situation where there are three types of creature: players, guards, and mobs (enemies).  Enemies view players and guards as viable targets, players and guards view enemies as viable targets.  If there are none of the other present, guards (or monsters) will path on a preset sequence of waypoints.  If a hostile rel them passes into their line of sight (I found that checking for ray collision was largely empty unless I raised the ray emanating from the creature a nominal height; this was due to the nature of capsule colliders I am using for creatures), or is sufficiently close (their “noise” > given threshold value) then they move to engage that target.

Once they are adjacent to the target they move to attack it (I found that I needed to reset the transform periodically for creatures when they were attacking, otherwise it bugged out, ie they did not stay fixed in place.  Even when I did this I became confused since it was still bugging out, but then I realised I need to fix the rotation as well.  So prior to attack I calculated the initial position and rotation information and then fed these as temp vars into the attack function).  If the target moves out of range they follow and re-engage.  If the target is reduced to < 0 hp it is destroyed; the associated spawn point for that target is then empty.  The spawn point then detects this and a cooldown timer is initiated.  Once this cooldown timer reaches 0 a new creature is popped at the spawn point and starts to patrol, etc.  As part of the spawn process the list of targets for the creature which struck the knockout blow is refreshed, and a new goal (hostile creature) assigned if there are any in range.  It then proceeds to attack the new hostile creature.

I decided that skeletons should have 50hp and guards 100hp.  They both do a similar amount of damage.  In the video you can see the cycle of destroy-respawn-destroy-respawn, an unending tide of guards and skeletons leaping to rejoin the fray to replace their fallen comrades.

One more thing is worth mentioning.  I also kept track of variables to make sure that the animation playing is appropriate – this is the MecAnim part of the picture.  So the guards and skeletons have state machines for their animations, as well as for their AI behaviour.

————————————-

I am reasonably satisfied with the outcome, but I know that in theory the implementation could be a lot cleaner.  My code is not totally unreadable but still is, for some scripts, way too long and should be written in a more sensible, concise format.  I’m also certain that in a few places I’ve written out the same functionality more than once; a bit more focus on reusability certainly would not go amiss.  And also redundancy – I’m fairly certain that the code is not as tight as it probably should be, in fact, I know that it isn’t.  This applies more generally to the project at large.  There are many places in my work where I’ve coded the same functionality for different things in different contexts.  Or even functions that have not been used.

So a little work needs to be done at some point on said matters.

In particular, todos that spring foremost to mind with this particular line of work (many of which, such as style, readability, best practice etc. I likely will not implement since this is primarily a “finding my coding feet” ongoing exercise):

  • make it clearer if a creature is in combat (ie, none of this running around in circles spontaneously business) – it could be that artifacts such as running around in circles occur because noise isn’t refreshed immediately for the goal creature when the original target is destroyed.  This could be fairly easily redressed.  Or maybe I might like to simply have a fixed (small) radius wherein if the goal is within that circle the creature automatically moves to attack (this is currently not the case, but it should be, and that is what noise/”sound” detection (generalisation of said idea) was supposed to do)
  • possibly aim to fix creatures in place during combat – try to make things more static
  • morale stat for creatures – chance to run away if allies nearby down / no support (possibly hard) or hp low; then move randomly away from attacker, or seek “wall” tagged object to attempt to throw off attacker?
  • knockout animation & possible option (if player dealt k.o.) for ability to loot the creature; then despawn timer prior to respawn
  • refactor the code to make some of the classes less lengthy and so that they have a more logical structure
  • subclass creature.cs (my main AI script) as part of a SFS_creature.cs script so that it interacts well with smartfoxserver
  • NPC_targeting.cs (my main AI targeting / listing script) – make this dependent more on “Broadcast messages”, possibly local messages.  There is a messaging system I am currently using for health bars – this however is more general and can be extended.  If the world becomes quite large and hence contains 100s of monsters, guards, players etc I do not want every single monster / guard / player to have a list of length 400 encoding and tracking the position of everything else in the world – that would be untenable.  But that is precisely how the program works currently.  Evidently this will have to be fixed, so that only enemies / guards in noise / detection / aggro radius are detected.  Or “targeting radius” which is larger than aggro radius.
  • Incorporate the idea of “threat” levels depending on which creature is damaging which – ie first calculated purely as a function of total damage dealt, then maybe factoring in threat generation abilities (eg taunt – sets to top threat) or threat reduction abilities (feint), and threat reset effects (moving beyond targeting radius – as per point above).  Evidently want the creature with highest threat to be the creature targeted.

The next part of the project will focus on hooking up a mysql database with the smartfoxserver software I am using as described here.  Basically I’d like to aim at storing 8 fields: username, password, spawn location (x,y,z) and last seen location (x,y,z).  Essentially I would like last location to be updated every time the player logs out, and then persisted in the database, so that when they log back in (if it is not a first time logon), they appear at that location.

If it is a first time logon they appear at the default spawn location, and last location is null until populated.

The architecture of the goal application will essentially be

client unity application <-> server SFS2X application <-> mysql database

with <-> denoting two way communication, the client application written in C#, the server application written in Java, as is currently the case; the new component will be the database.  Naturally a database can consist of more than one table, and more than 8 fields.  In a full blown, sophisticated application, there is no reason that all data about the players should be able to be stored in an appropriate database schema.  So certainly there is considerable room for extending this aspect of my learning, once I’ve managed to get this proof-of-principle up and running.

Consequent to this I might look at readapting this patrol example for SFS2X-deployed unity games, or something completely different.