码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Unity之PUN实现多人联机射击游戏的优化(Section 2)


    目录

    🎮一、准备工作

    🎮二、实现手雷投掷动作

    🎮三、手雷投掷同步

    💤3.1 photonView.RPC

    🎮四、同步手雷伤害


    这几周都给我布置任务了,最近可忙。现在终于有机会更新了,也谢谢大家的阅读,我们一起进步。如果前面两篇大家有没有看到的可以在本篇文章末尾点击链接查看,资源包也在博客里有链接。



    今天就来兑现诺言:有天我查看这个游戏包的资源,居然发现了手雷和其他很多武器,而且手雷的爆炸脚本是写好的,那就试着加一个手雷功能。看一下效果

    手雷爆炸的原理呢就像小编之前写的物理系统里面的小实例一样:

    Unity之物理系统_unity 物理系统-CSDN博客文章浏览阅读1.3k次,点赞22次,收藏20次。专栏的上一篇角色控制器控制角色移动跳崖,这一篇来说说Unity的物理系统。本篇小编还要带大家做一个碰撞检测效果实例,先放效果图:流星撞击地面产生爆炸效果。_unity 物理系统https://blog.csdn.net/qq_48512649/article/details/135600857

    手雷扔出去爆炸手雷的预设体会销毁对应的则生成爆炸特效的预设体。给爆炸特效加上碰撞组件,爆炸特效生成的一瞬间就会产生把玩家击飞的效果,随后爆炸特效预设体跟着消失。这个资源里边自带的脚本已经帮我们实现好了。

    放在单击游戏上实现起来很简单,但是对于小编来说最难的是数据同步,没办法既然想实现这个功能就试着去摸索。


    看一下踩过的坑,比如下面的图片,其中一个玩家画面里就会看到一个尸体在动,还会打人!!!!这就是数据同步没有做好,就会很搞笑

    修改之后,就小编目前的测试来说可以实现同步了(在公司只能开小窗口测试doge.jpg)


    一、准备工作

    首先来看资源包中手雷预设体的位置,这里所挂载的组件和数值大家可以进行参考

     这是爆炸特效预设体的位置以及其挂载的组件:

    玩家预设体上有一个手雷生成点,当我们按下投手雷时就设定在这个点生成手雷。缺点是只能朝着这个角度进行投掷。

    二、实现手雷投掷动作

    在前面两期代码的基础上,我们在PlayerController脚本来添加按下Q键实现投掷手雷的功能,这里做了一个设定是每隔5秒可以投一次手雷。

    1. //定义布尔值判断手雷是否可以进行投掷
    2. private bool boolHandGrenade = false;
    3. //角色操作:在判断为本机玩家操作的前提下
    4. public void InputCtl()
    5. {
    6. //按ESC退出游戏
    7. // if (Input.GetKeyDown(KeyCode.Escape))
    8. // {
    9. // Application.Quit();
    10. // }
    11. if (Input.GetKeyDown(KeyCode.Q))
    12. {
    13. if (boolHandGrenade == false)
    14. {
    15. boolHandGrenade = true;
    16. //每隔5秒才可以扔一次
    17. Invoke("boolThrowHandGrenade", 5f);
    18. //播放投掷手雷动作动画
    19. ani.Play("Grenade_Throw");
    20. StopAllCoroutines();
    21. //开启协程同步手雷的生成,在三部分讲
    22. StartCoroutine(AttHandGrenade());
    23. }
    24. }
    25. }
    26. //更改判断手雷是否可以进行投掷的布尔值
    27. void boolThrowHandGrenade()
    28. {
    29. boolHandGrenade = false;
    30. }

    上面这个代码块只实现了玩家投掷手雷时所做的动作,但是要生成手雷要在所有玩家画面上都要进行同步生成,我们接着往下看。

    三、手雷投掷同步

     手雷预设体生成的代码小编写在Gun脚本里了,和子弹生成的逻辑差不多。代码写好后我们按准备工作中的内容把手雷生成点和手雷预设体设置好。

    1. //枪的脚本
    2. public class Gun : MonoBehaviour
    3. {
    4. public int BulletCount = 10;
    5. public GameObject bulletPrefab;
    6. public GameObject casingPreafab;
    7. public Transform bulletTf;
    8. public Transform casingTf;
    9. //手雷
    10. public GameObject handGrenadePrefab;
    11. //手雷生成点
    12. public Transform handGrenadeTf;
    13. void Start()
    14. {
    15. }
    16. public void Attack()
    17. {
    18. //实例化一个子弹
    19. GameObject bulletObj = Instantiate(bulletPrefab);
    20. bulletObj.transform.position = bulletTf.transform.position;
    21. bulletObj.GetComponent().AddForce(transform.forward * 500, ForceMode.Impulse); //子弹速度 让中心点跟枪口位置可自行调整摄像机的偏移值
    22. GameObject casingObj = Instantiate(casingPreafab);
    23. casingObj.transform.position = casingTf.transform.position;
    24. }
    25. public void AttGrenade()
    26. {
    27. //实例化一个手雷
    28. GameObject handGrenadeObj = Instantiate(handGrenadePrefab,handGrenadeTf.transform.position,handGrenadeTf.transform.rotation);
    29. handGrenadeObj.GetComponent().AddForce(transform.forward * 1,ForceMode.Impulse); //投掷速度 让中心点跟枪口位置可自行调整摄像机的偏移值
    30. }
    31. }

    手雷生成的代码写好后我们来设置同步。在之前第二部分中,我们现在来讲

    1. //开启协程同步手雷的生成,在三部分讲
    2. StartCoroutine(AttHandGrenade());
    3. //协程方法实现
    4. IEnumerator AttHandGrenade()
    5. {
    6. yield return new WaitForSeconds(0.5f);
    7. // 3.1 photonView.RPC 中讲解
    8. photonView.RPC("throwHandGrenade", RpcTarget.All); //所有玩家执行 AttackRpc 函数
    9. }
    10. [PunRPC]
    11. public void throwHandGrenade()
    12. {
    13. gun.AttGrenade(); //这里会执行Gun脚本中的AttGrenade()方法
    14. }

    3.1 photonView.RPC

    进入源代码我们来看这一方法:参数有三个(方法名、目标群体、参数)

    这句代码的意思是所标注的目标群体一块执行我们自己写的方法,下图是目前群体的枚举类型:

    第三个参数   params object[] parameters  小编看到它最终是存到一个 Hashtable 类型里,我们现在只用到了前两个参数。


    对应到我们的代码中意思就是当前房间所有玩家同步其中一个人所生成的手雷。 

    四、同步手雷伤害

    依然在PlayerController脚本里,我们给爆炸特效一个Boom的图层标签,用来检测它是否与玩家发生碰撞。

    1. //监听发生碰撞: 只监听发生碰撞的一瞬间
    2. private void OnCollisionEnter(Collision collision) //参数 collision 就是你碰撞到的物体的碰撞信息
    3. {
    4. //给地面一个图层"Ground" collision.collider.tag == "Ground" 可以判断物体是否踩在地面上
    5. if (collision.collider.tag == "Boom")
    6. {
    7. GetHit(localPlayer,3,2);
    8. }
    9. }

    如果发生碰撞了就执行GetHit方法,这里我们给GetHit方法加了参数,因为爆炸和枪击的伤害值和得分是不同设定的,我们通过参数来进行区分。伤害值大家可以根据自己的想法设定。

    上图是枪击执行的GetHit方法。

    1. //同步所有角色受伤: p 本机玩家,addScore 获得的分, AttackHp 不同武器的伤害值不同
    2. public void GetHit(Player p,int addScore,int AttackHp)
    3. {
    4. if (isDie == true)
    5. {
    6. return;
    7. }
    8. switch (AttackHp)
    9. {
    10. case 1:
    11. //同步所有角色受伤:枪伤
    12. photonView.RPC("GetGunHitRPC", RpcTarget.All);
    13. break;
    14. case 2:
    15. //同步所有角色受伤:爆炸伤
    16. photonView.RPC("GetBoomHitRPC", RpcTarget.All);
    17. break;
    18. default:
    19. Debug.Log("------------ERROR");
    20. break;
    21. }
    22. Score += addScore;
    23. p.SetScore(Score);
    24. }
    25. [PunRPC]
    26. public void GetGunHitRPC()
    27. {
    28. CurHp -= 1; //扣血
    29. if (CurHp <= 0)
    30. {
    31. CurHp = 0;
    32. isDie = true;
    33. }
    34. if (photonView.IsMine)
    35. {
    36. Game.uiManager.GetUI("FightUI").UpdateHp(CurHp, MaxHp);
    37. Game.uiManager.GetUI("FightUI").UpdateBlood();
    38. if (CurHp == 0)
    39. {
    40. Invoke("gameOver", 3); //3秒后显示失败界面
    41. }
    42. }
    43. }
    44. [PunRPC]
    45. public void GetBoomHitRPC()
    46. {
    47. CurHp -= 3; //扣血
    48. if (CurHp <= 0)
    49. {
    50. CurHp = 0;
    51. isDie = true;
    52. }
    53. if (photonView.IsMine)
    54. {
    55. Game.uiManager.GetUI("FightUI").UpdateHp(CurHp, MaxHp);
    56. Game.uiManager.GetUI("FightUI").UpdateBlood();
    57. if (CurHp == 0)
    58. {
    59. Invoke("gameOver", 3); //3秒后显示失败界面
    60. }
    61. }
    62. }
    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^)┛

  • 相关阅读:
    Java实现Excel导入导出
    基于内容的个性化推荐算法
    不知道10年老电脑如何重装系统?其实很简单
    基础术语和模式的学习记录
    多线程之四(锁策略+CAS+synchronized)
    英伟达DeepStream学习笔记46——kafka修改默认日志存储路径\ 修改日志分块大小\修改日志自动删除时间
    深度学习——day18 卷积神经网络第四周——人脸识别和神经风格迁移
    RAMday9
    如何通过增强(Enhancement) 的方式给 SAP ABAP 标准程序增添新功能试读版
    游戏测试是一个怎样的行业?
  • 原文地址:https://blog.csdn.net/qq_48512649/article/details/137267066
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号