有没有办法使用 Photon Pun2 或 Photon Chat 发送或接收图像、音频和视频?
Posted
技术标签:
【中文标题】有没有办法使用 Photon Pun2 或 Photon Chat 发送或接收图像、音频和视频?【英文标题】:Is there any way to send or receive images, audio and video using Photon Pun2 or Photon Chat? 【发布时间】:2021-05-17 20:33:28 【问题描述】:我在我的应用程序中同时使用了 Photon Pun2 和 Photon Chat 软件包。但是我找不到任何通过私信发送或接收图像、音频或视频的方法。
【问题讨论】:
【参考方案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.RaiseEvent
和OnEvent
收发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 是可靠的,即使我选择了不可靠的发送方式,它也会尝试重新发送丢失的数据。因此,当您拥有大量数据时,累积的延迟可能会很大。以上是关于有没有办法使用 Photon Pun2 或 Photon Chat 发送或接收图像、音频和视频?的主要内容,如果未能解决你的问题,请参考以下文章