【问题标题】:Is there any way to send or receive images, audio and video using Photon Pun2 or Photon Chat?有没有办法使用 Photon Pun2 或 Photon Chat 发送或接收图像、音频和视频?
【发布时间】:2021-05-17 20:33:28
【问题描述】:

我在我的应用程序中同时使用了 Photon Pun2 和 Photon Chat 软件包。但是我找不到任何通过私信发送或接收图像、音频或视频的方法。

【问题讨论】:

    标签: unity3d multiplayer photon


    【解决方案1】:

    是的……但是,它非常有限。

    你要寄的东西到底有多大?


    聊天

    在 Photon 聊天消息中,有效负载限制在 400.000 到 500.000 字节之间。我没有更详细地对其进行测试,但是如果您的消息大小达到某个限制,您将立即断开连接而没有适当的反馈,原因是^^

    Photon Chat Intro

    例子

    public class MyChatListner : IChatClientListener
    {
        public event Action<byte[]> OnReceived;
    
        private ChatClient cient;
    
        public void Initialize()
        {
            client = new ChatClient(this);
            
            client.ChatRegion = ...;
            client.Connect(....);
        }
     
        // Sicne you already work with the chat you should know but anyway
        // This has to be called continuously (who knows in what intervals)
        public void Heartbeat()
        {
            client.Service();
        }
    
        public void SendData(string recipient, byte[] data)
        {
            client.SendPrivateMessage(recipient, data);
        }
    
        public void OnPrivateMessage(string sender, object message, string channelName)
        {
            OnReceived?.Invoke((byte[])message);
        }
        
        // also will have to implement the other methods from IChatClientListener ...
    }
    

    PUN2

    在 Pun2 中,我不知道是否存在这样的限制,但它肯定会延迟其他一切,直到文件完全接收。这里可以直接通过PhotonNetwork.RaiseEventOnEvent收发byte[](通过接口IOnEventCallback

    例子

    // doesn't even have to be monobehaviour necessarily
    public class FileTransmitter : IOnEventCallback
    {
        private const byte eventID = 42;
    
        public event Action<byte[]> OnReceived;
    
        public void Enable()
        {
            PhotonNetwork.AddCallbackTarget(this);
        }
    
        public void Disable()
        {
            PhotonNetwork.RemoveCallbackTarget(this);
        }
    
        public void SendData(byte[] data, SendOptions sendoptions, RaiseEventOptions raiseEventOptions = null)
        {
            PhotonNetwork.RaiseEvent(eventID, data, raiseEventOptions, sendoptions);
        }
    
        public void OnEvent(EventData photonEvent)
        {
            if(photonEvent.Code != eventID) return;
    
            var data = (byte[]) photonEvent.CustomData;
    
            OnReceived?.Invoke(data);
        }
    }
    

    当然,您也可以直接使用RPC 并使用例如

    public class FileTransfer : MonoBehaviourPun
    {
        [PunRPC]
        void ChatMessage(string fileName, byte[] content)
        {
            // e.g.
            File.WriteAllBytes(Path.Combine(Application.persistentDataPath, fileName), content);
        }
    
        public void SendFile(string fileName, byte[] content, PhotonPlayer targetPlayer)
        {
            photonView.RPC(nameof(ChatMessage), targetPlayer, fileName, content);
        }
    }
    

    无论哪种方式,我个人所做的只是使用一个byte[] 并将所有必需的信息编码到其中。 Photon 无论如何都会使用所有参数执行此操作,但如果您已经确切知道您发送的数据以及如何反序列化它,那么您自己执行此操作会更有效,例如在线程/任务中。然后在接收方我再次将这些反序列化为个人信息。

    【讨论】:

      【解决方案2】:

      这是可能的并且工作得很好(即使你应该注意@derHugo 所说的限制)。我的实现使用 RPC 使用 Texture2D.EncodeToPNG 发送一个字节数组,然后在客户端收到它后对其进行解码。

      要将字节数组转换回图像,可以使用Texture2D.LoadImage 方法。

      发送其他多媒体类型的方法类似,只是编码/解码方法不同。

      【讨论】:

        【解决方案3】:

        PhotonStream 允许您通过网络传输任何 byte[] 数据。 理论上,任何数据类型都可以转换成byte[],并在接收端解码。


        下面的示例脚本只是一个设置最少的示例。 参考自:https://frozenmist.com/docs/apis/fmetp-stream/pun2-example/

        还可以使用流行的第三方插件(如 FMETP STREAM)实时流式传输视频、音频和远程命令,该插件具有本机快速编码器,可实时捕获您的游戏视图和桌面视图,甚至与移动和 VR 设备兼容。

        using Photon.Pun;
        using System.Collections;
        using System.Collections.Generic;
        using UnityEngine;
        
        // ref: https://frozenmist.com/docs/apis/fmetp-stream/pun2-example/
        public class FMStreamPUN : Photon.Pun.MonoBehaviourPun, IPunObservable {
            private Queue<byte[]> appendQueueSendData = new Queue<byte[]>();
            public int appendQueueSendDataCount { get { return appendQueueSendData.Count; } }
        
            public UnityEventByteArray OnDataByteReadyEvent = new UnityEventByteArray();
        
            public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
                if (stream.IsWriting) {
                    //Send the meta data of the byte[] queue length
                    stream.SendNext(appendQueueSendDataCount);
                    //Sending the queued byte[]
                    while(appendQueueSendDataCount > 0) {
                        byte[] sentData = appendQueueSendData.Dequeue();
                        stream.SendNext(sentData);
                    }
                }
        
                if (stream.IsReading) {
                    if (!photonView.IsMine) {
                        //Get the queue length
                        int streamCount = (int)stream.ReceiveNext();
                        for (int i = 0; i < streamCount; i++) {
                            //reading stream one by one
                            byte[] receivedData = (byte[])stream.ReceiveNext();
                            OnDataByteReadyEvent.Invoke(receivedData);
                        }
                    }
                }
            }
        
            public void Action_SendData(byte[] inputData) {
                //inputData(byte[]) is the encoded byte[] from your encoder
                //doesn't require any stream, when there is only one player in the room
                if(PhotonNetwork.CurrentRoom.PlayerCount > 1) appendQueueSendData.Enqueue(inputData);
            }
        }
        

        【讨论】:

        • 嗨@sharimken,你成功实现了 Frozen Mist 编写的代码吗?我也使用他们的资产并尝试使用上面给出的代码使用 PUN 2 实现流式传输,但性能并不成功。游戏变得如此滞后,具有解码器本身的接收器将在流媒体给出的实际更新后最多 5-7 秒更新动作。
        • 我对上述代码的实现: 1. 创建包含 FMStreamPun.cs 和 Photon 视图的网络对象的预制件 2. 自加载游戏场景以来,当将流式传输其游戏的玩家进入房间时,该对象被实例化. 3. 当带有解码器的客户端进入房间时,流发生,并且在 Start() 上将找到具有 FMStreamPUN 的可用网络对象,并将通过 FMStreamPUN 的 OnDataByteReadyEvent 处理图像数据。 4. 是的,Action_SendData 由流媒体客户端的编码器调用。由于 FMStreamPUN 对象将被相应地实例化。谢谢
        • 我们也可以在我们这边重现这个问题,感谢您指出 PUN2 性能问题。我们发现一个临时解决方案是手动控制流量。例如,如果在一秒钟内发送的字节数超过 32k,我们不应该流式传输帧,直到流量低于此数字。
        • 我 99% 确定 PUN2 的 UDP 是可靠的,即使我选择了不可靠的发送方式,它也会尝试重新发送丢失的数据。因此,当您拥有大量数据时,累积的延迟可能会很大。
        猜你喜欢
        • 1970-01-01
        • 2020-03-09
        • 1970-01-01
        • 1970-01-01
        • 2014-06-29
        • 1970-01-01
        • 2012-11-05
        • 1970-01-01
        • 2021-12-15
        相关资源
        最近更新 更多