关于Tank的炮弹射击方式,我们要如何做到能在多人连线时,可以同步显示或是同步元件的效果呢? 此篇文章中会以二种方式来实作,一种是用前篇所介绍的PhotonNetwork。实例化,另一种会用到Photon里面的PunRPC(远程过程调用) “称为过程调用”来实作。 🤖

上面的GIF动画就是我们的专案执行时的炮弹射击实况!
那现在先来看看第一种做法吧〜
- 额外生活–林赛·查尔顿–中
- 如何建模角色 面向初学者的3D低多边形游戏建模[教程]
- 为Unity 3D创建数据管理器
- Devil May Cry 4向我许诺了更广阔的世界
- 在Game Crafter上制作自己的定制塑料游戏零件
方法A:PhotonNetowrk.Instantiate
在前二篇教学中,有提到如果物件必须要在不同的客户端中显示相同的位置/旋转/大小等的资讯,会须要用到PhotonView和PhotonTransformView; 所以我们先来看一下原范例中的炮弹设定。 可以在Assets→Complete→Prefabs→CompleteShell的路径看到如下的画面:

将原始范例的CompleteShell复制副本,并加上Photon视图与Photon Transformer视图后,放到我们的专案TanksPUN→ 资源底下,新的炮弹Prefab的设置画面会像下面的图示。

这样我们就可以在TankShooting.cs中的Fire()中,把实例化改成PhotonNetwork的方式来产生新的可网路同步的GameObject了〜
私人虚空之火 ()
{
m_Fired = true;
GameObject shellInstance = PhotonNetwork.Instantiate (
“ CompleteShell”,
m_FireTransform.position,
m_FireTransform.rotation,
0);
刚体正文= shellInstance.GetComponent ();
body.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
m_CurrentLaunchForce = m_MinLaunchForce;
}
如此,只要在游戏中我们点击炮弹发射键(Enter或Spacebar),在其他同在游戏室内的玩家都可以在画面上看到有个炮弹被发射(同步显示 )出来〜👾

有注意到网路同步显示的炮弹有什么不一样吗? 呵呵,因为我们只有用到Photon Transform View的Position + Rotation,所以它就只会同步有移动的位置资讯。 🐶
接下来看看另外一种实作方式吧〜
方法B:[PunRPC]
远端程序调用的这个方式,会在程式中使用[PunRPC]这个标签,让PUN知道哪一个部份的程序是可以被远端(Remote Client)叫用的。 同时,要调用有被[PunRPC]注记的程序,得用photonView.RPC来调用,所以也必须要更改一下TankShooting的Bass类为Photon.MonoBehaviour ,用这个由Photon提供的MonoBehaviour不用担心它里面会其他的什么事,最主要也只是让原本的calss可以用到photonView所提供的附加功能。
现在,整理一下目前我们使用这个方式所要注意的地方:
- 类别要继承Photon.MonoBehaviour
- 使用[PunRPC]标签,意思是PUN远程过程调用
- 使用photonView.RPC来调用有[PunRPC]标签的程序
公共课程TankShooting: Photon.MonoBehaviour
{
...
私人虚空之火 ()
{
m_Fired = true;
Rigidbody shellInstance =作为Rigidbody 实例化 (m_Shell,m_FireTransform.position,m_FireTransform.rotation);
photonView.RPC (“ FireOther”,PhotonTargets.Others,m_FireTransform.position);
shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
m_CurrentLaunchForce = m_MinLaunchForce;
}
[PunRPC]
void FireOther (Vector3 pos)
{
m_Fired = true;
刚体shellInstance =
实例化(m_Shell,pos,m_FireTransform.rotation)为刚体;
shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
m_CurrentLaunchForce = m_MinLaunchForce;
}
...
}
如此,只要在游戏中我们点击炮弹发射键(Enter或Spacebar),在其他同在游戏室内的玩家画面:就会有炮弹发射出来! 重要的是,生出来的炮弹是个在每个玩家游戏空间中的实体 , 而非网路同步显示的唷〜😬👻👏🏻

方法A和B的异同与使用时机
各位朋友,有发现这上面的二个方法产生的炮弹有什么不一样吗? 在游戏中会有什么影响吗?
方法A用的是同步位置资讯,所以它的网路上的物件是Clone出来的,只是位置会持续的被PUN所同步,就看原本的主体是在其中Client所产生出来的,那么它就有主要的变动权; 而其他其他资讯就得要自行重新编写对应的事件,像是要不要显示,是否已爆炸,是否要计分之类的。
方法B用的是“远端程序调用”,所以除了本身之外,客户中产生了一个真的炮弹,还叫别的客户同时处于相同的位置,产生一个同样速度与方向的炮弹; 所以产生出来的直接是一个实体,不会跟其他网路上的Client的炮弹做同步。 而因为少了网路不断同步的资讯传送,它的执行效果会快很多。
[PunRPC]的用法在这边只是简单的来生成炮弹之用,但它还有很多地方可以运用,像是传消息,取得某客户的物品,交换资料,对所有的客户做某件事等等,它的用处可大的很唷!
接下来,还有更多的问题可以想想:像是Tank的生命值/伤害/死亡与重生,实作上我们应该要怎么弄成网路同步呢? 呵呵,游戏设计方式百百种,就看我们怎么好好的运用这个方便的简单的入门应用,进阶的部分就日后再讨论喔〜🤖👻💕👾🎮
在设计游戏的路上,多多的互相交流喔〜😬