unity3d 有没有办法使用Photon Pun2或Photon Chat发送或接收图像、音频和视频?

noj0wjuj  于 2023-01-31  发布在  其他
关注(0)|答案(3)|浏览(349)

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

sd2nnvve

sd2nnvve1#

是的,有......但是,它是相当有限的。
你要寄的东西到底有多大?

聊天

在光子聊天中,消息的有效负载被限制在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[]和编码所有需要的信息到它。光子将这样做无论如何与所有参数,但如果你已经知道你发送什么数据,以及如何反序列化它,这是更有效的方式来做它自己,例如在线程/任务。然后在接收器端,我反序列化这些到个人信息再次。

33qvvth1

33qvvth12#

这是可能的,而且工作得很好(尽管你应该像@derHugo说的那样注意限制)。我的实现使用RPC发送一个字节数组,使用Texture2D.EncodeToPNG,然后在客户端接收到它时对其进行解码。
要将字节数组转换回图像,可以使用Texture2D.LoadImage方法。
该方法类似于发送其它多媒体类型,只是编码/解码方法不同。

iqjalb3h

iqjalb3h3#

PhotonStream允许你通过网络传输任何byte[]数据。理论上,任何数据类型都可以转换成byte[],并在接收端解码它们。
下面的示例脚本只是一个具有最小设置的示例。参考来源:https://frozenmist.com/docs/apis/fmetp-stream/pun2-example/
您还可以使用FMETP STREAM等流行的第三方插件实时传输视频、音频和远程命令,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);
    }
}

相关问题