Unity之PUN实现多人联机射击游戏的优化

目录

🎮一、 跳跃,加速跑

🎮二、玩家自定义输入昵称

🍅2.1 给昵称赋值

🍅2.2 实现 

🎮三、玩家昵称同步到房间列表

🍅3.1 获取全部玩家 

🍅3.2 自定义Player中的字段

🍅3.3 实现

🎮四、计分板功能的实现

🍅4.1 设置玩家分数

🍅4.2 实现


前几天对之前肝出的射击游戏Demo进行了小小的优化,顺便在了解一下PUN插件。怎么实现的这个Demo可以来看一下这篇文章:

Unity之PUN2插件实现多人联机射击游戏-CSDN博客文章浏览阅读1.1k次,点赞19次,收藏19次。周五的下午永远要比周六幸福,周五好啊大家有在认真摸鱼吗。前两天我突发奇想想做联机游戏,就去找教程,肝了一天终于做出来了。先说一下搜寻资料过程中找到的实现游戏联机暂时就记录了这11个,做的这个实例是通过PUN2实现的,先看一下效果:个人感觉这套模型和这个教程泰裤辣,能跟着做完这个游戏Demo也是很开心的,下面依然以博客的形式记录实现这个游戏的过程。https://blog.csdn.net/qq_48512649/article/details/136249522来看一下优化完的效果。

关于优化了哪几个小点:

  • 点击开始游戏玩家可以输入自己的昵称;进入到房间后玩家对应的昵称也会同步显示到房间列表上;
  • 和朋友一起玩的时候他说会卡进房间的模型里建议我加上跳跃功能,我就给加上了,顺便加了一个按住Shift和方向键进行加速跑;
  • 同时按住Tab键会显示出计分板。虽然弹道很飘,但是命中伤害是按照准星射线来处理的,这个计分板也是按照射击命中次数来计分的。

下面来记录一下这几点优化是怎么实现的

一、 跳跃,加速跑

相信对于Unity入门的人来说这两点太简单了,废话不多说直接上代码。在PlayerController这个脚本中

    public float MoveSpeed = 3f;  //只按方向键速度为3/// <summary>/// 跳跃/// </summary>public float jumpHeight = 0;//判断是否为跳跃状态private bool boolJump = false;void Update(){//Debug.Log(photonView.Owner.NickName);//判断是否是本机玩家  只能操作本机角色if (photonView.IsMine){if (isDie == true){return;}//在Update函数中如果判断为本机操控的玩家就执行更新位置的方法UpdatePosition();UpdateRotation();InputCtl();}else{UpdateLogic();}}void FixedUpdate(){body.velocity = new Vector3(dir.x, body.velocity.y, dir.z) + Vector3.up * jumpHeight;jumpHeight = 0f;//初始化跳跃高度}//更新位置public void UpdatePosition(){H = Input.GetAxisRaw("Horizontal");V = Input.GetAxisRaw("Vertical");dir = camTf.forward * V + camTf.right * H;body.MovePosition(transform.position + dir * Time.deltaTime * MoveSpeed);//当按下空格键进行跳跃if (Input.GetKeyDown(KeyCode.Space)){if (boolJump == false){boolJump = true;//设定一个跳跃时间间隔,不然就能一直往上跳了Invoke("something", 1.0f);//执行跳跃方法Jump();}}//加速跑  当同时按住Shift 和 方向键if (Input.GetKey(KeyCode.LeftShift) && (dir.x != 0 || dir.y != 0 || dir.z != 0)){body.MovePosition(transform.position + dir * Time.deltaTime * 10);}//当抬起 Shift 键else if (Input.GetKeyUp(KeyCode.LeftShift)){body.MovePosition(transform.position + dir * Time.deltaTime * MoveSpeed);}}void something() {boolJump = false;}//跳跃方法void Jump(){jumpHeight = 5f;}

二、玩家自定义输入昵称

2.1 给昵称赋值

首先说一下在PUN插件中给玩家昵称赋值的代码,赋好值之后我们只要进行获取就可以了

//playerNameInput.text —— 玩家手动输入的名字
PhotonNetwork.NickName = playerNameInput.text; 

2.2 实现 

UI方面小编就比较省事了,输入昵称和输入房间号用的同一个UI界面。在登录UI的LoginUI脚本中,点击开始游戏按钮我们不让它直接进行连接,先让它跳转到输入昵称的UI界面中。

//登录界面
public class LoginUI : MonoBehaviour //,IConnectionCallbacks
{// Start is called before the first frame updatevoid Start(){transform.Find("startBtn").GetComponent<Button>().onClick.AddListener(onStartBtn);transform.Find("quitBtn").GetComponent<Button>().onClick.AddListener(onQuitBtn);}public void onStartBtn(){//弹出输入玩家昵称的UI界面 CreatePlayerUIGame.uiManager.ShowUI<CreatePlayerUI>("CreatePlayerUI");}public void onQuitBtn(){Application.Quit();}}

 CreatePlayerUI脚本中进行连接并通过PhotonNetwork.NickName给玩家昵称赋值

using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;public class CreatePlayerUI : MonoBehaviour,IConnectionCallbacks
{private InputField playerNameInput;  //玩家名称void Start(){transform.Find("bg/title/closeBtn").GetComponent<Button>().onClick.AddListener(onCloseBtn);transform.Find("bg/okBtn").GetComponent<Button>().onClick.AddListener(onStartBtn);playerNameInput = transform.Find("bg/InputField").GetComponent<InputField>();//先随机一个玩家名称playerNameInput.text = "Player_" + Random.Range(1, 9999); }public void onStartBtn(){Game.uiManager.ShowUI<MaskUI>("MaskUI").ShowMsg("正在连接服务器...");//连接pun2服务器PhotonNetwork.ConnectUsingSettings();   //成功后会执行OnConnectedToMaster函数}//关闭按钮public void onCloseBtn(){Game.uiManager.CloseUI(gameObject.name);}//OnEnable()每次激活组件都会调用一次private void OnEnable(){PhotonNetwork.AddCallbackTarget(this);  //注册pun2事件}//OnDisable()每次关闭组件都会调用一次 与 OnEnable() 相对private void OnDisable(){PhotonNetwork.RemoveCallbackTarget(this);  //注销pun2事件}//连接成功后执行的函数public void OnConnectedToMaster(){//关闭所有界面Game.uiManager.CloseAllUI();Debug.Log("连接成功");//显示大厅界面Game.uiManager.ShowUI<LobbyUI>("LobbyUI");//执行昵称赋值操作PhotonNetwork.NickName = playerNameInput.text;}//断开服务器执行的函数public void OnDisconnected(DisconnectCause cause){Game.uiManager.CloseUI("MaskUI");}public void OnRegionListReceived(RegionHandler regionHandler){}public void OnCustomAuthenticationResponse(Dictionary<string, object> data){}public void OnCustomAuthenticationFailed(string debugMessage){}public void OnConnected(){}
}

三、玩家昵称同步到房间列表



3.1 获取全部玩家 

 PUN插件中从服务器获取房间里的全部玩家:

//从服务器遍历房间里的所有玩家项
for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++)
{Player p = PhotonNetwork.PlayerList[i];//打印出玩家昵称,看看我们赋没赋值成功Debug.Log("NickName:" + p.NickName);
}

PUN插件的Player类中,NickName(玩家昵称)和ActorNumber(玩家编号)字段是Player类源码中定义的字段,如果我们开发者需要自定义字段可以通过这样来自定义:Demo中玩家是否准备就是用下面的方式来定义的

3.2 自定义Player中的字段

同步自定义字段:

using ExitGames.Client.Photon;
Hashtable props = new Hashtable() { { "IsReady", true } };
PhotonNetwork.LocalPlayer.SetCustomProperties(props);

 获取自定义字段:

foreach (Player p in PhotonNetwork.PlayerList)
{print(p.NickName);object isPlayerReady;if (p.CustomProperties.TryGetValue("IsReady", out IsReady)){print((bool)IsReady ? "当前玩家已准备好" : "当前玩家未准备好");}
}//获取所有自定义字段
Debug.Log(玩家Player.CustomProperties.ToStringFull());

 3.3 实现

  1. 获取房间内所有的玩家信息包括昵称和准备状态
  2. 将昵称和准备状态显示到UI界面中

RoomUI脚本中,先获取房间内的所有玩家,对应的每一个玩家就会生成一个新的RoomItem

我们给房间列表成员RoomItem中添一个玩家昵称的字段,用来获取玩家进入游戏输入的昵称并展示在UI界面中。 

public int owerId;  //玩家编号
public bool IsReady = false; //是否准备
public string playerName; //玩家名称

 RoomUI脚本:

using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;public class RoomUI : MonoBehaviour,IInRoomCallbacks
{Transform startTf; Transform contentTf;GameObject roomPrefab;public List<RoomItem> roomList;private void Awake(){roomList = new List<RoomItem>();contentTf = transform.Find("bg/Content");//房间列表玩家成员roomPrefab = transform.Find("bg/roomItem").gameObject;transform.Find("bg/title/closeBtn").GetComponent<Button>().onClick.AddListener(onCloseBtn);startTf = transform.Find("bg/startBtn");startTf.GetComponent<Button>().onClick.AddListener(onStartBtn);PhotonNetwork.AutomaticallySyncScene = true; //执行PhotonNetwork.LoadLevel加载场景的时候 其他玩家也跳转相同的场景}void Start(){//从服务器获取房间里的玩家项for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++){Player p = PhotonNetwork.PlayerList[i];Debug.Log("NickName:" + p.NickName);//获取房间中的玩家后,每一个玩家生成对应的一个ItemCreateRoomItem(p);}}private void OnEnable(){PhotonNetwork.AddCallbackTarget(this);}private void OnDisable(){PhotonNetwork.RemoveCallbackTarget(this);}//生成玩家public void CreateRoomItem(Player p){GameObject obj = Instantiate(roomPrefab, contentTf);obj.SetActive(true);RoomItem item = obj.AddComponent<RoomItem>();item.owerId = p.ActorNumber;  //玩家编号item.playerName = p.NickName; //玩家昵称item.playerNameText(item.playerName);   //让玩家昵称显示到UI界面中roomList.Add(item);object val;if (p.CustomProperties.TryGetValue("IsReady", out val)){item.IsReady = (bool)val;}}//删除离开房间的玩家public void DeleteRoomItem(Player p){RoomItem item = roomList.Find((RoomItem _item) => { return p.ActorNumber == _item.owerId; });if (item != null){Destroy(item.gameObject);roomList.Remove(item);}}//关闭void onCloseBtn(){//断开连接PhotonNetwork.Disconnect();Game.uiManager.CloseUI(gameObject.name);Game.uiManager.ShowUI<LoginUI>("LoginUI");}//开始游戏void onStartBtn(){//加载场景 让房间里的玩家也加载场景PhotonNetwork.LoadLevel("game");}//新玩家进入房间public void OnPlayerEnteredRoom(Player newPlayer){CreateRoomItem(newPlayer);}//房间里的其他玩家离开房间public void OnPlayerLeftRoom(Player otherPlayer){DeleteRoomItem(otherPlayer);}public void OnRoomPropertiesUpdate(ExitGames.Client.Photon.Hashtable propertiesThatChanged){}//玩家自定义参数更新回调public void OnPlayerPropertiesUpdate(Player targetPlayer, ExitGames.Client.Photon.Hashtable changedProps){RoomItem item = roomList.Find((_item) => { return _item.owerId == targetPlayer.ActorNumber;});if (item != null){item.IsReady = (bool)changedProps["IsReady"];item.ChangeReady(item.IsReady);}//如果是主机玩家判断所有玩家的准备状态if (PhotonNetwork.IsMasterClient){bool isAllReady = true;for (int i = 0; i < roomList.Count; i++){if (roomList[i].IsReady == false){isAllReady = false;break;}}startTf.gameObject.SetActive(isAllReady); //开始按钮是否显示}}public void OnMasterClientSwitched(Player newMasterClient){}
}

RoomItem脚本:

using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;public class RoomItem : MonoBehaviour
{public int owerId;  //玩家编号public bool IsReady = false; //是否准备public string playerName; //玩家名称void Start(){if (owerId == PhotonNetwork.LocalPlayer.ActorNumber){transform.Find("Button").GetComponent<Button>().onClick.AddListener(OnReadyBtn);}else{transform.Find("Button").GetComponent<Image>().color = Color.black;}ChangeReady(IsReady);}public void OnReadyBtn(){IsReady = !IsReady;ExitGames.Client.Photon.Hashtable table = new ExitGames.Client.Photon.Hashtable();table.Add("IsReady", IsReady);PhotonNetwork.LocalPlayer.SetCustomProperties(table); //设置自定义参数ChangeReady(IsReady);}public void ChangeReady(bool isReady){transform.Find("Button/Text").GetComponent<Text>().text = isReady == true ? "已准备" : "未准备";}public void playerNameText(string playerName){transform.Find("Name").GetComponent<Text>().text = playerName;}
}

四、计分板功能的实现

4.1 设置玩家分数

//设置玩家分数 
PhotonNetwork.LocalPlayer.SetScore(0);

PUN中有自带的设置玩家分数功能,我们来看一下源码:SetScoreAddScoreGetScore

通过方法的命名我们就知道它们分别是设置分数、增加分数、获取分数, 不过小编这里只用了设置和获取(*/ω\*),分数更新后把原有的重新设置覆盖掉了。

知道了原理我们来实现计分板功能。

4.2 实现

首先计分板的UI我还是用的房间界面的UI改一下。

先来理一下思路  —— 

  1. 当识别为本机玩家操作后,按住Tab键弹出该界面,松开关掉界面
  2. 计分板要获取房间内所有玩家信息:昵称、分数
  3. 当本机玩家射击击中其他玩家后,本机玩家分数自增
  4. 玩家分数更新后再次按下Tab键时要更新UI中的分数
  5. 当游戏房间中有玩家离开对应计分板也会删掉对应的玩家信息

PlayerController中 

   private int Score = 0;  //定义分数变量  ——  重点!!!!void Update(){//Debug.Log(photonView.Owner.NickName);//判断是否是本机玩家  只能操作本机角色  ——  重点!!!!if (photonView.IsMine){if (isDie == true){return;}UpdatePosition();UpdateRotation();//判断为本机玩家后执行按键操作方法  ——  重点!!!!InputCtl();}else{UpdateLogic();}}//角色操作public void InputCtl(){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.Escape)){Application.Quit();}//持续按下按键,查看计分板if (Input.GetKey(KeyCode.Tab)){//打开计分板界面  ——  重点!!!!Game.uiManager.ShowUI<ScoreboardUI>("ScoreboardUI");//执行更新分数方法 ——  重点!!!!Game.uiManager.ShowUI<ScoreboardUI>("ScoreboardUI").UpDateScore(); // foreach (Player p in PhotonNetwork.PlayerList)// {//     Debug.Log("NickName:" + p.NickName);//     Debug.Log("GetScore:" + p.GetScore());// }}//当Tab键抬起else if(Input.GetKeyUp(KeyCode.Tab)){//关闭计分板界面  ——  重点!!!!Game.uiManager.CloseUI("ScoreboardUI");}if (Input.GetKeyDown(KeyCode.Q)){ani.Play("Grenade_Throw");}if (Input.GetKeyDown(KeyCode.R)){//填充子弹AudioSource.PlayClipAtPoint(reloadClip, transform.position); //播放填充子弹的声音ani.Play("Reload");gun.BulletCount = 10;Game.uiManager.GetUI<FightUI>("FightUI").UpdateBulletCount(gun.BulletCount);}}//攻击协同程序IEnumerator AttackCo(){//延迟0.1秒才发射子弹yield return new WaitForSeconds(0.1f);//播放射击音效AudioSource.PlayClipAtPoint(shootClip, transform.position);//获取本机玩家  ——  重点!!!!Player p = PhotonNetwork.LocalPlayer;//射线检测 鼠标中心点发送射线Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width * 0.5f, Screen.height * 0.5f,Input.mousePosition.z));//射线可以改成在枪口位置为起始点 发送,避免射线射到自身RaycastHit hit;if (Physics.Raycast(ray, out hit, 10000, LayerMask.GetMask("Player"))){Debug.Log("射到角色");//当本机玩家射中其他玩家时,把获取的本机玩家作为参数传递到GetHit方法中  ——  重点!!!!hit.transform.GetComponent<PlayerController>().GetHit(p);}photonView.RPC("AttackRpc", RpcTarget.All);  //所有玩家执行 AttackRpc 函数}[PunRPC]public void AttackRpc(){gun.Attack();}//同步所有角色受伤  p  ——  代表本机玩家public void GetHit(Player p)  {if (isDie == true){return;}//同步所有角色受伤photonView.RPC("GetHitRPC", RpcTarget.All);//本机玩家得分自增并同步给服务器  ——  重点!!!!Score += 1;p.SetScore(Score);}

 在ScoreboardUI中,和RoomUI的脚本逻辑差不多

using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Pun.UtilityScripts;
using Photon.Realtime;
using UnityEngine.UI;public class ScoreboardUI : MonoBehaviour
{Transform startTf; Transform contentTf;GameObject roomPrefab;public List<ScoreItem> roomList;// Start is called before the first frame updatevoid Awake(){roomList = new List<ScoreItem>();contentTf = transform.Find("bg/Content");//房间列表玩家成员roomPrefab = transform.Find("bg/roomItem").gameObject;}void Start(){//从服务器获取房间里的玩家项for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++){Player p = PhotonNetwork.PlayerList[i];CreateRoomItem(p);}}//生成玩家public void CreateRoomItem(Player p){GameObject obj = Instantiate(roomPrefab, contentTf);obj.SetActive(true);ScoreItem item = obj.AddComponent<ScoreItem>();item.owerId = p.ActorNumber; item.playerName = p.NickName;item.playerNameText(item.playerName);item.Score = p.GetScore();item.playerScoreText(item.Score);roomList.Add(item);}//执行更新房间内玩家分数的操作  ——  重点!!!!public void UpDateScore(){for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++){Player p = PhotonNetwork.PlayerList[i];ScoreItem item = roomList.Find((ScoreItem _item) => { return p.ActorNumber == _item.owerId; });if (item != null){item.playerName = p.NickName;item.playerNameText(item.playerName);item.Score = p.GetScore();item.playerScoreText(item.Score);Debug.Log("NickName:" + p.NickName + "GetScore:" + p.GetScore());Debug.Log("::::::::::::::::::::::::::::::::::::::::::::::::::");}}}//删除离开房间的玩家public void DeleteRoomItem(Player p){ScoreItem item = roomList.Find((ScoreItem _item) => { return p.ActorNumber == _item.owerId; });if (item != null){Destroy(item.gameObject);roomList.Remove(item);}}//房间里的其他玩家离开房间public void OnPlayerLeftRoom(Player otherPlayer){DeleteRoomItem(otherPlayer);}private void OnEnable(){PhotonNetwork.AddCallbackTarget(this);}private void OnDisable(){PhotonNetwork.RemoveCallbackTarget(this);}
}

ScoreItem的脚本用来把玩家信息和分数显示到计分板上

using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Pun.UtilityScripts;
using Photon.Realtime;public class ScoreItem : MonoBehaviour
{public int owerId;  //玩家编号public int Score; //玩家分数public string playerName; //玩家名称public void playerNameText(string name){transform.Find("Name").GetComponent<Text>().text = name; //PhotonNetwork.LocalPlayer.NickName;}public void playerScoreText(int score){transform.Find("Score").GetComponent<Text>().text =  score.ToString();//PhotonNetwork.LocalPlayer.GetScore().ToString();}
}

 完成任务,真的很喜欢这个Demo,以后有时间还会继续优化的。今天先到这里,拜拜┏(^0^)┛

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/744537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

圈内大佬呕心之作,一年后斩获腾讯T3,这份Java学习笔记有多厉害

说这句话的人其实有一些误解&#xff0c;误解就在于&#xff0c;安逸的生活并不等于不需要奋斗&#xff0c;这要看你的家底。 某聪如果说要选择安逸的生活&#xff0c;他可以很安逸&#xff0c;因为他有了安逸的资本&#xff0c;而大部分的你&#xff0c;并没有这个资本&#…

SQL中的distinct的使用方法

1. distinct含义与使用方法 distinct用来查询不重复记录的条数,即用distinct来返回不重复字段的条数&#xff08;count(distinct id)&#xff09;,其原因是distinct只能返回他的目标字段&#xff0c;而无法返回其他字段。 注意事项 distinct 【查询字段】&#xff0c;必须放…

压缩json字符串

GZIPOutputStream 需要关闭&#xff0c;而 ByteArrayOutputStream 不需要关闭。具体原因如下&#xff1a; GZIPOutputStream&#xff1a;GZIPOutputStream是一种过滤流&#xff0c;它提供了将数据压缩为GZIP格式的功能。当使用此类的实例写入数据时&#xff0c;它会对数据进行压…

阿里云数据湖存储加速套件JindoData

计算存储分离已经成为云计算的一种发展趋势。在计算存储分离之前&#xff0c;普遍采用的是传统的计算存储相互融合的架构&#xff0c;但是这种架构存在一定的问题&#xff0c;比如在集群扩容的时候会面临计算能力和存储能力相互不匹配的问题。用户在某些情况下只需要扩容计算能…

[MYSQL数据库]- 索引

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、认识索…

力扣--课程表--bfs+dfs

整体思路&#xff1a; 这是一道拓扑序列的题目&#xff0c;我们将边的方向定义成从先修课指向后修课的方向&#xff0c;借一下官方的题解图片&#xff0c;我们需要判断的是形成的这个图结构是否存在环&#xff0c;如果存在环&#xff0c;那么代表不能完成所有课程的学习。 bfs思…

强推游戏爱好者!雾锁王国联机服务器部署教程

继《幻兽帕鲁》游戏爆火之后&#xff0c;与它同类型的《雾锁王国》也是强力刷屏&#xff0c;不分伯仲&#xff0c;在 Steam 上的评分一直稳定在“特别好评”&#xff0c;让小伙伴们很“上头”。就在两者游戏玩家反响爆火的同时&#xff0c;官方服务器人数爆满&#xff0c;卡顿频…

JavaScript进阶2之执行上下文、作用域链、函数创建、函数激活、checkScope的执行过程、闭包、this

JavaScript进阶 执行上下文执行上下文中的属性变量对象全局上下文的变量对象函数上下文执行过程进入执行上下文代码执行思考题 作用域链函数创建函数激活checkScope的执行过程总结 闭包分析闭包 this 执行上下文 执行上下文中的属性 每一个执行上下文都有三个核心属性 变量对…

【趣味项目】一键生成LICENSE

【趣味项目】一键生成LICENSE 项目地址&#xff1a;GitHub(最新版本) | GitCode(旧版本) 项目介绍 一款用于自动生成开源项目协议的工具&#xff0c;可以通过 npm 进行安装后在命令行使用&#xff0c;非常方便 使用方式 npm install xxhls/get-license -gget-license --l…

python的函数与类的定义

目录 1.函数 1.函数的定义 2.输入参数与输出参数的类型 3.输入和输出多个参数 1.普通参数 2.含有任意数量的参数 3.关键字参数 4.普通参数与多个参数的结合 2.类 1.类的定义 2.类的实例化 3.继承 1.函数 1.函数的定义 def 函数名(输入参数): 文档字符串 函数体 …

第七届国际通信与网络工程会议(ICCNE 2024)即将召开!

2024年第七届国际通信与网络工程会议&#xff08;ICCNE 2024&#xff09;将于7月26-28日在越南岘港召开。本次会议由维新大学主办&#xff0c;岘港大学、胡志明市科技大学协办。ICCNE 2024旨在为来自行业和学术界的研究人员、从业者和专业人士提供论坛&#xff0c;分享其最新研…

基于boost库的搜索引擎项目

文章目录 一、项目背景二、什么样的搜索引擎三、搜索引擎的宏观图原理四、Parse模块4.1下载boost库源代码4.2提取boost库中以.html为结尾的文件4.2.1 boost库的简单使用 4.3数据清洗(去标签化)4.3.1数据清洗的具体实现 4.4将清洗后的数据写入到raw.txt文件中 五、正排索引 vs 倒…

C++面试问题收集

0 持续更新中 目录 0 持续更新中 1 C语言相关 1.1 malloc/free和new/delete区别 1.2 内存泄漏 1.3 堆区和栈区的区别 1.4 宏定义和const的区别 1.5 多态 1.6 类中的静态成员变量 2 操作系统相关 2.1 进程和&#xff08;用户&#xff09;线程的区别 2.2 系统调用 2.3…

学习SSM的记录(七)-- SSM整合

目录 SSM整合理解 什么是SSM整合 SSM整合核心问题 1.SSM整合需要几个ioc容器 2.每一个ioc容器对应哪些类型组件 ​编辑 3.ioc容器之间关系和调用方向 4.具体多少配置类以及对应容器关系 5.ioc初始化方式和配置位置 ​编辑 SSM整合配置实战 1.数据库准备 2.创建项目…

十分钟教你有效运用百度检索式

十分钟教你有效运用百度检索式 ​ 百度作为国内最大的搜索引擎网站&#xff0c;虽然很多人都喷它的搜索页面广告太多&#xff0c;但是对于不会科学上网的同学来说&#xff0c;似乎除了继续用百度以外也没有更好的选择。 ​ 其实搜索引擎一般都会内涵一些高级的搜索技巧&#…

中间件漏洞(redis)

目录 1.Redis服务器被挖矿案例 2.redis常见用途 3.redis环境配置 4.redis的持久化机制 5.redis动态修改配置 6.webshell提权案例 7.定时任务bash反弹连接提权案例 8.SSH Key提权案例 9.redis安全加固分析 1.Redis服务器被挖矿案例 我没有体验过&#xff0c;那就看看别…

【Redis】Redis常用命令一

1.keys&#xff1a;返回所有满足条件的key&#xff0c;比如&#xff1a; KEYS pattern时间复杂度&#xff1a;O(N)&#xff0c;返回值&#xff1a;匹配pattern的所有key。 • h?llo 匹配 hello , hallo 和 hxllo • h*llo 匹配 hllo 和 heeeello • h[ae]llo 匹配 hello 和 …

【CSP试题回顾】201709-1-打酱油

CSP-201709-1-打酱油 解题代码 #include<iostream> using namespace std;int n, num;int main() { cin >> n;if (n / 50 ! 0){num 7 * (n / 50);n % 50;}if (n / 30 ! 0){num 4 * (n / 30);n % 30;}if (n / 10 ! 0) num (n / 10);cout << num;return…

Flask 专题

[CISCN2019 总决赛 Day1 Web3]Flask Message Board 查看session解密 但不知道密钥&#xff0c;题目说FLASK,那肯定就是找密钥,发现输入什么都没有显示&#xff0c;只有author那里有回显在版上&#xff0c;所以尝试sstl&#xff0c;{{config}}找到密钥 扫目录发现有admin进入…

6个免费的3D模型网站,助你3D建模渲染不用愁

​随着3D建模和渲染技术的不断发展&#xff0c;其重要性也日益增加。创建新的3D模型往往需要耗费大量时间&#xff0c;因此&#xff0c;本文整理了六个顶尖的免费3D模型资源网站&#xff0c;以便您能够方便地获取3D模型&#xff0c;大幅减少建模时间。这些资源有助于您更快地开…