Unity之PUN实现多人联机射击游戏的优化(Section 3)
目录
💣一、准备工作
💣二、生成弹头脚本的编写
💣三、实现发射和伤害同步
手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图,分别是单机和联机的效果。


添加火箭筒依旧是在原有的基础上更改,我查看火箭筒模型的时候资源里把关于弹头爆炸的脚本也都实现好了。实现了手雷的同步功能后再去写火箭筒就感觉简单多了。
一、准备工作
先在素材中找到火箭筒模型,名字是 Rocket_Launcher_01。

弹头的模型,名称是 Rocket_Launcher_01_Projectile 。把碰撞组件和刚体组件加好,并且把弹头和爆炸特效的标签设置为 “Boom”,用来做伤害检测,和手雷的伤害检测共用一套逻辑。

把火箭筒装到玩家 Player 模型上,我们通过武器组件的激活来实现武器切换的效果。

这里是单个武器组件的切换,如果武器多的话就把所有武器放进一个数组里,通过数组下标进行切换。
二、生成弹头脚本的编写
我把前边的手雷脚本单独拎出来了,handGrenade,然后把手持类武器放进了同一个脚本中用于归类。
public class handGrenade : MonoBehaviour
{//手雷public GameObject handGrenadePrefab;//手雷生成点public Transform handGrenadeTf;void Start(){}public void AttGrenade(){//实例化一个手雷GameObject handGrenadeObj = Instantiate(handGrenadePrefab,handGrenadeTf.transform.position,handGrenadeTf.transform.rotation);handGrenadeObj.GetComponent<Rigidbody>().AddForce(transform.forward * 1,ForceMode.Impulse); //投掷速度 让中心点跟枪口位置可自行调整摄像机的偏移值}
Gun 脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;//枪的脚本
public class Gun : MonoBehaviour
{public int BulletCount = 15;public GameObject bulletPrefab;public GameObject casingPreafab;public Transform bulletTf;public Transform casingTf;//火箭筒弹药数量public int RocketBulletCount = 1;//弹头预设体public GameObject rocketBulletPrefab;//火箭筒发射点public Transform RocketBulletTf;void Start(){}public void Attack(){//实例化一个子弹GameObject bulletObj = Instantiate(bulletPrefab);bulletObj.transform.position = bulletTf.transform.position;bulletObj.GetComponent<Rigidbody>().AddForce(transform.forward * 500, ForceMode.Impulse); //子弹速度 让中心点跟枪口位置可自行调整摄像机的偏移值GameObject casingObj = Instantiate(casingPreafab);casingObj.transform.position = casingTf.transform.position;}public void RocketAttack(){//实例化一个火箭筒弹头GameObject bulletObj = Instantiate(rocketBulletPrefab);bulletObj.transform.position = RocketBulletTf.transform.position;bulletObj.GetComponent<Rigidbody>().AddForce(transform.forward * 300, ForceMode.Impulse); //子弹速度 让中心点跟枪口位置可自行调整摄像机的偏移值}}
三、实现发射和伤害同步
在 PlayerController 脚本中我们要做的事:
- 实现武器的切换
- 生成弹头的同步
- 实现伤害同步
- 换弹药的逻辑(枪换弹药和火箭筒换弹药)
换枪的动画暂时就先用换弹的动画代替了。
下面代码有些和之前是重复的,不过火箭筒都用到这些的
伤害、得分和爆炸范围(爆炸范围是修改爆炸特效的半径)大家可以自己调整,我这里火箭筒和手雷的伤害检测和得分共用同一个逻辑 —— 都是爆炸伤害。
//角色控制器
public class PlayerController : MonoBehaviourPun,IPunObservable
{public Gun gun; //枪的脚本public handGrenade HandGrenade; //手雷的脚本//装载火箭筒、枪的预设体public GameObject RocketObject;public GameObject GunObject;//目标变量用来切换武器,1为枪 0为火箭筒int RocketFlag = 1;void Start(){gun = GetComponentInChildren<Gun>();HandGrenade = GetComponentInChildren<handGrenade>();}void Update(){//Debug.Log(photonView.Owner.NickName);//判断是否是本机玩家 只能操作本机角色if (photonView.IsMine){if (isDie == true){return;}UpdatePosition();UpdateRotation();InputCtl();}else{UpdateLogic();}}//角色操作public void InputCtl(){switch (RocketFlag){case 0://火箭筒if (Input.GetMouseButtonDown(0)){//判断子弹个数if (gun.RocketBulletCount > 0){//如果正在播放填充子弹的动作不能开枪if (ani.GetCurrentAnimatorStateInfo(1).IsName("Reload")){return;}RocketShell.SetActive(false);gun.RocketBulletCount--;Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.RocketBulletCount);//播放开火动画ani.Play("Fire", 1, 0);StopAllCoroutines();StartCoroutine(RocketAttack());}}//火箭筒if (Input.GetKeyDown(KeyCode.R)){//填充子弹AudioSource.PlayClipAtPoint(reloadClip, transform.position); //播放填充子弹的声音ani.Play("Reload");RocketShell.SetActive(true);gun.RocketBulletCount = 1;Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.RocketBulletCount);}break;case 1:if (Input.GetMouseButtonDown(0)){//判断子弹个数if (gun.BulletCount > 0){//如果正在播放填充子弹的动作不能开枪if (ani.GetCurrentAnimatorStateInfo(1).IsName("Reload")){return;}gun.BulletCount--;Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.BulletCount);//播放开火动画ani.Play("Fire", 1, 0);StopAllCoroutines();StartCoroutine(AttackCo());}}if (Input.GetKeyDown(KeyCode.R)){//填充子弹AudioSource.PlayClipAtPoint(reloadClip, transform.position); //播放填充子弹的声音ani.Play("Reload");gun.BulletCount = 15;Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.BulletCount);}break;default:Debug.Log("------------error");break;}//按ESC退出游戏// if (Input.GetKeyDown(KeyCode.Escape))// {// Application.Quit();// }//持续按下按键,查看计分板if (Input.GetKey(KeyCode.Tab)){Game.uiManager.ShowUI<ScoreboardUI>("ScoreboardUI");Game.uiManager.ShowUI<ScoreboardUI>("ScoreboardUI").UpDateScore();}else if(Input.GetKeyUp(KeyCode.Tab)){Game.uiManager.CloseUI("ScoreboardUI");}if (Input.GetKeyDown(KeyCode.Q)){if (boolHandGrenade == false){boolHandGrenade = true;//每隔5秒才可以扔一次Invoke("boolThrowHandGrenade", 5f);//播放投掷手雷动作动画ani.Play("Grenade_Throw");StopAllCoroutines();StartCoroutine(AttHandGrenade());}}//按E切换枪和火箭筒if (Input.GetKeyDown(KeyCode.E)){ani.Play("Reload");if (RocketFlag == 1){RocketObject.SetActive(true);GunObject.SetActive(false);Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.RocketBulletCount);RocketFlag = 0;}else{RocketObject.SetActive(false);GunObject.SetActive(true);Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.BulletCount);RocketFlag = 1;}}}//火箭筒攻击协程IEnumerator RocketAttack(){//延迟0.1秒才发射子弹yield return new WaitForSeconds(0.1f);//播放射击音效AudioSource.PlayClipAtPoint(shootClip, transform.position);photonView.RPC("AttackRocketRpc", RpcTarget.All); //所有玩家执行 AttackRpc 函数}//执行火箭筒同步[PunRPC]public void AttackRocketRpc(){gun.RocketAttack();}//监听发生碰撞: 只监听发生碰撞的一瞬间 —— 火箭筒和手雷共用private void OnCollisionEnter(Collision collision) //参数 collision 就是你碰撞到的物体的碰撞信息{//给地面一个图层"Ground" collision.collider.tag == "Ground" 可以判断物体是否踩在地面上if (collision.collider.tag == "Boom"){GetHit(localPlayer,3,2);}}//同步所有角色受伤: 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);}
}

缺点:火箭筒弹道很偏,可能和人物模型的呼吸晃动有关,小弟暂时无能为力。日后改进
祝大家周五愉快,拜拜┏(^0^)┛
狗剩的成长日记:
Unity之PUN2插件实现多人联机射击游戏_unity pun2-CSDN博客文章浏览阅读1.5k次,点赞21次,收藏29次。周五的下午永远要比周六幸福,周五好啊大家有在认真摸鱼吗。前两天我突发奇想想做联机游戏,就去找教程,肝了一天终于做出来了。先说一下搜寻资料过程中找到的实现游戏联机暂时就记录了这11个,做的这个实例是通过PUN2实现的,先看一下效果:个人感觉这套模型和这个教程泰裤辣,能跟着做完这个游戏Demo也是很开心的,下面依然以博客的形式记录实现这个游戏的过程。_unity pun2https://blog.csdn.net/qq_48512649/article/details/136249522Unity之PUN实现多人联机射击游戏的优化(Section 1)_unity pun2 角色名称-CSDN博客文章浏览阅读1.5k次,点赞24次,收藏29次。关于优化了哪几个小点:点击开始游戏玩家可以输入自己的昵称;进入到房间后玩家对应的昵称也会同步显示到房间列表上;和朋友一起玩的时候他说会卡进房间的模型里建议我加上跳跃功能,我就给加上了,顺便加了一个按住Shift和方向键进行加速跑;同时按住Tab键会显示出计分板,这个计分板是按照射击命中次数来计分的。_unity pun2 角色名称
https://blog.csdn.net/qq_48512649/article/details/136615629Unity之PUN实现多人联机射击游戏的优化(Section 2)_unity photon 多人射击游戏-CSDN博客文章浏览阅读1k次,点赞21次,收藏34次。这几周都给我布置任务了,最近可忙。今天就来兑现诺言:有天我查看这个游戏包的资源,居然发现了手雷和其他很多武器,而且手雷的爆炸脚本是写好的,那就试着加一个手雷功能。看一下效果手雷爆炸的原理呢就像小编之前写的物理系统里面的小实例一样:Unity之物理系统_unity 物理系统-CSDN博客专栏的上一篇角色控制器控制角色移动跳崖,这一篇来说说Unity的物理系统。本篇小编还要带大家做一个碰撞检测效果实例,先放效果图:流星撞击地面产生爆炸效果。_unity 物理系统。_unity photon 多人射击游戏
https://blog.csdn.net/qq_48512649/article/details/137267066

相关文章:
Unity之PUN实现多人联机射击游戏的优化(Section 3)
目录 💣一、准备工作 💣二、生成弹头脚本的编写 💣三、实现发射和伤害同步 手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图,分别是单机和联机的效果。 添加火箭筒依旧是在原有的基础上更改,我查看火箭筒模型…...
PDF锐化
PDF Shaper Ultimate(pdf转图片) 编辑->添加文件->选中一个要处理的pdf 操作->转换->PDF转为图片 ComicEnhancerPro设置(把图片锐化) PDF Shaper Ultimate(图片转pdf) 编辑-添加图片->选中所有锐化处理后的图片 转换->图片转为pdf(会把所有图…...
【python和java】
如何理解java和python的不同,在java中,先有类,类生出对象,对象承载数据。而python是直接数据,没有类的概念 理解 Java 和 Python 在面向对象编程(OOP)方面的不同,关键在于理解它们各…...
C盘满了怎么办,清理工具TreeSize
TreeSize是一款强大的磁盘空间分析工具,它可以帮助用户轻松地找出电脑中占用空间最多的文件和程序,从而让用户进行针对性地删除或卸载。 占用空间很小 下载链接:https://pan.quark.cn/s/bea23ed6b1d3...
【vue】watch 侦听器
watch:可监听值的变化,旧值和新值 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…...
校招生如何准备软件测试、测试开发岗位的面试?
校招生如何准备软件测试、测试开发岗位的面试? 求职建议 大家都很困惑如何学习测试?如何准备测试方面的面试? 我有朋友是做研发的,他认为测试不用准备,直接用开发的简历就行。也有人认为要学习一些测试理论…...
蓝桥杯抱佛脚篇~
文章目录 基础语法输入输出集合(set)排序 基础语法 输入输出 # 输入一个数 nint(input())# 输入两、三个数,例如:1 2 或者 1 2 3 x,y map(int,input().split())# 输入数组 # ——— 1 —— nums[int(i) for i in input().split()] print(n…...
基于springboot的大学城水电管理系统源码数据库
基于springboot的大学城水电管理系统源码数据库 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了大学城水电管理系统的开发全过程。通过分析大学城水电管理系统管理的不足,创建了一个计算机管理大学城水…...
AI大模型探索之路-应用篇2:Langchain框架ModelIO模块—数据交互的秘密武器
目录 前言 一、概述 二、Model 三、Prompt 五、Output Parsers 总结 前言 随着人工智能技术的不断进步,大模型的应用场景越来越广泛。LangChain框架作为一个创新的解决方案,专为处理大型语言模型的输入输出而设计。其中,Model IO&#…...
【SSH】群晖开启ssh访问
群晖开启ssh访问 假设 你需要设置群晖 账号 test-user 开启ssh访问 设置 你的 test-user 为管理员权限 否则你无法通过cmd 面板 连接访问 群晖你需要哪个账号 就使用哪个账号终端 cmd连接 否则需要考虑后续创建 rsa 公密钥文件的 所属权 问题账号密码连接登录终端 ssh -p 端…...
Vue 移动端(H5)项目怎么实现页面缓存(即列表页面进入详情返回后列表页面缓存且还原页面滚动条位置)keep-alive缓存及清除keep-alive缓存
一、需求 产品要求:Vue移动端项目进入列表页,列表页需要刷新,而从详情页返回列表页,列表页则需要缓存并且还原页面滚动条位置 二、实现思路 1、使用Vue中的keep-alive组件,keep-alive提供了路由缓存功能 2、因为我项…...
【MVCC】深入浅出彻底理解MVCC
MVCC概述 MVCC(Multi-Version Concurrency Control)即多版本并发控制。主要是为了提高数据库的并发性能而提供的,采用了不加锁的方式处理读-写并发冲突,确保了任何时刻的读操作都是非阻塞的。只需要很小的开销,就可以…...
【问题解决】ubuntu安装新版vscode报code-insiders相关错误
问题 目前 vscode官网 最新的包为 insiders_1.89.0-1712297812_amd64.deb ,双击或者使用sudo dpkg -i code-insiders_1.89.0-1712297812_amd64.deb安装后报错,执行其他命令也报错。 安装环境:ubuntu18.04 dpkg: 处理软件包 code-insiders (…...
【Python】面向对象(专版提升2)
面向对象 1. 概述1.1面向过程1.2 面向对象 2. 类和对象2.1 语法2.1.1 定义类2.1.2 实例化对象 2.2 实例成员2.2.1 实例变量2.2.2 实例方法2.2.3 跨类调用 3. 三大特征3.1 封装3.1.1 数据角度3.1.2 行为角度3.1.3 案例:信息管理系统3.1.3.1 需求3.1.3.2 分析3.1.3.3 设计 3.2 继…...
Vscode设置滚轮进行字体大小的调节
Vscode设置滚轮进行字体大小的调节 正常的话按 ctrl 或者 ctrl - 进行字体的大小调节 1.打开Vscode,找打设置的图标,在点击设置,或者直接使用快捷键,【ctrl ,】 2. 在搜索框搜索Font Ligatures 3.双击进入settings.json ,找到如…...
【QT入门】Qt自定义控件与样式设计之控件提升与自定义控件
【QT入门】Qt自定义控件与样式设计之控件提升与自定义控件 往期回顾 【QT入门】Qt自定义控件与样式设计之QProgressBar用法及qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QSlider用法及qss-CSDN博客 【QT入门】Qt自定义控件与样式设计之qss的加载方式-CSDN博客 一、最终…...
Spring Validation解决后端表单校验
NotNull:从前台传递过来的参数不能为null,如果为空,会在控制台日志中把message打印出来 Range:范围,最大多少,最小多少 Patten,标注的字段值必须符合定义的正则表达式(按照业务规则࿰…...
Harmony鸿蒙南向驱动开发-UART接口使用
功能简介 UART指异步收发传输器(Universal Asynchronous Receiver/Transmitter),是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 两个UART设备的连接示意图如下,UART与其他模块一…...
【示例】MySQL-事务控制示例:账户转账-savepoint关键字
前言 本文讲述MySQL中的事务,以账户转账为例,体会事务的概念,并讲解事务相关的一个关键字用法:savepoint 示例 数据准备 drop table if exists account;create table account(id int primary key AUTO_INCREMENT comment ID,n…...
STM32使用标准版RT-Thread,移植bsp中的板文件后,想使用I/O设备模型,使用串口3或者串口4收发时,发现串口3或者串口4没反应
STM32移植RT-Thread出现的问题及解决办法 问题原因解决方法 问题 使用标准版RT-Thread,移植bsp中的板文件后,想使用I/O设备模型,使用串口3或者串口4收发时,发现串口3或者串口4没反应。出现问题:程序一直跑在 while (__HAL_UART_…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
