草庐IT

Unity Render Streaming通过Js与Unity自定义通讯

foenix66 2023-11-27 原文

Unity Render Streaming通过Js与Unity自定义通讯


Js通讯发送示例在WebApp\client\public\videoplayer;
对应C#接收端案例Unity Render Streaming插件的WebBrowserInput

JS发送部分

videoplayer/js/main.js按钮通讯示例

    const elementBlueButton = document.createElement('button');
    elementBlueButton.id = "blueButton";
    elementBlueButton.innerHTML = "Light on";
    playerDiv.appendChild(elementBlueButton);
    elementBlueButton.addEventListener("click", function () {
      sendClickEvent(videoPlayer, 1);
    });

案例只能发送一个按钮Number ID
往上溯源,在js/register-events.js文件中的sendClickEvent函数

export function sendClickEvent(videoPlayer, elementId) {
  let data = new DataView(new ArrayBuffer(3));
  data.setUint8(0, InputEvent.ButtonClick);
  data.setInt16(1, elementId, true);
  videoPlayer && videoPlayer.sendMsg(data.buffer);
}

核心代码

videoPlayer.sendMsg(data.buffer); // 这是一个二进制数组发送函数,理论上可以发送任意数据。
data.setUint8(0, InputEvent.ButtonClick); // 二进制数组的第一个字段是1个字节的类型标记
data.setInt16(1, elementId, true); // 第一个字节之后的数据由标签类型定义不同而解释不同,这里转为2字节的short类型,代表按钮id

查看案例已经定义的所有通讯类型

const InputEvent = {
  Keyboard: 0,
  Mouse: 1,
  MouseWheel: 2,
  Touch: 3,
  ButtonClick: 4,
  Gamepad: 5,// 案例定义了0-5标记,分别对应鼠标键盘游戏手柄,和按钮通讯
};

我们新增加一个发送字符串的通讯类型,定义标签为 6

  function sendMessage(videoPlayer, message) {
    function utf8FromStr(str) {
      var strUtf8 = unescape(encodeURIComponent(str)); // UTF8编码文本到二进制
      var arr = new Uint8Array(strUtf8.length);
      for (var i = 0; i < strUtf8.length; ++i) {
        arr[i] = strUtf8.charCodeAt(i);
      }
      return arr;
    }
    message = " " + message; // 预留空格作为第一个字节,存放类型标签6
    var buf = utf8FromStr(message);
    let data = new DataView(buf.buffer);
    data.setUint8(0, 6); // 自定义标签6顶替掉第一个预留的空格字符

    videoPlayer && videoPlayer.sendMsg(data.buffer); // 发送二进制数据串
  }
  function sendJson(videoPlayer, json) { // 也可以发送自定义Json格式化文本数据
    sendMessage(videoPlayer, JSON.stringify(json));
  }

C#接收部分

Unity Streaming Render示例的WebBrowserInputChannelReceiver是接收webRtc数据通讯的通道(channel),继承自InputChannelReceiverBase类。WebBrowserInputChannelReceiver通过消息注册获取标签类型为4的ButtonClick事件
我们的目标是自定义字符串(JSON)通讯,默认基类不会处理自定义类型。
从派生一个新类,直接继承OnMessage接收二进制数据流函数,OnMessage收到的字节流就是JS中sendMsg发送的二进制原始数据
代码如下:

  public class DBBrowserInputChannelReceiver : WebBrowserInputChannelReceiver
  {
    public GameObject[] targets;
    protected override void OnMessage(byte[] bytes)
    {
      if (bytes.Length > 0)
      {
        int code = bytes[0]; // 第一个字节为通讯类型标记
        if (code == 6) // 我们自定义的字符串通讯类型标记
        {
          string message = System.Text.UTF8Encoding.UTF8.GetString(bytes, 1, bytes.Length - 1); // 去掉数据流第一个标记字节,剩余字节通过UTF8编码转化回字符串,对应JS的UTF8编码函数unescape(encodeURIComponent(str))
          foreach (GameObject go in targets)
          {
            go.SendMessage("OnNetMessage", message); // 将数据通过Unity的SendMessage发送给处理节点
          }
          if (code <= 5)
          {
            base.OnMessage(bytes); // 通过基类处理默认类型消息
          }
        }
      }
    }
  }

有关Unity Render Streaming通过Js与Unity自定义通讯的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  4. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  5. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  6. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  7. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  8. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  9. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  10. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

随机推荐