目录
这几周都给我布置任务了,最近可忙。现在终于有机会更新了,也谢谢大家的阅读,我们一起进步。如果前面两篇大家有没有看到的可以在本篇文章末尾点击链接查看,资源包也在博客里有链接。
今天就来兑现诺言:有天我查看这个游戏包的资源,居然发现了手雷和其他很多武器,而且手雷的爆炸脚本是写好的,那就试着加一个手雷功能。看一下效果
手雷爆炸的原理呢就像小编之前写的物理系统里面的小实例一样:
手雷扔出去爆炸手雷的预设体会销毁对应的则生成爆炸特效的预设体。给爆炸特效加上碰撞组件,爆炸特效生成的一瞬间就会产生把玩家击飞的效果,随后爆炸特效预设体跟着消失。这个资源里边自带的脚本已经帮我们实现好了。
放在单击游戏上实现起来很简单,但是对于小编来说最难的是数据同步,没办法既然想实现这个功能就试着去摸索。
看一下踩过的坑,比如下面的图片,其中一个玩家画面里就会看到一个尸体在动,还会打人!!!!这就是数据同步没有做好,就会很搞笑
修改之后,就小编目前的测试来说可以实现同步了(在公司只能开小窗口测试doge.jpg)
首先来看资源包中手雷预设体的位置,这里所挂载的组件和数值大家可以进行参考
这是爆炸特效预设体的位置以及其挂载的组件:
玩家预设体上有一个手雷生成点,当我们按下投手雷时就设定在这个点生成手雷。缺点是只能朝着这个角度进行投掷。
在前面两期代码的基础上,我们在PlayerController脚本来添加按下Q键实现投掷手雷的功能,这里做了一个设定是每隔5秒可以投一次手雷。
- //定义布尔值判断手雷是否可以进行投掷
- private bool boolHandGrenade = false;
-
-
- //角色操作:在判断为本机玩家操作的前提下
- public void InputCtl()
- {
- //按ESC退出游戏
- // if (Input.GetKeyDown(KeyCode.Escape))
- // {
- // Application.Quit();
- // }
-
- if (Input.GetKeyDown(KeyCode.Q))
- {
- if (boolHandGrenade == false)
- {
- boolHandGrenade = true;
- //每隔5秒才可以扔一次
- Invoke("boolThrowHandGrenade", 5f);
- //播放投掷手雷动作动画
- ani.Play("Grenade_Throw");
-
- StopAllCoroutines();
- //开启协程同步手雷的生成,在三部分讲
- StartCoroutine(AttHandGrenade());
- }
- }
- }
-
- //更改判断手雷是否可以进行投掷的布尔值
- void boolThrowHandGrenade()
- {
- boolHandGrenade = false;
- }
上面这个代码块只实现了玩家投掷手雷时所做的动作,但是要生成手雷要在所有玩家画面上都要进行同步生成,我们接着往下看。
手雷预设体生成的代码小编写在Gun脚本里了,和子弹生成的逻辑差不多。代码写好后我们按准备工作中的内容把手雷生成点和手雷预设体设置好。
- //枪的脚本
- public class Gun : MonoBehaviour
- {
-
- public int BulletCount = 10;
-
- public GameObject bulletPrefab;
- public GameObject casingPreafab;
-
- public Transform bulletTf;
- public Transform casingTf;
-
- //手雷
- public GameObject handGrenadePrefab;
- //手雷生成点
- public Transform handGrenadeTf;
-
- void Start()
- {
-
- }
-
- public void Attack()
- {
- //实例化一个子弹
- GameObject bulletObj = Instantiate(bulletPrefab);
- bulletObj.transform.position = bulletTf.transform.position;
- bulletObj.GetComponent
().AddForce(transform.forward * 500, ForceMode.Impulse); //子弹速度 让中心点跟枪口位置可自行调整摄像机的偏移值 -
- GameObject casingObj = Instantiate(casingPreafab);
- casingObj.transform.position = casingTf.transform.position;
- }
-
- public void AttGrenade()
- {
- //实例化一个手雷
- GameObject handGrenadeObj = Instantiate(handGrenadePrefab,handGrenadeTf.transform.position,handGrenadeTf.transform.rotation);
- handGrenadeObj.GetComponent
().AddForce(transform.forward * 1,ForceMode.Impulse); //投掷速度 让中心点跟枪口位置可自行调整摄像机的偏移值 - }
- }
手雷生成的代码写好后我们来设置同步。在之前第二部分中,我们现在来讲
- //开启协程同步手雷的生成,在三部分讲
- StartCoroutine(AttHandGrenade());
-
- //协程方法实现
- IEnumerator AttHandGrenade()
- {
- yield return new WaitForSeconds(0.5f);
- // 3.1 photonView.RPC 中讲解
- photonView.RPC("throwHandGrenade", RpcTarget.All); //所有玩家执行 AttackRpc 函数
- }
-
-
- [PunRPC]
- public void throwHandGrenade()
- {
- gun.AttGrenade(); //这里会执行Gun脚本中的AttGrenade()方法
- }
进入源代码我们来看这一方法:参数有三个(方法名、目标群体、参数)
这句代码的意思是所标注的目标群体一块执行我们自己写的方法,下图是目前群体的枚举类型:
第三个参数 params object[] parameters 小编看到它最终是存到一个 Hashtable 类型里,我们现在只用到了前两个参数。
对应到我们的代码中意思就是当前房间所有玩家同步其中一个人所生成的手雷。
依然在PlayerController脚本里,我们给爆炸特效一个Boom的图层标签,用来检测它是否与玩家发生碰撞。
- //监听发生碰撞: 只监听发生碰撞的一瞬间
- private void OnCollisionEnter(Collision collision) //参数 collision 就是你碰撞到的物体的碰撞信息
- {
- //给地面一个图层"Ground" collision.collider.tag == "Ground" 可以判断物体是否踩在地面上
- if (collision.collider.tag == "Boom")
- {
- GetHit(localPlayer,3,2);
- }
- }
如果发生碰撞了就执行GetHit方法,这里我们给GetHit方法加了参数,因为爆炸和枪击的伤害值和得分是不同设定的,我们通过参数来进行区分。伤害值大家可以根据自己的想法设定。
上图是枪击执行的GetHit方法。
- //同步所有角色受伤: p 本机玩家,addScore 获得的分, AttackHp 不同武器的伤害值不同
- public void GetHit(Player p,int addScore,int AttackHp)
- {
- if (isDie == true)
- {
- return;
- }
- switch (AttackHp)
- {
- case 1:
- //同步所有角色受伤:枪伤
- photonView.RPC("GetGunHitRPC", RpcTarget.All);
- break;
- case 2:
- //同步所有角色受伤:爆炸伤
- photonView.RPC("GetBoomHitRPC", RpcTarget.All);
- break;
- default:
- Debug.Log("------------ERROR");
- break;
- }
-
- Score += addScore;
- p.SetScore(Score);
- }
-
- [PunRPC]
- public void GetGunHitRPC()
- {
- CurHp -= 1; //扣血
- if (CurHp <= 0)
- {
- CurHp = 0;
- isDie = true;
- }
-
- if (photonView.IsMine)
- {
- Game.uiManager.GetUI
("FightUI").UpdateHp(CurHp, MaxHp); - Game.uiManager.GetUI
("FightUI").UpdateBlood(); -
- if (CurHp == 0)
- {
- Invoke("gameOver", 3); //3秒后显示失败界面
- }
- }
- }
-
- [PunRPC]
- public void GetBoomHitRPC()
- {
- CurHp -= 3; //扣血
- if (CurHp <= 0)
- {
- CurHp = 0;
- isDie = true;
- }
-
- if (photonView.IsMine)
- {
- Game.uiManager.GetUI
("FightUI").UpdateHp(CurHp, MaxHp); - Game.uiManager.GetUI
("FightUI").UpdateBlood(); -
- if (CurHp == 0)
- {
- Invoke("gameOver", 3); //3秒后显示失败界面
- }
- }
- }
GetGunHitRPC 和 GetBoomHitRPC 除了伤害值不同其他逻辑都相同,小编本来想合成一个共用的方法奈何没成功,目前只能shi山堆积了。如果大家有更好的写法小编还要虚心向大家请教。
前面两篇博客的链接:
Unity之PUN2插件实现多人联机射击游戏_unity pun2-CSDN博客文章浏览阅读1.3k次,点赞20次,收藏24次。周五的下午永远要比周六幸福,周五好啊大家有在认真摸鱼吗。前两天我突发奇想想做联机游戏,就去找教程,肝了一天终于做出来了。先说一下搜寻资料过程中找到的实现游戏联机暂时就记录了这11个,做的这个实例是通过PUN2实现的,先看一下效果:个人感觉这套模型和这个教程泰裤辣,能跟着做完这个游戏Demo也是很开心的,下面依然以博客的形式记录实现这个游戏的过程。_unity pun2https://blog.csdn.net/qq_48512649/article/details/136249522Unity之PUN实现多人联机射击游戏的优化(Section 1)_unity pun2 角色名称-CSDN博客文章浏览阅读1.5k次,点赞23次,收藏28次。关于优化了哪几个小点:点击开始游戏玩家可以输入自己的昵称;进入到房间后玩家对应的昵称也会同步显示到房间列表上;和朋友一起玩的时候他说会卡进房间的模型里建议我加上跳跃功能,我就给加上了,顺便加了一个按住Shift和方向键进行加速跑;同时按住Tab键会显示出计分板,这个计分板是按照射击命中次数来计分的。_unity pun2 角色名称https://blog.csdn.net/qq_48512649/article/details/136615629今天先到这里,拜拜┏(^0^)┛