Thursday, November 15, 2012

Managing Game Objects with Unity

Dear Unity Developers,

I have more than 1000 views on my blog now! Thank you everyone. 

I've come across improper use Unity's GameObject.Find() so many times that I wanted to share the best ways to deal with this. Unity has ways to avoid this completely thus increasing performance in your code. I started typing this guide for my project teams, and I just thought it would be helpful for everyone to read. It uses code snippets from two projects.

Please, if you don't have time to read it now, do read it and make sure to fully understand it. E-mail any questions!! We're all studying game development, and I'm just trying to help. Also, I think that soon I'll be moving this blog over to my own personal site in order to offer code highlighting.

First, I'll show an example of a standard problem that I encounter in the file
//EnemyManagerClient.cs
public GameObject[] enemies = new GameObject[2];
void Update()
{
     Vector3 temp = GameObject.Find("Panda P1").transform.position 
              - enemies[0].transform.position;
}
You'll notice in this line that enemies[0] does not have to be "found" by Update(). This mean the object doesn't have to be found each time this statement is executed.

Every time your code exceutes GameObject.Find(), Unity has to look through all of your object. You should really store the reference to that object, and then your game object will act as a pointer. The least you could do is code it like this. Start is run one time before your first call to update,

public GameObject[] enemies = new GameObject[2];
private GameObject panda1;

void Start()
{
   panda1 = GameObject.Find("Panda P1")
}

void Update()
{
     Vector3 temp = panda1.transform.position 
            - enemies[0].transform.position;
}
That's way better!! You can also set game objects object in 3 additional ways.


1. Store the reference with the Unity Inspector. This works for objects in the hierarchy that want to reference a prefab or hierarchy object. It is the most effective way.

(extra caution, A script that is attached to a prefab will not be able to store a reference to an object in the hierarchy: use method 2 or 3)

Here's how. Add the line "public GameObject" panda1 to the top of the code. Compile. Look at the object that has the EnemyManagerClient component on it in the hierarchy (using Unity's Inspector). It now has a blank spot to which you can drag the object from the hierarchy. Doing so will give the component a permanent reference to the game object. Save the scene. Now, you never have to run find in the code. This is what was done with enemies[0]. You could drag the Panda 1 game object into enemies[1].

2. To maintain OOP, you need a way to refer to class scripts that are stored on other game objects as components.

//here is the wrong way to access variables in your script
void SendPacket()
{
     float xVelClient1 = 
            client1.GetComponent().velocity.x;
}

//Fritzie has already stored a reference to this 
//ProfMoveScript in this file. At the top we've added:
private ProfMoveScript profScript1;
void Start()
{
     //...
     profScript1 = client1.GetComponent();
}
This reference to client1 (Panda P1) was set by the same method as in example 1. (dragging and dropping in the unity editor )

3. Use this method if an object will be created dynamically and then referenced in an update or function. Prefab components can only store refs to things on the prefab. Attempts to get a component from a null object will throw a null reference exception.

This is a modified version of a way that I get a Networked animation script from a dynamically created player object in Club Consortya. This is similar to how we will want to get the references to the enemies in Panda so that we can then call their functions and edit their healths.

//There is a player script that has to be initialized 
//once the user is created
private bool initalized = false;
private GameObject user;

//Declare your script object
NetworkedAnimation networkedAnimation;

void Update ()
{
    if(!initialized)
    {
         Initialize();
    }
    else
    {
        networkedAnimation.Sync();
    }
}

void Initialize()
{
    //First you have to store a ref to the user
    if(user == null)
    {
      user = GameObject.FindGameObjectWithTag("Player");
    }

    //Only if you have the user can you get a component from it
    //otherwise, you will get a null reference exception    
    else if(user != null && networkedAnimation == null)
    {
        networkedAnimation = user.GetComponent("   NetworkedAnimation") 
              as NetworkedAnimation;
    }
    //Now see if it's all good to go, and then you won't have to 
    //run the initialize code in update anymore
    else if(user != null && networkedAnimation != null)
    {
        initialized = true;   
    }
}
And that does it. You can use this method to really make your code look beautiful. Next post will be about using a singleton reference. Let me know what you want to hear about in the comments below.

Saturday, September 29, 2012

Using the Buddy List with Unity and Smart Fox

Read my official documentation and download the source at http://docs2x.smartfoxserver.com/ExamplesUnity/buddy-messenger

Dear Reader

Thank you for following my blog. This might be my last entry until I begin a new project. I have been working on the contents of this for a while. Previously, the only example that Unity had for Buddy Messenger used Flash. I've coordinated with Smart Fox to make one for Unity, and they have added it to their Unity examples. Although, it's been a lot of work, and I've been really busy lately. I made notes here as I worked on the example, so if you want to know how or why I made certain decisions, you can peruse this listing and the links below.

Stream of consciousness notes:

I've been working to make my layout match that of the flash example. There are quite a few things to worry about with the buddy list. One thing I didn't realize is that anytime you change a buddy variable, you have to send the request to smart fox. Another thing is that you don't change the variable in the buddy manager, you are only supposed to access that variable. The online state as a buddy is different from your online state as a user. There is a list of reserved variables that you can use to edit state, nickname, and online status. It's quite a unique set up that they have in Smart Fox Server's buddy list. I got pretty annoyed with it, but I think that in the long run this is the most efficient way to maintain the buddy lists of all the users in your zone. I'm assuming that these buddy variables persist throughout each room in the zone, but they don't leave the zone. So, you'll want to have all the rooms that these people will want their same buddy lists to be in the same zone. If you have a bunch of online card games, then you'll want each of these to be in the same zone, that way users can invite their friends to all of the games.

My combo box is pretty unique. I know that with a more elaborate GUI system you could probably avoid the complex way that I'm using to draw it in the correct location, but I wanted to stick with the original Unity GUI so as to not have to distribute a custom GUI when I try to submit this to Smart Fox as a Unity example. For the add, remove, and block buttons, I will make it so they work only when the user in that text field is a user in smart fox's user list. Otherwise, it would generate an error.

I've split the code into three different functions which are called from OnGUI. I'd say that the majority of my time with this project was actually making the GUI look good. The actual use of Smart Fox was mainly a hindrance in desiging the project because I wasn't absolutely sure what kind of things were necessary for the application to work. I'd suggest logging in as two different user names and adding the other user to your buddy list. That is what enabled me to test the functionality that I'd created. You can create your own personal variables for buddies, so that makes it a pretty unique system. The example on sfs is to see what song your friend is listening to. You can also set your mood. I've done quite a bit of refactoring, and I have more to do tomorrow before I consider the project good enough.

I'll do a combo box for the user list and disable the switch between users and buddies. That way the project will more closely resemble the outline that I'm working from.

You can check it out at Smart Fox Server soon because they will be using my project as an official Untiy example.


//Invitation
http://docs2x.smartfoxserver.com/AdvancedTopics/game-api#invApi
//Make sure you've read the official sfs documenation
http://docs2x.smartfoxserver.com/AdvancedTopics/buddy-list-api
//They have a buddy list example in the old documentation
http://smartfoxserver.com/docs/1x/index.htm?http://smartfoxserver.com/docs/1x/docPages/sfsPro/buddyList2.htm
//I want to talk about error messages
http://docs2x.smartfoxserver.com/AdvancedTopics/client-error-messages
//This dude helped
http://smartfoxserver.com/forums/viewtopic.php?f=20&t=11962&p=49005&hilit=buddy+list#p49005

//Flash tutorials for buddy manager
http://www.actionscripterrors.com/?p=1454
http://www.adobe.com/devnet/flex/articles/fcf_mxml_actionscript.html

//Budy List Events
http://docs2x.smartfoxserver.com/api-docs/javadoc/server/
http://docs2x.smartfoxserver.com/api-docs/asdoc/com/smartfoxserver/v2/core/SFSBuddyEvent.html

//Nice dropdown menu script wiki
http://www.unifycommunity.com/wiki/index.php?title=PopupList

//GUI Selection Grid
http://forum.unity3d.com/threads/117150-Gui-Selection-Grid

//Reposition the box
http://answers.unity3d.com/questions/127219/know-guilayout-current-screen-position.html

Tuesday, July 17, 2012

Unity Scripts & Network Management

Hi. Today I'm going more in depth with Unity development by adding some important information for managing you network and players. SmartFox connections can be very delicate, and a program that closes without properly disconnecting from SmartFox will crash Unity nearly every time.

First, here a few simple tips for designing the script that connects you to SmartFox. This pertains to people who debug on a localhost and also on a remote connection. Save your remote connection and 127.0.0.1 in strings and then add a public bool variable so that your program will switch between Local and Remote Connection in Start. Then you can tick the checkmark in Unity's inspector whenever you want to switch between your different SmartFoxServer instances. You can do something similar with a guest boolto change the user name to guest if you have allowed a guest to log into your server. Lastly, be sure that debugging information is always sent on bad connections. In my connector, I have a status message that is updated based upon how things are going with the three phases: Connection, Login, and Joining the Room. After logging in, I show the client a list of each of the rooms in the zone, so that they can choose which one they want to join. A client should be alerted of the status of all these things as they go along.

Make sure your database is configured the way you want it and that your zone and room connection scripts should be connecting to it as you intend. You can sett a zone variable using the SmartFoxServer admin tool to allow guests to log in. Their name will  always start with Guest. You could keep this disabled and manually assign a name, but I find this automatic way to be much simpler. In your Unity Script that connects to the server, you need to send a keyword in your login request.  I'd suggest setting the user name to "Guest" or "" (null), and then in your zone extension->OnLoginHandler add in the code below to avoid triggering an error message for a login request that intentionally will not be in the database.

if(clientName.compareToIgnoreCase("Guest")==0 
    || clientName.compareTo("")==0)
{
    //Guest login code
} 
else try 
{
    //Your Normal Login Code;
}

In my game before each user is sent the reply for the "spawn me" request, my room extension retrieves a specific model name which is stored in the database. You'll have to ensure that a default model name is returned for guests. In your room's "Spawn Me Handler",  I'd suggest doing this without querying the database so that your team can typically run the game without having to start WAMP or have the database locally installed.

if(user.getName().startsWith("Guest"))
{
    model="Guest"
} 
else try 
{
    //db query...
}

In your Unity Player Manager, check for this and load a generic prefab, or you could even generate a random model if you are up to the challenge.

There are a lot more things you should do to your Unity code. Now that we have discussed adding a player, let's make sure that your game knows how to remove one. Make sure that your users have a way that they can request to log out of the zone and disconnect from the server. The room extension that you built should have this:
addEventHandler(SFSEventType.USER_LEAVE_ROOM, OnUserGoneHandler.class);

However, it's come to my attention that the USER_LEAVE_ROOM event is not called when you send a logout request to the server. A logout only occurs in the zone, so your room will not be notified. This will cause a lot of problems because you have to access your world class and remove the leaving player so that their model is removed from the list of players and from each client's instantiated guests. Do this when a user activates logout. I'd also suggest placing this inside of OnApplicationQuit in SmartFoxConnection before the smartFox.disconnect. That way the users will be gracefully removed even if they don't log out. There is a lot of messaging among users, so make sure to broadcast a leaving message.
smartFox.Send (new PublicMessageRequest(userName + " left"));
smartFox.Send (new LeaveRoomRequest());
smartFox.Send (new LogoutRequest());

Look here for more information on leaving the room. http://www.smartfoxserver.com/forums/viewtopic.php?t=12524

I find it necessary to store my id within network manager so that if it happens to be me that is logging out, I don't erroneously try to remove my id from the guests dictionary.
// When a user leaves room destroy his object
private void OnUserLeaveRoom(BaseEvent evt)
{
 User user = (User)evt.Params["user"];
 if(user.Id != smartFox.myself.Id)
 {
      PlayerManager.Instance.RemoveGuest(user.Id);
 }
 Debug.Log("User "+ user.Name+ " left");
}

Then place this in your Player Manager.
public void removeGuest(int id)
{ 
    receivers.Remove(id);
    Destroy(guests[id]);
    guests.Remove(id); 
}

Saturday, July 7, 2012

Link SFS to a MySQL database using JDBC

Most admins in the SmartFox forums seem to think that connecting to a database is not that complicated, but I came across several hours worth of problems while trying to make it work. Most of these are from coding subtleties that only a person truly versed in JDBC knows. It's my goal here to help you connect to your database with ease. I know that everyone has their own formula for database management (usually the first thing you learn is what you want to use), and it shouldn't be too difficult to follow my example in mind of exchangeable parts. Here is a quick bio of why I'm using JDBC (skip to next paragraph if you don't care). I used it once in my graduate Database Management class at USC. In that class, my teacher taught us the theory, but we had to learn all of the implementation on our own to finish his rigorous assignments. I developed a formula to test all of the MySQL, PHP, HTML, XML Schema, CSS etc! No joke, I had to pull an all nighter every time one of our a coding assignment was due. So, I became extremely good friends with the amazing w3 school tutorials, occasionally reading an entire web language tutorial multiple times. http://www.w3schools.com/ should be your first reference for any web development tutorials. Even with my prior exposure to database management (I'm in no way a guru), I still had trouble making things work with SmartFoxServer.

I am currently managing the server on my own computer using WAMP. I believe Mac users can use MAMP.  This program allows you to manage a local database on your computer and even expose it to the outside world if you so desire. It comes built in with MySQL which is the component that you need for this tutorial. Instead of using PHP or ASP like you would do when developing a web site, we're going to connect to the database with JDBC: get the connector at http://www.mysql.com/products/connector/ and place the .jar in your {SFS2X directory}/Extension/__lib__.  I have created a MySQL database on my local computer using the phpMyAdmin tool and Oracle's MySQL Workbench. You can create a .sql file pretty easily with the Workbench. Design your database visually and use the forward engineer function to make a .sql creation script. Then, create that database on your WAMP server by typing localhost in your browser and clicking phpMyAdmin. You might need to edit your hosts file so that localhost will redirect to 127.0.0.1, and if you already have other programs in control of host, try associating it with a name like localhostwamp. This will show you all the databases you have on your server. Create a new database with the file that you built with the workbench.

Ok, so now you have installed a server that is running MySQL, and you have created a database that at least holds one user entry with a user name and password. You'll want to combine the official instructions http://docs2x.smartfoxserver.com/GettingStarted/howtos#item2
with this tutorial from the forums http://www.smartfoxserver.com/forums/viewtopic.php?f=4&t=11793&p=48400&hilit=jdbc+databasemanager#p48400  Well there are a couple of things that they don't explain. Firstly, the Database driver class doesn't refer to the name of the .jar connector, it refers to the name of the class located inside of the file. So for JDBC it's com.mysql.jdbc.Driver  If you're using WAMP then your MySql server should be running on port 3306. You can check this by clicking WAMP -> MySQL -> my.ini which will show you your password and port. The default user name is root. So for connection string it is jdbc:mysql://127.0.0.1:3306/yourDbName
Change the TestSQL value to "select count(*) from yourUserTable". When you boot up your server, I suggest doing it manually by clicking the SFS2X.bat file in your SFS2X directory.  This will show you a cmd window and alert you of any problems it is having connecting to the database. If it doesn't show any errors, then that means that your TestSQL script worked! Be happy! If not, then perhaps your sql statement isn't following standard syntax or has a typing error. Try getting some help from the post in the forums.

Now that your server is configured to connect with the database, you can start coding your server side extension. Previously, I've showed you how to create a room extension, but only a zone extension can be used to register login events. You'll need to open Net Beans and create a new project. Refer to my other posts about how to create an extension. In the main class of this extension,  you'll want to add this line of code addEventHandler(SFSEventType.USER_LOGIN, LoginEventHandler.class); 
inside of your init function. Make sure to create a Login Event Handler class for that function to call. There is a great snippet of code where someone has made a handler that checks the user name and password against the values in the database. http://www.smartfoxserver.com/forums/viewtopic.php?t=13292 Go with the second portion of code that says
by Zageron» 30 Jan 2012, 16:40  You can reference most of the functions in this documentation by SmartFoxServer and searching for the IDBManager http://docs2x.smartfoxserver.com/api-docs/javadoc/server/

It is a pretty complex thing, but this will work really well and follows pretty good Java coding practices. There are a couple things that might seem strange. One is that he calls the password a hash. This is true. SmartFoxServer will always send a password from the client as a hash. So that is why you have to use the API function to check the password from the database against the one the client sent. The other has to to do with stored procedures. You can't just grab a value from result. You must specify Result.first() or Result.next() to get increment the result iterator for the user's table entry for which you were looking. Prepared statements are good because you can iterate through several rows that are returned each time with Result.next(). Still having problems? Check this article on prepared statements to see why he is including a ? in the code. http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/PreparedStatement.html  
 and then look here http://stackoverflow.com/questions/2120255/java-resultset-exception-before-start-of-result-set

*make sure to enable use custom login for the zone

Here is a little update so that you will know how to proceed when you want to connect to the database from the Room instead of the Zone extension. I do this to load a specific character according to what my user has stored in the database. Since you're following the example of the first person shooter, you should have a world class and a spawn me handler. This is quite a nice gift, so enjoy and make your program connect to your database like a champion!

//This is in your SpawnMeHandler.java class
public void handleClientRequest(User user, ISFSObject data)
{
 World world = RoomHelper.getWorld(this);
 String modelName = null;
 String request = "SELECT * FROM users WHERE username = ?";
 try
 {
  modelName = venue.sqlRequest(request, "characterModel", user.getName());
 }
 catch(Exception ex){}
 
 boolean newPlayer = venue.addPlayer(user, modelName);
 if(newPlayer)
 {
  sendOtherPlayersInfo(user);
 }
}

//Connect to a database in your Room Extension
public String sqlRequest(String sqlRequest, String field, String userName) throws SFSException
{
 IDBManager dbManager = extension.getDbManager();
 try
 {
  Connection connection = dbManager.getConnection();
  PreparedStatement stmt = connection.prepareStatement(sqlRequest);
  stmt.setString(1, userName);
  ResultSet result = stmt.executeQuery();
  if(result.first())
  {
   sqlRequest = result.getString(field);
  }
  
  stmt.close();
  connection.close();
 }
 catch(Exception ex)
 {
  SFSErrorData errData = new SFSErrorData(SFSErrorCode.GENERIC_ERROR);
  errData.addParameter("SQL Error: " + ex.getMessage());
  throw new SFSLoginException("A SQL Error occurred: " + ex.getMessage(), errData);
 }
 
 return sqlRequest;
}

Thank you for reading, and feel free to comment below.

Sunday, July 1, 2012

Unity Scripts & Game Objects

Unity is a powerful game engine that caters to the needs of programmers of any skill level. Its ability to create object prefabs and graphically place them using the Unity Editor is arguably the most used feature. There is another way, however, to place objects in a scene: via a script. In this post I'll discuss how to use Smart Fox Server and Unity to create a player object and update there locations.

If you've been reading this blog from the first post, then you already have a basic understanding of how to develop an infrastructure for your multiplayer game. You've looked closely at the First Person Shooter example for Unity available here http://docs2x.smartfoxserver.com/ExamplesUnity/fps and you understand that by creating a custom extension you can allow the server to correspond with your game.

To get things running, attach Network Manager and Player Manager as components of the main camera in your game scene. You should have a login scene that that connects the user to the zone and room, and that scene will then save the connection into the static class SmartFoxConnection and load your game scene.

Most games that you have developed probably have the player already added into the scene. The challenge of creating a networked, multiplayer game is that no character should already be in the scene. Rather, when the Unity client starts the game scene, it sends a request to the server extension to create that player on their client and every other client connected to the same room.

In my previous post I discussed the different classes that you will need to develop in Unity. Another important aspect is to create player prefab objects. For the most basic implementation, you'll want two kinds of objects in Player Manager. Create two prefabs: myPlayer and otherPlayer. Add the character controllers and animations as you normally would to a character. On the otherPlayer prefab, make sure to remove any code that would respond to input from the user's keyboard. Instead, you want to add a Network Transform Receiver script onto that prefab.  Then, add NetworkTransformSender.cs to the otherPlayer prefab. You'll need to have this code in your Player Manager and save.
public GameObject playerPrefab;
public GameObject guestPrefab;
Then, look at your main camera in the Unity property inspector. You'll see these two objects by the Player Manager script that you added to the camera. Click the small circle to the right of playerPrefab and select your myPlayer prefab. Then, do the same for guestPrefab except select the otherPlayer prefab. Use any naming convention you like, just make sure it's obvious which is which.

Make sure you've followed the guidlines of the FPS demo and enabled UDP. The game sends user transforms with UDP because it is much faster and, though less reliable than TCP, UDP will function well enough for sending transforms.

//SendTransform is a function in NetworkManager.cs
public void SendTransform(NetworkTransform nTransform)
{
 Room room = smartFox.LastJoinedRoom;
 ISFSObject data = new SFSObject();
 nTransform.ToSFSObject(data);
 // True flag = UDP
 ExtensionRequest request = 
  new ExtensionRequest("sendTransform", data, room, true);
 smartFox.Send(request);
}

Let's explore the code in the picture above. Send Transform is called in the SendTransformHandler after each period of time as set by the sendingPeriod variable. When called, it determines the client's current room and serializes the transform in an ISFSObject (used to efficiently transmit data across the network). Then it creates a new Extension Request which it labels "sendTransform". You might recall the init function in your extension.java file has the line addRequestHandler("sendTransform", SendTransformHandler.class) So, when this request reaches the server the SendTransformHandler.class is called and will in turn send a request back to all the other clients.

Adding the data variable to request is self-explanatory. The room specifies the exact room to target, however, it also limits your extension to only function as a room extension and NOT as a zone extension (otherwise to transmit to the zone, replace room with false). Last but not least is the value true. This means that this request will be transmitted using UDP.  So make sure that somwhere in the login script that connects to your server you have called this function:  smartFox.InitUDP(serverName, serverPort) or the UDP request will not transfer.

Finally, in Player Manager you will need to maintain a dictionary of all the otherPlayer Game Objects and Network Transform Receivers in order to manage each of their locations.Once you've created them, you'll want functions like these in your Player Manager class. Creating your SpawnPlayer class does not require a dictionary, and I will leave creating it as an exercise for you to figure out on your own. One thing I haven't figured out yet is how to have the main camera target the transform of your player object after it has been created.  But, this is how you can manage all the other players.

public void SpawnGuest(int id, NetworkTransform nTransform, string name)
{
 GameObject guestObj = GameObject.Instantiate(guestPrefab) as GameObject;
 guestObj.transform.position = ntransform.Position;
 guestObj.transform.localEulerAngles = ntransform.AngleRotationCC;
 
 guests.Add(id, guestObjt);
 receivers.Add(id, guests[id].GetComponent());
}

public NetworkTransformReceiver GetRecipient(int id)
{
 if(guests.ContainsKey(id)
 {
  return receivers[id];
 }
 
 return null;
}

Feel free to leave me a comment or contact me through www.GuitarRpg.com
This past week I've been coding and debugging the client classes in Unity that will connect to the Smart Fox Extension that I coded for my previous post. Throughout the process I realized how expansive, out of control, and volatile a project can get up until you sort out the problems. The Smart Fox forums were the best source of information, but the information you need is difficult to find and even more difficult to validate. I'd like to explain it here to keep you from having to trudge through the forums as much as I did.

The first thing to do is to decide which Unity classes from the First Person Shooter example would help accomplish one seemingly simple goal. I'll state the goal. "I want smart fox server to respond to a spawn Me request from a Unity client. The server will send a transform (location coordinates) and character prefab name for the client to load into the scene after I log into the room." That was the primary goal, but I also coded beyond that to broadcast a message to all other players in the room so that each client will render every player in the same room.

Previously I used Eclipse to create 3 classes: Connector, ChatWindow, and SmartFoxConnection. Now, to interact with my extension, I've improvised on these other classes from the FPS example: Network Manager, Player Manager, Network Transform, and Network Transform Receiver/Sender. After some trial and error, I decided that Net Beans with Java SE was a much better IDE for this kind of development. It is easier to create a Jar and to attach a debugger with Net Beans.

Once you have set up your project in Net Beans, you can edit the build.xml file to automatically copy your jar by adding these lines of code. (replace the ** items with the actual paths and folder names)



    Builds, tests, and runs the project MyExtension.
    
    
        
            
        
 



Now that you have a .jar use the Smart Fox administrator tool to load the file into your room. I've noticed that when you use a line like "ExtensionRequest request = new ExtensionRequest("spawnMe", new SFSObject(),smartFox.LastJoinedRoom)" it will only work if you add the extension to the room and NOT the zone. Look to the forums for guidance. Adding an extension to the zone is more efficient if you have several rooms. But, for now, you are only trying to get the extension to work within one room in a particular zone.

It's time to debug your extension. It is ALWAYS best to make sure the stuff works on your localhost first. Leave the extension's project open in NetBeans. Using the admin tool go to server configurator and add 127.0.0.1 TCP port 8787 to the allowed incoming connections. Then, you should save your sfs2x.bat in C:\Program Files\SmartFoxServer2X\SFS2X as sfs2x_debug. Using notepad++ or any text editor, the contens of sfs2x_debug should be:

@java -cp "./;lib/*;lib/Jetty/*;extensions/__lib__/*" -Xdebug -Xnoagent 
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n 
-Dfile.encoding=UTF-8 com.smartfoxserver.v2.Main $1 $2 $3

You don't "have" to use 8787, that's just what was suggested in the forums. If you're running a smart fox server, then stop it, and run this .bat instead. It will load a smart fox server that is perfectly capable of debugging with Net Beans or Eclipse (though I suggest Net Beans). Click Debugger->Attach Debugger (after you've started the sfs2x_debug.bat. When you run the project in Unity (with Net Beans project open and attached) then at the break points you've set in net beans, you can see the values of your objects and enjoy the freedom given to you by a debugger. You can also run Unity in debug mode at the same time. A debugger has 3 important tools that look like arrows. Step Over (executes a line of code and all it's internal functions), Step Into (shows you the line of code that is being called: very good for stepping through code that you don't exactly understand), and Step Out (exit the complicated inner workings of code). Use the debugger as much as you can to help avoid hours of searching for errors. I also suggest that in your Unity .cs files you add to your Debug.log ("message") at points in the code you want to make sure are being executed. If you don't see the messages in your Unity console, then you know that that line of code has not been called properly.

These debuggers are the absolute best way to help you code your extensions. If you have any questions, contact me through www.GuitarRpg.com and I'll try to help you out.

Running and Debugging a Room Extension

This past week I've been coding and debugging the client classes in Unity that will connect to the Smart Fox Extension that I coded for my previous post. Throughout the process I realized how expansive, out of control, and volatile a project can get up until you sort out the problems. The Smart Fox forums were the best source of information, but the information you need is difficult to find and even more difficult to validate. I'd like to explain it here to keep you from having to trudge through the forums as much as I did.

The first thing to do is to decide which Unity classes from the First Person Shooter example would help accomplish one seemingly simple goal. I'll state the goal. "I want smart fox server to respond to a spawn Me request from a Unity client. The server will send a transform (location coordinates) and character prefab name for the client to load into the scene after I log into the room." That was the primary goal, but I also coded beyond that to broadcast a message to all other players in the room so that each client will render every player in the same room.

Previously I used Eclipse to create 3 classes: Connector, ChatWindow, and SmartFoxConnection. Now, to interact with my extension, I've improvised on these other classes from the FPS example: Network Manager, Player Manager, Network Transform, and Network Transform Receiver/Sender. After some trial and error, I decided that Net Beans with Java SE was a much better IDE for this kind of development. It is easier to create a Jar and to attach a debugger with Net Beans.

Once you have set up your project in Net Beans, you can edit the build.xml file to automatically copy your jar by adding these lines of code. (replace the ** items with the actual paths and folder names)



    Builds, tests, and runs the project MyExtension.
    
    
        
            
        
    



Now that you have a .jar use the Smart Fox administrator tool to load the file into your room. I've noticed that when you use a line like "ExtensionRequest request = new ExtensionRequest("spawnMe", new SFSObject(),smartFox.LastJoinedRoom)" it will only work if you add the extension to the room and NOT the zone. Look to the forums for guidance. Adding an extension to the zone is more efficient if you have several rooms. But, for now, you are only trying to get the extension to work within one room in a particular zone.

It's time to debug your extension. It is ALWAYS best to make sure the stuff works on your localhost first. Leave the extension's project open in NetBeans. Using the admin tool go to server configurator and add 127.0.0.1 TCP port 8787 to the allowed incoming connections. Then, you should save your sfs2x.bat in C:\Program Files\SmartFoxServer2X\SFS2X as sfs2x_debug. Using notepad++ or any text editor, the contens of sfs2x_debug should be:

@java -cp "./;lib/*;lib/Jetty/*;extensions/__lib__/*" -Xdebug -Xnoagent 
-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n 
-Dfile.encoding=UTF-8 com.smartfoxserver.v2.Main $1 $2 $3

You don't "have" to use 8787, that's just what was suggested in the forums. If you're running a smart fox server, then stop it, and run this .bat instead. It will load a smart fox server that is perfectly capable of debugging with Net Beans or Eclipse (though I suggest Net Beans). Click Debugger->Attach Debugger (after you've started the sfs2x_debug.bat. When you run the project in Unity (with Net Beans project open and attached) then at the break points you've set in net beans, you can see the values of your objects and enjoy the freedom given to you by a debugger. You can also run Unity in debug mode at the same time. A debugger has 3 important tools that look like arrows. Step Over (executes a line of code and all it's internal functions), Step Into (shows you the line of code that is being called: very good for stepping through code that you don't exactly understand), and Step Out (exit the complicated inner workings of code). Use the debugger as much as you can to help avoid hours of searching for errors. I also suggest that in your Unity .cs files you add to your Debug.log ("message") at points in the code you want to make sure are being executed. If you don't see the messages in your Unity console, then you know that that line of code has not been called properly.

These debuggers are the absolute best way to help you code your extensions. If you have any questions, contact me through www.GuitarRpg.com and I'll try to help you out.

Saturday, June 23, 2012

Planning an Extension with Java Server API

In this article I'll describe how to begin making your own server extensions and hint at connecting to a database. If you haven't been reading about this on the Smart Fox website, then I suggest reviewing the information at http://docs2x.smartfoxserver.com/DevelopmentBasics/writing-extensions to gain a basic understanding of why and how to start. The overview is that a .jar file is created by compiling a java project from an IDE (Integrated Development Environment) such as Eclipse. You'll link the SFS2X and SFS2X-core files which contain a lot of classes that you can use in your extension. This includes the User and Room classes which you can extend with extra features and functions.

Smart Fox's Java Server API  http://docs2x.smartfoxserver.com/api-docs/javadoc/server/ is thorough, but this detailed documentation will be more useful when you are trying to learn how to use a specific piece of code. If you've read my prior posts, then you've already downloaded the examples which are a great place to start learning how to write an extension: the Tris and FPS examples. Each of these have the .java files that were used to create a server side extension to run the games. By looking at the code, you can start to understand the layout that you will need for your specific use.

So, at this point, you're probably overwhelmed by how much you need to learn to write even a basic extension... let alone an entire game. Well, that's why you're keeping up with my blog right?  The first question is "what kind of experience are you trying to create for the user". If you'd like to make a game where people can come together and play board games, then the Tris example is a great place to start. Otherwise, if you want to make a game that has character movement in a collaborative or competitive environment, then the place to start is the server code of the First Person Shooter example. Honestly though, it is a good idea to look at the Tris code first because there are fewer files to pore over. Read the code and each time it refers to another file, look there and understand how the files relate to one another.

Here are a few points of advice. Both projects have a .java file with the same name as the extension. This file is like a wrapper for all of the code. It has a reference to most of the other files which in turn reference others. There are also event listeners created here. A RequestListener responds to messages that are sent from the user's scripts (the scripts in Unity). An EventHandler responds to events within the server. Each file in the handlers package contains all the responses to an event listener of the same name.  The FPS example is split into multiple packages, and this is to help you understand which files are closely related.

The Simulation folder holds all the classes that tend to resemble in-game objects. This includes, the world class which contains a list of all the players and objects in the world. The Combat Player class holds all the information of a combatant such as a function to return a transform (location of a player) and functions that respond to event handlers. The files in the helper folder help the extension interact with Smart Fox's User and Room classes. I could go deeper into this but SFS has plenty of documentation on the project; I'm trying to show you how this is all wrapped up into a .jar file that extends the server's ability to monitor this game world and all of its intricacies.

The next step after reading documentation and looking at files is to think of what you need for your game. If you have Microsoft Visio or any other visual layout program then draw a rectangle for each class that you think you need. Add to this class a name and several attributes that you think it needs. Even if you don't manage to follow this exact structure, it's the perfect way to wrap your mind around everything that you are going to need to make your extension. Without this, you won't be able to extract all the important information from the classes. I've had to leave out quite a bit of the code, but that has been easier to discern since I understood what I needed in my code. I tend to remove all the lines that refer to bullets firing because my game doesn't have guns. So sometimes I copy all the contents of a class or function except for a few lines, and I have to rename the variables according to something meaningful for what I am creating.

I'll elaborate on this post when I've finished up my extension. For now I'll tell you this. I'm using the extension to monitor a lot of people in a game world. So, the important things for me are to have a room which monitors the location and animation of the registered players inside. How though, can you allow only players who have registered? This is done with a database that you can also link to your server. You can learn more about server extensions and database connections here: http://docs2x.smartfoxserver.com/GettingStarted/howtos

~Helpful tip
Sometimes, when you add a room extension, the server might not restart because your extension is not built properly. If this happens, you can manually open up the xml at [~installation]\SmartFoxServer2X\SFS2X\zones\yourZoneName.xml. Whether it's a zone or room extenstion, between <extension> and </extension>, delete the contents between <name></name> & <file> </file> to  reset your extension.

As always, feel free to comment here or send me a message by going to www.GuitarRpg.com

Sunday, June 17, 2012

Multiple Unity Scenes and Amazon EC2

Hey followers and new viewers. Today, I will review how to develop an overall structure for your Unity project that's networked with Smart Fox Server 2X. I'll also point you towards starting a server that can be accessed over the web.

I've noticed so many subtle features of Smart Fox that aren't explicitly stated in the documentation. That is why it's important for you to examine the code in the examples: found here SFS Unity Connector. When you look in each example's folder, you'll notice that it contains a deploy and source folder. The deploy folder contains the client which has been built to run in a web browser. The source folder typically contains a Unity package; the "First Person Shooter" and "Tris" example also contain a server folder which holds Java files necessary for maintaining the game on an external server. I discussed the Connector and Lobby examples in my last post, so today, I suggest that you tinker with "Object Movement" which is an example of networked game play that is Client to Client.  Create a new project in Unity and load the package by clicking Assets> Import Package> Custom Package. Once it is imported you will have access to all the scripts and assets for the project.

This example uses multiple Unity scenes which is why we're looking at it today. The architecture for this is that the first person to log in becomes the server. The data for all people who join afterwards is maintained by this first person. If your game doesn't require all that much movement, then this would be a decent architecture for you to look into further. For my purposes though, I'm showing this example so that you understand how to manage a smart fox server through multiple scenes and scripts on the client side without having to use any Java files. However, a game like the MMO you are trying to develop will benefit from having a true server / client architecture that uses Java files on an authoritative server. I'll talk about that in another post though.

The SmartFoxConnection script is crucial for maintaining a connection throughout your project. It holds a private static connection; static variables are maintained in memory until an application closes (watch out for making too many in a scene though; even when that scene is closed, the static variables will not be deleted). The first scene you'll open is Login, and you'll notice that there is a Login GUI script in the hierarchy. When it is selected, look in the inspector to see that the server Name is set to 127.0.0.1 (If you are having problems connecting refer to my last post or go ahead and build it for pc/mac which will solve the problem). When you run this program, before you even click to log in, you're client will already be connected to the server. The connection in SmartFoxConnection is then set to the connection in the Login GUI. This is exactly what you want. Now, when you log in,  you will be logged in to the room The Lobby and the scene will close. If SmartFoxConnection had not copied your connection then the new scene would not be connected. It also maintains a fantastic function on lines 34-38 that will automatically disconnect you from the server when the application closes. If it weren't for this line, Unity would crash each time you stop the application. Now, when any script containing a private SmartFox is loaded with a scene, the instance will copy the static connection that is maintained by your SmartFoxConnection script.

It's important to follow a structure like this because it streamlines the execution of your game. Once you're connected to the server and subsequently logged in to a specific room, you can close the script that has all of those event listeners for the login process. This will make it so that all you need to focus on in the game scripts are the variables and messages that need to be transferred among all the users. You will be able to send public messages to everyone else in your room. You should also automatically send a public message to users in a room once you have logged in and loaded it. This way everyone will know that you've joined. Now take some steps on your own to read all of these scripts and see how they interconnect. If you don't work hard to see how they all work together, then you won't succeed at copying the important parts to your own project and manipulating it to suit your needs.

So that about covers how to manage the connection for all of your scripts in a project. Now, I will point out some of the basics of getting the server running on Amazon. Go to Amazon web services, and you will find that they even have a free plan for 1 year. Be wary though because this plan is intended to be used mostly for testing purposes and could cost you money if you go over the limits. But basically, you need to get the server and then instantiate a Virtual Machine on it. Amazon has several Virtual Machines to choose from which enable you to remotely control a computer. We went with Windows Server 2008 RC2. Install Smart Fox on it and follow the instructions at the bottom of this page Server Installation. If you're using Amazon EC2 to host SFS2X be sure to open the TCP & UDP ports in the Security Group settings in the EC2 control panel. Also, make absolutely certain that you edit the firewall settings as suggested in the Getting Started documentation linked above or it will not let you access it from other computers. Once you start the service, you can copy the URL (excluding http://) and paste it into Server Name in your project's Unity Inspector. You can even control it using the sfs admin tool as per usual with localhost:8080 in the browser on your Virtual Machine. Great try it out with a friend with the Lobby example and you'll both be able to chat with one another.

Thank you for reading. Please comment below with any suggestions, thoughts, or insights. Follow me at https://www.facebook.com/FaytownGames  and join my circles on Google+


Have a more in depth question? Use the forums at www.consortya.com/forums/ or drop me a line at www.GuitarRpg.com

Friday, June 15, 2012

Starting the Server: smart fox lobby example

I'm developing a game that will be played online. It uses Unity as the game engine, and the networking portion is done with smart fox server 2x. Be kind on the parts where I am vague. I am trying to not let on as to what I'm actually building, but I want to create a little tutorial to coincide with the smart fox documentation as well as monitor my progress in this blog. This is my first post, and I've already done a good portion of the programming. As the need becomes apparent, I will explain things I have done already.

So the first thing you'll need to do is download and install the latest version of Unity. Then go to www.smartfoxserver.com to download and install the free smart fox server 2x community edition. We have chosen to develop our Unity scripts in C#. Some of these scripts also act as client code which connects to the smart fox server. Now as it stands, we have started to use a free Amazon server, but it's not fully functional yet. I've read that we should have Right Scale to do it, but we would rather install and manage the server ourselves if possible.

When reading the smart fox documentation, you really have to know exactly what you are looking for. I would suggest reading most of the basics first (you will be rereading most of the documentation multiple times). Then, download the Unity examples and attempt to run them... you'll probably not understand at all what to do on your first go: I didn't. But after a little experimentation, I started to understand what is happening. Most of the examples have a login scene with a connector script. I'd suggest starting with the Lobby example. Now in the Unity inspector you can select which server ip address you want to connect to. You actually have to manage this ip address in the inspector and NOT in the script itself. The serverName is declared as a public variable in the script. This means that when it's value is set in the inspector, it overrides the value that is present in the script. The default is 127.0.0.1 which known to most network programmers as "local host." If you and a friend want to connect to each other, then one computer will be the server, and one computer will be the client. The server computer will connect to the local host. If you're using windows then go to the start menu and type cmd. When it opens a dos window, type ipconfig. Scroll and look for your ip v4 address. Otherwise check out www.whatismyip.com This is the address that your friend will type into serverName in their login scene in Unity. Make sure the host computer has started the smart fox service. You can check by going to your web browser and entering the url localhost:8080 and opening the smart fox admin tool. The default user name and password is sfsadmin.

Now, there is a good chance that your program will throw an error message and not connect to the server. This is an error anytime you have to load a config.xml file. It won't do this in the Unity Editor or a web browser. Essentially, the way it works in the browser it won't fetch the file. Check here for more info http://www.smartfoxserver.com/forums/viewtopic.php?t=13126 Go to your build settings and instead of running the project in the Unity Editor, set it to build for the pc/mac. Build and run it, and you should see that it's connected to the server. In a later post I will figure out a workaround so that you can hard code these settings into the project and thus enable it to run in both the editor and browser. So from here, you should both be connected to the same server and be able to chat with one another. Great!

Please comment with any suggestions, thoughts, or insights. Have a more in depth question? Use the forums at http://www.consortya.com/forums/ and check out my personal website at www.GuitarRpg.com