Code Monkey home page Code Monkey logo

unitysimpletcpnetwork's Introduction

Exploring TCP Network in Unity

I have checked out several network libraries to use with unity. Then I wanted to make a simple one from scratch.

I found some tutorials and repos along the way and they helped a lot. But mostly, they were too complicated or abstracted. I just needed a dune buggy.

So, I tried my best to keep it simple and lean.

Hope that this project helps you, if you're trying to figure out TCP network in your game.

Why Unity as a Server?

Why would I use unity as a server while dotnet core is great?

Because unity has an editor, scene management, physics, navigation and so on.

Sample

Here is the complete network folder below.

...
Network
└───Message
│   │   Message.cs
│   │   MessageHandler.cs
│   │   MessageSerializeExtensions.cs
│   Client.cs
│   Connection.cs    
│   Server.cs
│   ThreadManager.cs
...

Open up the Server scene. There is a component created for server to setup and listen ServerApplicationStartup.

using System;
using UnityEngine;

public class ServerApplicationStartup : MonoBehaviour
{
    private Server _server;
    private MessageHandler _handler;

    private void Start()
    {
        _server = new Server(7777);
        _server.Start();
        _server.ClientConnectedEvent    += OnClientConnect;
        _server.MessageReceivedEvent    += OnMessage;
        _server.ClientDisconnectedEvent += OnClientDisconnect;

        _handler = new MessageHandler();
        _handler.AddHandler("chat", HandleChatMessage);
    }

    //  event callbacks
    private void OnClientConnect(int connId)
    {
        var greet = new GreetData()
        {
            id = connId,
            greetMessage = "Server connection success. Welcome to chat."
        };

        var msg = new Message()
        {
            header = "greet",
            body   = greet.Serialize()
        };

        _server.Send(connId, msg.Serialize());
    }

    private void OnMessage(int connId, byte[] data)
    {
        _handler.Handle(data);
    }

    private void OnClientDisconnect(int connId)
    {
        Debug.Log("Client connection lost. connId: " + connId);
    }

    private void OnApplicationQuit()
    {
        _server.Stop();
    }

    //  handlers
    private void HandleChatMessage(byte[] data)
    {
        var chat = data.Deserialize<ChatData>();

        Debug.Log("received chat, author: " + chat.author);

        var msg = new Message()
        {
            header = "chat",
            body = data
        };
        
        _server.SendAll(msg.Serialize());
    }
}

For the client scene I created some ui elements.

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

public class ClientApplicationStartup : MonoBehaviour
{
    public string ip = "127.0.0.1";
    public int port = 7777;
    public Transform canvasParent;
    public GameObject loginPrefab;
    public GameObject chatPrefab;

    private string _clientNickname;
    private ChatPanel _chatPanel;

    private Client _client;
    private MessageHandler _handler;

    private void Start()
    {
        var login = Instantiate(loginPrefab, canvasParent).GetComponent<LoginPanel>();
        login.inputField.onEndEdit.AddListener(input => _clientNickname = input );
        login.connectButton.onClick.AddListener(() => Connect());
    }

    private void CreateChatPanel()
    {
        _chatPanel = Instantiate(chatPrefab, canvasParent).GetComponent<ChatPanel>();
        _chatPanel.chatLogText.text = "";
        _chatPanel.inputField.onEndEdit.AddListener(OnChatInput);
        _chatPanel.inputField.ActivateInputField();
    }
    
    private void Connect()
    {
        CreateChatPanel();

        _client = new Client();
        _client.Start(ip, port);
        _client.OnMessageReceived   += MessageReceived;
        
        _handler = new MessageHandler();
        _handler.AddHandler("chat",     HandleChatMessage);
        _handler.AddHandler("greet",    GreetHandleMessage);
    }

    //  event callbacks
    private void MessageReceived(byte[] msg)
    {
        _handler.Handle(msg);
    }

    private void OnChatInput(string input)
    {
        if (!string.IsNullOrEmpty(input) && !string.IsNullOrWhiteSpace(input))
        {
            var chat = new ChatData()
            {
                author = _clientNickname,
                entry  = input
            };

            var msg = new Message()
            {
                header = "chat",
                body   = chat.Serialize()
            };

            _client.Send(msg.Serialize());

            _chatPanel.inputField.text = "";
            _chatPanel.inputField.ActivateInputField();
        }
    }

    private void OnApplicationQuit()
    {
        _client.Disconnect();
    }

    //  handlers
    private void HandleChatMessage(byte[] data)
    {
        var chat = data.Deserialize<ChatData>();
        _chatPanel.AddLog(chat.author + ": " + chat.entry);
    }

    private void GreetHandleMessage(byte[] data)
    {
        var greet = data.Deserialize<GreetData>();
        _chatPanel.AddLog(greet.greetMessage);
        _chatPanel.AddLog("Connection id: " + greet.id);
    }
}

Finally, ThreadManager is responsible for executing on main thread. Further info here, https://stackoverflow.com/questions/41330771/use-unity-api-from-another-thread-or-call-a-function-in-the-main-thread

Closing words

When I search for this topic, I saw so much discussion about unity, old and new unity network stack and it's server capabilities.

Also, in this forum thread, Joachim Ante(CTO, Unity) gives detailed answers to some good questions.

https://forum.unity.com/threads/dots-netcode-for-mmorpg.867463/

At this point, would I use a custom homebrew server from scratch in my in-production game?

Well if I need to fill my custom needs, I would bet my money on Telepathy and it's aproach to solve unity bounds and battle tested codebase. Here some detailed info on this topic from the author,

https://mirror-networking.com/apathy/

https://github.com/vis2k/Telepathy

Referenced resources

Telepathy

SimpleUnityTCP

Tom Weiland unity network series

Facepunch.Steamworks

LICENCE

MIT

unitysimpletcpnetwork's People

Contributors

cemuka avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.