首先我们要搞懂,我们要同步什么?
Object Synchronization,即对象同步。Object Synchronization适合频繁同步的属性。 使用 PUN,我们可以很容易地使某些游戏对象“网络感知”。
该组件的信息同步,通过 PhotonView 组件完成。
Owner:物体的拥有者
-0Fixed:固定的 -0Takeover:可被接管的 -0Request:可被请求接管
ViewID:运行后显示当前物体是拥有者的第几个物体。最多是999。若超过999,则只是后三位
Observeoption:观察设置,添加上同步组件后,该值默认是UnreliableOnChange(在每次改变时通过“不可靠”传输同步)
ObservedComponents:同步组件。我们可以往里面添加该物体的Transform、Animator等,同步这些选项。 添加上这些属性之后,会自动再添加属性。 添加Transform会自动添加PhotoTransformView,勾选需要同步的选项即可 添加Animator会自动添加PhotonAnimatorView中:
Animator中Trigger属性要放在栈的最后,否则会可能没被执行(不是很理解怎样放在栈最后。。
场景中有好几个人控制的角色,都挂有某相同脚本,按下按键,如不判断,这些角色不知道谁该执行当前用户输入的命令。因此要进行判断:
//需继承MonoBehaviourPun
bool isMine = photonView.IsMine;
摄像机设置
在网络中,要先判断摄像机是否属于当前用户,再决定是否跟随。因此PlayerManager增加代码如下。并取消CameraWork的FollowOnStart。
我们之前已经做完了发射激光的判断。现在我们已实现了本机的操作,后面我们要将本机的状态同步到互联网上,同步其他电脑中自己人物的状态。
void Start()
{
Skode_CameraWork _cameraWork = GetComponent<Skode_CameraWork>();
if (_cameraWork != null && photonView.IsMine)
{
_cameraWork.OnStartFollowing();
}
}
false为离线。使用教程:传送门
bool isConnected = PhotonNetwork.IsConnected;
目标:
流程:
a、继承并实现
要同步的脚本继承接口 IPunObservable 并实现。
实现OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)方法,用它接收发送数据。
注:若不继承不会报错,但代码不会运行。
b、书写方式
脚本判断自己是发送方还是接收方
写法有规范,要怎样发,怎样接收。
c、Inspector面板配置
要把要同步的脚本(发送信息、接收信息的脚本)赋值进同步组件ObservedComponents
PlayerManager 最新代码:
using UnityEngine;
using Photon.Pun;
public class PlayerManager : MonoBehaviourPunCallbacks, IPunObservable
{
#region Parameters
public GameObject beams;
public float Health = 1f;
//当用户开火时,为True
bool IsFiring;
#endregion
#region Mono CallBacks
void Awake()
{
beams.SetActive(false);
}
void Start()
{
Skode_CameraWork _cameraWork = GetComponent<Skode_CameraWork>();
if (_cameraWork != null && photonView.IsMine)
{
_cameraWork.OnStartFollowing();
}
}
void Update()
{
if (Health <= 0f)
GameManager.ins.Skode_LeaveRoom();
if (PhotonNetwork.IsConnected == true && photonView.IsMine)
ProcessInputs();
if (IsFiring != beams.activeSelf)
beams.SetActive(IsFiring);
}
#endregion
#region IPunObservable CallBacks
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if (stream.IsWriting)
{
// 我们拥有这个角色:把我们的数据发送给其他人
stream.SendNext(IsFiring);
stream.SendNext(Health);
}
else
{
// 网络角色,接收数据
IsFiring = (bool)stream.ReceiveNext();
Health = (float)stream.ReceiveNext();
}
}
#endregion
#region Private Methods
void ProcessInputs()
{
//鼠标左键
if (Input.GetButtonDown("Fire1"))
IsFiring = true;
if (Input.GetButtonUp("Fire1"))
IsFiring = false;
}
void OnTriggerEnter(Collider other)
{
if (!photonView.IsMine && !other.CompareTag("beam"))
return;
Health -= 0.1f;
}
void OnTriggerStay(Collider other)
{
if (!photonView.IsMine && !other.CompareTag("beam"))
return;
//乘以增量时间,防止因为帧率FPS不同,扣血不同(举例:不乘,每帧执行一次扣血,卡的人比流畅的人扣血少)
Health -= 0.1f * Time.deltaTime;
}
#endregion
}
大家还有什么问题,欢迎在下方留言!