DEV Community

Masui Masanori
Masui Masanori

Posted on • Updated on

[Unity] Communicate with SignalR from Unity

Intro

This time, I will try communicating with SignalR from Unity applications.
For server side, I will use the application what I created last time.

Environments

  • Unity ver.2020.2.1f1
  • Microsoft.AspNetCore.SignalR.Client ver.5.0.4
  • nuget.exe ver.5.8.1

AspNetCore.SignalR.Client

I can connect SignalR hub by AspNetCore.SignalR.Client.
I used JavaScript(TypeScript) version last time.

This time, I use C# version.

Though this library is named "AspNetCore", it complies .NET Standard.
So I can use it from WPF, Unity, and so on like the article above.

Use AspNetCore.SignalR.Client from Unity

How to install?

One important problem is I can't use NuGet for Unity applications.
So I must put dlls into the Assets/Plugins folder manually.

First, I tried installing AspNetCore.SignalR.Client in a .NET 5 console application, and copying dlls.
But the dlls were complied .NET Standard 2.1.

Because Unity applications only could use .NET Standard 2.0.

So I used NuGet of commandline version.

I just installed nuget.exe and executed "./nuget install Microsoft.AspNetCore.SignalR.Client".

Copy dlls

After installing, I could get packages.
Alt Text

And there were some dlls for several platforms.
Alt Text

So I copied netstandard2.0 one.

First, I copied "Microsoft.AspNetCore.SignalR.Client.Core.dll" and got errors.
It was because lacking of dependencies. So I copied them.

When I couldn't get .NET Standard2.0 packages, I copied older one.

Copied dlls

  • Microsoft.AspNetCore.Http.Connections.Client.dll
  • Microsoft.AspNetCore.Http.Connections.Common.dll
  • Microsoft.AspNetCore.Http.Features.dll
  • Microsoft.AspNetCore.SignalR.Client.Core.dll
  • Microsoft.AspNetCore.SignalR.Client.dll
  • Microsoft.AspNetCore.SignalR.Common.dll
  • Microsoft.AspNetCore.SignalR.Protocols.Json.dll
  • Microsoft.Bcl.AsyncInterfaces.dll
  • Microsoft.Extensions.DependencyInjection.Abstractions.dll
  • Microsoft.Extensions.DependencyInjection.dll
  • Microsoft.Extensions.Logging.Abstractions.dll
  • Microsoft.Extensions.Logging.dll
  • Microsoft.Extensions.Options.dll
  • Microsoft.Extensions.Primitives.dll
  • System.Buffers.dll
  • System.Diagnostics.DiagnosticSource.dll
  • System.IO.Pipelines.dll
  • System.Memory.dll
  • System.Runtime.CompilerServices.Unsafe.dll
  • System.Text.Encodings.Web.dll
  • System.Text.Json.dll
  • System.Threading.Channels.dll
  • System.Threading.Tasks.Extensions.dll

  • Unity で ASP.NET Core SignalR を利用する - xin9le.net

Communicate with SignalR

MainPage.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Microsoft.AspNetCore.SignalR.Client;

public class MainPage : MonoBehaviour
{
    public Text ReceivedText;
    public InputField MessageInput;
    public Button SendButton;
    private SignalRConnector connector;
    public async Task Start()
    {
        connector = new SignalRConnector();
        connector.OnMessageReceived += UpdateReceivedMessages;

        await connector.InitAsync();
        SendButton.onClick.AddListener(SendMessage);
    }
    private void UpdateReceivedMessages(Message newMessage)
    {
        var lastMessages = this.ReceivedText.text;
        if(string.IsNullOrEmpty(lastMessages) == false)
        {
            lastMessages += "\n";
        }
        lastMessages += $"User:{newMessage.UserName} Message:{newMessage.Text}";
        this.ReceivedText.text = lastMessages;
    }
    private async void SendMessage()
    {
        await connector.SendMessageAsync(new Message
        {
            UserName = "Example",
            Text = MessageInput.text,
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Message.cs

public class Message
{
    public string UserName { get; set; }
    public string Text { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

SignalRConnector.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using Microsoft.AspNetCore.SignalR.Client;

public class SignalRConnector
{
    public Action<Message> OnMessageReceived;
    private HubConnection connection;
    public async Task InitAsync()
    {
        connection = new HubConnectionBuilder()
                .WithUrl("http://localhost:5000/chatHub")
                .Build();
        connection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            OnMessageReceived?.Invoke(new Message
            {
                UserName = user,
                Text = message,
            });
        });
        await StartConnectionAsync();
    }
    public async Task SendMessageAsync(Message message)
    {
        try
        {
            await connection.InvokeAsync("SendMessage",
                message.UserName, message.Text);
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.LogError($"Error {ex.Message}");
        }
    }
    private async Task StartConnectionAsync()
    {
        try
        {
            await connection.StartAsync();
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.LogError($"Error {ex.Message}");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Alt Text

--- 2021-04-01 Update ---

IL2CPP

When I set "Scripting Backent" to "IL2CPP", I will get error.
Alt Text

Because some classes are removed.
For avoiding this problem, I add "link.xml" into the Assets folder.

link.xml

<linker>
    <assembly fullname="Microsoft.AspNetCore.Connections.Abstractions" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.Http.Connections.Client" preserve="all"/>
     <assembly fullname="Microsoft.AspNetCore.Http.Connections.Common" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.Http.Features" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.SignalR.Client.Core" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.SignalR.Client" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.SignalR.Common" preserve="all"/>
    <assembly fullname="Microsoft.AspNetCore.SignalR.Protocols.Json" preserve="all"/>
    <assembly fullname="Microsoft.Bcl.AsyncInterfaces" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection.Abstractions" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.DependencyInjection" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Logging.Abstractions" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Logging" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Options" preserve="all"/>
    <assembly fullname="Microsoft.Extensions.Primitives" preserve="all"/>
    <assembly fullname="System.Buffers" preserve="all"/>
    <assembly fullname="System.Diagnostics.DiagnosticSource" preserve="all"/>
    <assembly fullname="System.IO.Pipelines" preserve="all"/>
    <assembly fullname="System.Memory" preserve="all"/>
    <assembly fullname="System.Runtime.CompilerServices.Unsafe" preserve="all"/>
    <assembly fullname="System.Text.Encodings.Web" preserve="all"/>
    <assembly fullname="System.Text.Json" preserve="all"/>
    <assembly fullname="System.Threading.Channels" preserve="all"/>
    <assembly fullname="System.Threading.Tasks.Extensions" preserve="all"/>
</linker>
Enter fullscreen mode Exit fullscreen mode

Discussion (5)

Collapse
warriorwork profile image
WarriorWork • Edited on

Thanks for great tutorial!
I get the error in picture..
dev-to-uploads.s3.amazonaws.com/up...
I have to use the newtonsoft.Json 8.0.0.0 because I use it for IBM plugin...

What can I do?

Thanks!

Collapse
masanori_msl profile image
Masui Masanori Author • Edited on

Thank you for reading my post.

I have to use the newtonsoft.Json 8.0.0.0 because I use it for IBM plugin...
What can I do?

I think it's hard to resolve :(.
Because "Microsoft.AspNetCore.SignalR.Client" requires .NET Standard 2.0 compatibility from ver.1.0.0.

nuget.org/packages/Microsoft.AspNe...

But Newtonsoft.Json has supported .NET Standard 2.0 from ver.11.

github.com/JamesNK/Newtonsoft.Json...

So I think it's better to find out how to force to use Newtonsoft.Json version 11 or later.

Collapse
warriorwork profile image
WarriorWork

Hey I think I resolved the problem!
At the begining I was following this tutorial:
youtube.com/watch?v=ntqxSSWG66g
And he uses Newtonsoft... then I pay attenion to your post and you didnt use it.
So I was following your tutorial post and it works good I dont need to change my newtonsoft to any versions

Thank you!

Collapse
warriorwork profile image
WarriorWork

Hi!
In Mac OS it should work? Because when I run it on MAC I cannot connect to the Server by:
connection = new HubConnectionBuilder()
.WithUrl("localhost:5000/chatHub")
.Build();

The HubConnection.ConnectionID is empty. In others platforms it works but only in MacOS it doesn't work... Do you have any idea?

Collapse
pereviader profile image
Pere Viader

One important problem is I can't use NuGet for Unity applications. So I must put dlls into the Assets/Plugins folder manually.

You might be interested in this project I did github.com/PereViader/CSharpProjec...
It might help you integrate any c# project as a unity package