Affichage des articles dont le libellé est networking. Afficher tous les articles
Affichage des articles dont le libellé est networking. Afficher tous les articles

mercredi 15 juin 2016

Unity : networking part II

I create a tiny connection screen in a nex scene. This scene has no network, only a canvas to show a background picture, and panel/buttons.
To be exhaustive, I ve created a gameobject named PLayerOverScene I talked about in previous article. I linked to this gameobject, the playerscript script. I will store in it, some information, like the ip asked by the player.


Important field for me, now is IP and connect.
I will not speak about login and password for the moment. I will use a rest repository, I will connect to, to validate user/password in a further article.

As always, I will create a c# script to handle click button on connect : ShimConnection.
I create a single simple function:

 public void checkLogin()

I added the script as component to the button.
I create a onclick event on buttonscript component.


For now, when you click on connect button, you will call checkLogin function.

Travel

Now what you want is to load the game scene, and to link to the networked scene from server.

At connect click, I store the Ip into PlayerOverScene:

GameObject playerOverScene = GameObject.Find("PlayerOverScene");
PlayerScript plScript = playerOverScene.GetComponent<PlayerScript>();
plScript.setIpToGo(IP.text);

First of all, you have to load the new scene (I have only two scenes, so for the moment, I will put hardcoded name of the scene).

     SceneManager.LoadScene("scenes/level1");

The game scene will be loaded... now we have to connect to server.
I Will modify this previous code :
public void Start()
    {
         GameObject playerOverScene = GameObject.Find("PlayerOverScene");
        if (playerOverScene == null)
        {
            bool result =this.StartServer();
        }else
        {
            this.StartClient();
        }   
}

To


public void Start()
    {
         GameObject playerOverScene = GameObject.Find("PlayerOverScene");
        if (playerOverScene == null)
        {
            bool result =this.StartServer();
        }else
        {
           PlayerScript ps = playerOverScene.GetComponent<PlayerScript>();
            if (ps)
            {
                this.networkAddress = ps.getIpToGo();

            }
            this.StartClient();
        }   
}

I grab back the Ip store into playerOverScene object to determine to modify internal variable (networkAdress).
I start client, I am connected (I hope) to the server.

Quite simple...


Next step, I will describe how to spawn the player ship...

jeudi 9 juin 2016

Unity : networking part 1

In the way, to have a dedicated server, and client able to connect to it, you can use standard script from unity. One of them, draw a little hud, where you can choose to launch standalone server, a client, or client hosting server.

Another script is more usefull and manage all events upon network : NetworkManager.

For my purpose, I create my onw c# script, inheriting of networkmanager. I wish to override several events, and function, so it is the best way to do. Its name will be ShimNetworkManager.

As in any script, you have a start and update function. In the start function, I will start a server, or start a client.

When the scene will start, this script must be runned. For this, I will add in my scene, a simple GameObject. I will name it NetworkManager.
I will add as component, my newly ShimNetworkManager script.

For now, as you will launch the game, it will execute automatically this script. But how to know if I am a server, or a client?

From my mind, it will be a server, if the game is loading directly this scene.
If the load of the scene comes from an another scene, it is a player trying to connect to a client. It is my assumption.

Pass GameObject scene to scene


I spent lot of time on this question.
When you load a scene, you destroy the old one, and all object belonging to this scene, even those you have instantiated by a script.
Finally, I discover a trick that allow to pass scene to scene some GameObject. So, to know if this is a client that is loading the scene, I test the existence of this object.

I create a second scene, named authentificationLevel. In this scene, I create a GameObject named PlayerOverScene.
I create a c# script named playerScript which will contain in further articles, the information linked to user (name, id, ....).

To allow to an object to be not destroyed, when you change your scene, you have to code this :

void Awake()
    {
        DontDestroyOnLoad(transform.gameObject);
    }

This line of code save your life.

For now, in all scene you will go, this object will remain, and you have a good way to store game information (score, player information, server information,....).

Back to Networking : Client or Server

In ShimNetworkManager, I can test this PLayerOverScene Object to know if I have to run server or client.
public void Start()
    {
         GameObject playerOverScene = GameObject.Find("PlayerOverScene");
        if (playerOverScene == null)
        {
            bool result =this.StartServer();
        }else
        {
            this.StartClient();
        }   
}








mercredi 8 juin 2016

Unity : Shimstar ; reloaded

OK let's try to create a multiplayer space game with 6 degrees of freedom.

I am not sure to follow the right way to create a game from scratch, I will write articles depending of what I consider to be important to know to create a multiplayer game, with physics.

SkyBox


Because, I like to be in the atmosfear, I ve created a skybox using SpaceScape to grab 6 textures.

I create into a folder, named Materials a new Material called skybox. In the inspector, choose the shader (skybox/6 sided)


Next try to add your 6 images to have in the preview your skybox.

Now you can go to the top menu "Window", and choose lighting, to make your new material effective to your scene :

Modify light configuration, to have an ambient light to light your object into the scene.


Networking in Unity

A game is at first defines by different scene. A player will play into one scene, and can travel scene to another scene.
In a configuration of one server, and multiple client connected, you will have a server running for each scene you will create.
The client will loadLevel and connect to the server it needs.
Server must have authority on physics, and will receive input from client, and broadcast results to all client who needs it.
You don't have a global server which manage a world with subscene. It is important to understand this.
Indeed, you will to manage to connect to a scene, and to disconnect from the scene, to connect to another scene running elsewhere (different IP, or different port).

In Unity, each object of the scene, can have multiple component:
  • mesh
  • material
  • scripts
You can associate as much of script you need, to manage behaviour of the object.
For example, you will have 3 scripts:
  • network identity : standard unity script which provide an unique network identity
  • network transform : standard unity script which manage the data transfer of position and rotation of the object
  • your behaviour script : custom script, with your specific fields, and function to manage custom behaviour
Unity will manage network behaviour on object possessing networking script.

Next Step


I will try to describe enough in details the different mechanism, during construction of the game.

I will show you how to manage a connection scene, and connect to a server.

After that, I will show you how to manage physics through networking.







dimanche 14 février 2016

Third Party server with UE4 : part 3 : C++ : connect and read socket

I ve created mainly two functions, one to connect, one other to read socket


I think it is quite easy to understand, and easy to modify to what you need, because apart port and ip, you don't have to modify lot of thing :D.

this->connected, is a variable to store connection status, you can use in a function like isConnected :D


This function will read the socket, retrieve the data in receivedData.
In my case, I will deserialize data from string to json, and I will store the message into a customize class, which will store all message.

This function is called each tick, because I have not lot of information send into these socket.
If you prefer to thread it, you can





Third Party server with UE4 : part 2 : C++ : include package

For now, we need C++ code.
I will not explain how ue manage class, path to includes, and so on. All is not very clear for me.
It seems that when you need to use "package", you have to include it in your build.cs.

Here it is a screenshot of filetree on my computer, of the engine source. In red the non exhaustive list of package under source/runtime.

We will need socket package, and networking, so in my build.cs

using UnrealBuildTool;

public class pocshim : ModuleRules
{
    public pocshim(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","Blu", "Networking", "Sockets","Json" });

    }
}






Third Party server with UE4 : part 1 : nodejs

I have discovered that ue4 is very good for certain purpose, but not good for others.
One of the point is that if you want to manage persistance, or if you want to have information you can dispatch to all players, you need to use a third party server for this (for chat purpose too for example, because you must know all players who are playing to the game).

I ve found piece of code to write a nodejs server. For the moment, it is the easiest way (if you know javascript of course) to write an external third party server. It is light, easy to write, and enough for my purpose.
This server will:
-- receive connection
-- receive TCP message
   -- receive login message
       -- check if the login/password are ok in database
       -- send a json to the sender by TCP message



var net = require('net');
var mysql = require('mysql');

var mySqlClient = mysql.createConnection({
  host     : "*****",
  user     : "****",
  password : "********",
  database : "*******"
});


// Keep track of the chat clients
var clients = [];

// Start a TCP Server
net.createServer(function (socket) {
   
  // Identify this client
  socket.name = socket.remoteAddress + ":" + socket.remotePort

  // Put this new client in the list
  clients.push(socket);

  // Send a nice welcome message and announce
  //~ socket.write("Welcome " + socket.name + "\n");
  broadcast(socket.name + " joined the chat\n", socket);

  // Handle incoming messages from clients.
  socket.on('data', function (data) {
    //broadcast(socket.name + "> " + data, socket);
      try{
        var val = JSON.parse(data);
        if (val.code == "1"){
            login(socket,val);
        }
      }catch(err){
            console.log("data received not in JSON format : "  + data  + "/////" + err);
      }
  });
    socket.on('error',function(){
        console.log('socket reset');
        clients.splice(clients.indexOf(socket), 1);
    });
  // Remove the client from the list when it leaves
  socket.on('end', function () {
    clients.splice(clients.indexOf(socket), 1);
    broadcast(socket.name + " left the chat.\n");
  });
 
  function login(sender,jsonObj){
      //~ console.log(jsonObj);
      var selectQuery = "SELECT * FROM table where name ='" + jsonObj.login + "' and passwd = '" + jsonObj.password +"'";
       var status=0;
        var sqlQuery = mySqlClient.query(selectQuery);
        sqlQuery.on("result", function(row) {

          status=1;
        });
       
        sqlQuery.on("end", function() {
            //~ if (status){
          //~ mySqlClient.end();
            //~ }
          sender.write('{"code":"1","status":"' + status + '"}');
        });
       
        sqlQuery.on("error", function(error) {
          console.log(error);
            sender.write('{"code":"1","status":"-1"}');
        });

  }
 
  // Send a message to all clients
  function broadcast(message, sender) {
    clients.forEach(function (client) {
      // Don't want to send it to sender
      if (client === sender) return;
      client.write(message);
    });
    // Log it to the server output too
    process.stdout.write(message)
  }

}).listen(5000);

// Put a friendly message on the terminal of the server.
console.log("Chat server running at port 5000\n");







 

vendredi 22 janvier 2016

ue4 multiple level zoning, and architecture

It is important to understand how ue4 works to make a multiplayer game.
A dedicated server runs only one level (physics, replication, ...).
You have multiple possibilities. If all your players are changing of zone at same time, and the zone is loaded only at this moment, your server can change zone, and load it, and the clients will do the same.
One server is enough

But if you wish to have several zone running at same time, you must keep in mind, that you must have one dedicated server per zone.
The client will connect to the server it needs at the moment it wants.
From my side, when client is launched, it is not connected. It shows a level with a tiny scene, and an UI to fill knickname, and a button to connect.
Once player clicks on connect, I send a connection to the first server using IP and port.
it is enough. Once connected, the server will send the level to load, and replicate actors which need to be replicated.

during game, maybe player wish to change zone, to travel elsewhere. I will disconnect to current server, probably load a temporary level, with tiny scene, to wait connection to other server, and then I will connect to a new IP/Port, to reach the new server hosting the level I want to travel to.
Once again, the server will send the name of level to load, and replicate what it needs.

Finally it is quite standard as an architecture, but you don't have choice, it is way to do.

I got a question on instantied zone. I think best way is to have a running server by instance too.

vendredi 8 janvier 2016

Networking : day 3 : torque

After moving forward, next step is to rotate on 2 axis (I choosed 2 for more convenient, I don't like roll :p).

As seen before, the keyboard input are given on client side, and the physics is managed on server side.
So the input must be treated on remote, and the modification value done on server.

First, create input in project settings : using QD and ZS.













Next, we will in pawn blueprint, create an addTorque server event (custom event), running on server, with a vector in input.



 Now we can react at leftright event, and calculate the vector to apply torque



Notice the switch has autority... It is keyboard input, so we have to use remote activity.
 And now, we have to apply torque server side



I think switch has authority is not necessary here, it is more convenient to show example...

Finally, we will catch updown event, to pitch the spaceship


 Done...

For now, you can speed up to go forward, apply torque to turn right/left, or up/down.

Because you are using physics, reaction on bouncing, will be quite realistics

mercredi 6 janvier 2016

networking ue4 : day 2

You got speed management... but now how to move your pawn?

First of all, check that your spaceship is using physics... Go to your pawn blueprint, and look at your static mesh


Check simulate physics, put linear and angular damping at 1, to have enough frictions, to slow your ship in rotation or movement (otherwise it will speed very highly, and rotate very quickly... :p)

It is a space game, I disabled gravity.

Physics is important  on server, but totally unusefull on client, so desactivate it, on begin play event.



As you see you choose remote on switch autority, to disable physics simulation only on client side.

I am using physics because, I wish to have bounce behavior, collision, and so on. So I will add Force to my mesh, to make it move forward.
I will do this on server



And this is it, your pawn is moving. But client didn't see the move...
I created a custom event, I will use to broadcast the new position/rotation to client. I give to it, vector and rotator as parameter.
Multicast == broadcasting


On server side, I will get my rotation, and location, and give it to my custom event. Custom event will run on client side, I set to my mesh, the new position and location.


Global schema is this
































ue4 : networking day1

The aim of my game is to do a multiplayer game, with a dedicated server and clients.

It was sometimes hard to find my way, to understand networking in unreal engine, so I will try to take time to explain different things about networking, and to illustrate what I 've done in my game about the different topic.

If you need, more precise focus, let me know.

First of all, because it is dedicated server, server has control over all things. You have to draw blueprint in same blueprint for case of "server", and case of "client".

It is important to understand this. It is important also to understand what will be managed by server and replicated to client, and what is manage by client.

On client board, you will manage essentially UI, special effects, keyboard/mouse input management...
Server will manage AI, movement, physics, spawning, ...

So every time, you wish to move your pawn, through keyboard input, you will have to send the information to server, which will move the pawn, and replicate/broadcast new position.

Ok with this very few basics...

First, I will show you how to manage increase/decrease speed on my spaceship.
First I create new input in project settings








 Next in my pawn Blueprint, I create two variables, speed, and speedmax.
Speed will be replicated. It is an information needed by client to manage UI and FX for example.
Replication is always from server to client.



I ve created next a new custom event in my blueprint. The event receives the new speed, and set the variable with it.
Event must be run on server



 Finally, I receive my speed input (through A or W keyboard input), and I manage the increase of speed, and send it to server.





Pay Attention on switch authority. Switch authority allows to run what is after on server, or client. Here, because it is a client input, I have to manage following on client. So I choose remote.
If it was an event about collision for example, I must switch on authority, to manage it only on server.

If you don't use this switch, it will be run on both (client and server), and you can have strange behavior or maybe error. For example, if you manage to update an UI, on dedicated server, you will have errors, because there is no window for server.

Here, you will manage keyboard input to increase speed, and send the update to server.
Server will update speed variable, and because of that, the update will be replicated to all client.

To do better, you can send the input to server, which will manage the different test case, to be sure and guarantee no cheat :D