DEV Community

loading...

[Unity] Communicate with SignalR from Unity

Masui Masanori
Programmer, husband, father I love C#, TypeScript, etc.
Updated on ・4 min read

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 (0)