【Unity实战】从零手戳一个库存背包系统

news/2024/4/29 6:23:12/文章来源:https://blog.csdn.net/qq_36303853/article/details/133021338

文章目录

  • 前言
  • 素材
  • 开始
    • 一、绘制背包UI
    • 二、背包开启关闭
    • 三、初始化背包网格
    • 四、 添加物品
    • 五、 拖拽交换功能物品
    • 六、 物品拆分
    • 七、 物品堆叠
    • 八、 拖拽还原
    • 九、 引入字典存储数据
    • 十、 拾取物品
    • 十一、 丢弃物品
  • 最终效果
  • 源码
  • 完结

前言

库存背包系统是大多数游戏的关键部分,几乎在每种类型的游戏都可能会用到,今天我将带你从零实现一个能够进行拖放的库存拆分、堆叠和丢弃的背包系统,你可以将它轻松的移植到你的游戏中。

老粉丝应该知道我之前有做过一个背包系统,当时做的比较简单,很多功能都没有实现,所以这次算一个重置版,当然你有兴趣可以看看之前实现的背包系统:https://blog.csdn.net/qq_36303853/article/details/129962414

先来看看实现的最终效果
在这里插入图片描述

素材

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

开始

一、绘制背包UI

在这里插入图片描述
物品列表网格添加Grid Layout Group组件控制物品格子排序
在这里插入图片描述
效果
在这里插入图片描述

二、背包开启关闭

物品槽信息类,用于存储每个物品槽的信息

// 物品槽信息类,用于存储每个物品槽的信息
[System.Serializable]
public class ItemSlotInfo
{public Item item;// 物品对象public string name;// 物品名称public int stacks;// 堆叠数量public ItemSlotInfo(Item newItem, int newstacks){item = newItem;stacks = newstacks;}
}

库存系统

using System.Collections.Generic;
using UnityEngine;public class Inventory : MonoBehaviour
{[SerializeReference] public List<ItemSlotInfo> items = new List<ItemSlotInfo>();// 物品列表[Space][Header("库存菜单组件")]public GameObject inventoryMenu;// 背包菜单public GameObject itemPanel;// 物品列表容器public GameObject itemPanelGrid;// 物品列表网格布局[Space]public int inventorySize = 24;// 背包容量大小void Start(){// 初始化物品列表并赋值为 nullfor (int i = 0; i < inventorySize; i++){items.Add(new ItemSlotInfo(null, 0));}}void Update(){// 按下 Tab 键显示或隐藏背包界面if (Input.GetKeyDown(KeyCode.Tab)){if (inventoryMenu.activeSelf){inventoryMenu.SetActive(false);Cursor.lockState = CursorLockMode.Locked;// 隐藏光标并锁定在屏幕中心}else{inventoryMenu.SetActive(true);Cursor.lockState = CursorLockMode.Confined;// 显示光标并限制在屏幕内部移动}}}
}

挂载Inventory 脚本在canvas,配置数据
在这里插入图片描述

运行效果
在这里插入图片描述

三、初始化背包网格

新建物品容器脚本

using UnityEngine;
using UnityEngine.UI;
using TMPro;public class ItemPanel : MonoBehaviour
{public Inventory inventory;// 背包脚本引用public ItemSlotInfo itemSlot;// 物品槽信息public Image itemImage;// 物品图像组件public TextMeshProUGUI stacksText;// 堆叠数量文本组件
}

挂载代码
在这里插入图片描述

新建物品抽象类,所有物品类型都需要继承此类

using UnityEngine;
//物品抽象类,所有物品类型都需要继承此类
[System.Serializable]
public abstract class Item
{public abstract string GiveName();// 获取物品名称public virtual int MaxStacks()// 获取每个物品槽的最大堆叠数量{return 30;// 默认为 30}public virtual Sprite GiveItemImage()// 获取物品图片{return Resources.Load<Sprite>("UI/Item Images/No Item Image Icon");// 默认图片}
}

Inventory新增刷新背包功能,每次打开背包时调用RefreshInventory();

private List<ItemPanel> existingPanels = new List<ItemPanel>();//物品容器列表//刷新背包
public void RefreshInventory()
{//物品容器列表existingPanels = itemPanelGrid.GetComponentsInChildren<ItemPanel>().ToList();//如果物品列表容器不足,创建物品面板if (existingPanels.Count < inventorySize){int amountToCreate = inventorySize - existingPanels.Count;for (int i = 0; i < amountToCreate; i++){GameObject newPanel = Instantiate(itemPanel, itemPanelGrid.transform);existingPanels.Add(newPanel.GetComponent<ItemPanel>());}}int index = 0;foreach (ItemSlotInfo i in items){//给物品列表元素命名i.name = "" + (index + 1);if (i.item != null) i.name += ":" + i.item.GiveName();else i.name += ":-";//更新物品面板ItemPanel panel = existingPanels[index];panel.name = i.name + " Panel";if (panel != null){panel.inventory = this;panel.itemSlot = i;if (i.item != null){panel.itemImage.gameObject.SetActive(true);  // 显示物品图标panel.itemImage.sprite = i.item.GiveItemImage();  // 设置物品图标的精灵panel.stacksText.gameObject.SetActive(true);  // 显示物品叠加数量panel.stacksText.text = "" + i.stacks;  // 设置物品叠加数量的文本}else{panel.itemImage.gameObject.SetActive(false);  // 隐藏物品图标panel.stacksText.gameObject.SetActive(false);  // 隐藏物品叠加数量}}index++;}
}

效果
在这里插入图片描述

四、 添加物品

Inventory实现添加和清除物品功能

//添加物品
public int AddItem(Item item, int amount)
{// 检查已有物品槽中是否有空余位置foreach (ItemSlotInfo i in items){if (i.item != null){if (i.item.GiveName() == item.GiveName()){if (amount > i.item.MaxStacks() - i.stacks){amount -= i.item.MaxStacks() - i.stacks;i.stacks = i.item.MaxStacks();}else{i.stacks += amount;//如果背包菜单处于激活状态,刷新背包显示if (inventoryMenu.activeSelf) RefreshInventory();return 0;}}}}//将剩余的物品放入空的物品槽中foreach (ItemSlotInfo i in items){if (i.item == null){if (amount > item.MaxStacks()){i.item = item;i.stacks = item.MaxStacks();amount -= item.MaxStacks();}else{i.item = item;i.stacks = amount;//如果背包菜单处于激活状态,刷新背包显示if (inventoryMenu.activeSelf) RefreshInventory();return 0;}}}Debug.Log("库存中没有空间:" + item.GiveName());//如果背包菜单处于激活状态,刷新背包显示if (inventoryMenu.activeSelf) RefreshInventory();return amount;
}//清空指定物品槽中的物品和叠加数量
public void ClearSlot(ItemSlotInfo slot)
{slot.item = null;slot.stacks = 0;
}

新增第一个物品,木头脚本,继承Item基类,重新对应参数

using UnityEngine;
public class WoodItem : Item
{public override string GiveName()// 获取物品名称{return "Wood";}public override int MaxStacks()// 获取每个物品槽的最大堆叠数量{return 10;}public override Sprite GiveItemImage()// 获取物品图片{return Resources.Load<Sprite>("UI/Item Images/Wood Icon");}
}

添加40个木头进库测试

public class Inventory : MonoBehaviour
{void Start(){// 。。。AddItem(new WoodItem(), 40);}
}

效果
在这里插入图片描述

五、 拖拽交换功能物品

先实现指针跟随鼠标,新增脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;public class Mouse : MonoBehaviour
{public GameObject mouseItemUI; // 鼠标上的物品UIpublic Image mouseCursor; // 鼠标光标public ItemSlotInfo itemSlot; // 物品槽信息public Image itemImage; // 物品图像public TextMeshProUGUI stacksText; // 叠加数量文本void Update(){// 将鼠标指针位置设置为当前鼠标位置transform.position = Input.mousePosition;// 如果鼠标被锁定if (Cursor.lockState == CursorLockMode.Locked){mouseCursor.enabled = false; // 隐藏鼠标光标mouseItemUI.SetActive(false); // 隐藏鼠标上的物品UI}else{mouseCursor.enabled = true; // 显示鼠标光标// 如果物品槽中有物品if (itemSlot.item != null){mouseItemUI.SetActive(true); // 显示鼠标上的物品UI}else{mouseItemUI.SetActive(false); // 隐藏鼠标上的物品UI}}}public void SetUI(){stacksText.text = "" + itemSlot.stacks; // 设置叠加数量文本itemImage.sprite = itemSlot.item.GiveItemImage(); // 设置物品图像}public void EmptySlot(){itemSlot = new ItemSlotInfo(null, 0);// 清空物品槽}
}

新增拖拽,跟随鼠标显示的UI
在这里插入图片描述
效果,就和一个格子效果一致
在这里插入图片描述
给Mouse挂载mouse脚本,并添加Canvas Group组件,将这个组件的blocksRaycasts属性设置为false,表示在我们刚开始拖拽的整个过程当中,鼠标不会再去把这个UI物品当作一个阻挡物来看待,包括他的子物体的所有的UI对象
在这里插入图片描述
ps:当然,选择去除各个子组件Image里的射线投射目标,也能实现相同的效果
在这里插入图片描述

记得默认先隐藏mouse下的物品列表容器
在这里插入图片描述
修改ItemPanel脚本实现物品拖拽和交换

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.EventSystems;public class ItemPanel : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IPointerUpHandler, IDragHandler, IDropHandler
{public Inventory inventory; // 背包脚本引用public ItemSlotInfo itemSlot; // 物品槽信息public Image itemImage; // 物品图像组件public TextMeshProUGUI stacksText; // 堆叠数量文本组件private bool click; // 当前是否点击private Mouse mouse; // 鼠标// 当鼠标进入时调用的方法public void OnPointerEnter(PointerEventData eventData){eventData.pointerPress = this.gameObject;}// 当鼠标按下时调用的方法public void OnPointerDown(PointerEventData eventData){click = true;}// 当鼠标抬起时调用的方法public void OnPointerUp(PointerEventData eventData){if (click){OnClick();click = false;}}// 在拖拽结束时调用public void OnDrop(PointerEventData eventData){OnClick();click = false;}// 在拖拽过程中连续调用public void OnDrag(PointerEventData eventData){if (click){OnClick();click = false;OnDrop(eventData);}}// 将物品拾取到鼠标槽位public void PickupItem(){mouse.itemSlot = itemSlot;mouse.SetUI();}// 物品面板淡出效果public void Fadeout(){itemImage.CrossFadeAlpha(0.3f, 0.05f, true);//0.05 秒itemImage透明度渐变到0.3}// 将物品放下到当前物品面板上public void DropItem(){itemSlot.item = mouse.itemSlot.item;itemSlot.stacks = mouse.itemSlot.stacks;inventory.ClearSlot(mouse.itemSlot);}// 交换两个物品槽位的物品public void SwapItem(ItemSlotInfo slotA, ItemSlotInfo slotB){// 暂存槽位A的物品信息ItemSlotInfo tempItem = new ItemSlotInfo(slotA.item, slotA.stacks);// 将槽位B的物品信息赋值给槽位AslotA.item = slotB.item;slotA.stacks = slotB.stacks;// 将暂存的物品信息赋值给槽位BslotB.item = tempItem.item;slotB.stacks = tempItem.stacks;}// 当物品面板被点击时调用的方法void OnClick(){if (inventory != null){mouse = inventory.mouse;// 如果鼠标槽位为空,将物品拾取到鼠标槽位if (mouse.itemSlot.item == null){if (itemSlot.item != null){PickupItem();Fadeout();}}else{// 点击的是原始槽位if (itemSlot == mouse.itemSlot){inventory.RefreshInventory();}// 点击的是空槽位else if (itemSlot.item == null){DropItem();inventory.RefreshInventory();}// 点击的是不同物品类型的已占用槽位else if (itemSlot.item.GiveName() != mouse.itemSlot.item.GiveName()){SwapItem(itemSlot, mouse.itemSlot);inventory.RefreshInventory();}}}}
}

修改Inventory,初始化清空鼠标物品槽

public Mouse mouse;void Update()
{// 按下 Tab 键显示或隐藏背包界面if (Input.GetKeyDown(KeyCode.Tab)){if (inventoryMenu.activeSelf){//。。。mouse.EmptySlot();}else{//。。。}}
}
//刷新背包
public void RefreshInventory()
{//。。。mouse.EmptySlot();
}

为了方便交换测试,我们新增一个石头的物品脚本

using UnityEngine;
public class StoneItem : Item
{public override string GiveName()// 获取物品名称{return "Stone";}public override int MaxStacks()// 获取每个物品槽的最大堆叠数量{return 5;}public override Sprite GiveItemImage()// 获取物品图片{return Resources.Load<Sprite>("UI/Item Images/Stone Icon");}
}

在Inventory中生成

void Start()
{//。。。AddItem(new WoodItem(), 40);AddItem(new StoneItem(), 40);
}

运行效果
在这里插入图片描述

修复问题,基本拖到和交换功能是做好了,但是你会发现物品放下时物品透明的并没有还原,那是因为前面我们拖动时调用了Fadeout方法,实现了物品面板淡出效果,透明度变为了0.3,我们放置物品时没有还原物品面板透明度

在Inventory新增代码

//刷新背包
public void RefreshInventory()
{//。。。foreach (ItemSlotInfo i in items){//。。。if (panel != null){//。。。if (i.item != null){//。。。panel.itemImage.CrossFadeAlpha(1, 0.05f, true);//0.05 秒itemImage透明度渐变到1完全不透明}//。。。}}
}

效果
在这里插入图片描述

六、 物品拆分

实现滚轮拆分物品,shift对半分物品效果

修改Mouse代码,实现滚轮拆分物品

public ItemPanel sourceItemPanel; // 源物品面板对象
public int splitSize; // 拆分数量void Update()
{// ...if (itemSlot.item != null) // 如果物品槽中有物品{if (Input.GetAxis("Mouse ScrollWheel") > 0 && splitSize < itemSlot.stacks){// 当鼠标向上滚动并且拆分数量小于物品槽剩余堆叠数量时splitSize++; // 增加拆分数量}if (Input.GetAxis("Mouse ScrollWheel") < 0 && splitSize > 1){// 当鼠标向下滚动并且拆分数量大于1时splitSize--; // 减少拆分数量}stacksText.text = "" + splitSize; // 在UI中显示拆分数量if (splitSize == itemSlot.stacks)// 如果拆分数量等于物品的堆叠数量{ // 将源物品面板的堆叠数量文本组件设置为不可见sourceItemPanel.stacksText.gameObject.SetActive(false);  }else{sourceItemPanel.stacksText.gameObject.SetActive(true);// 在文本组件中显示物品的剩余堆叠数量sourceItemPanel.stacksText.text = "" + (itemSlot.stacks - splitSize);}}
}   public void SetUI()
{// stacksText.text = "" + itemSlot.stacks; // 设置叠加数量文本stacksText.text = "" + splitSize;// 在UI中显示拆分数量itemImage.sprite = itemSlot.item.GiveItemImage();
} 

修改ItemPanel,实现shift对半分物品效果

// 将物品拾取到鼠标槽位
public void PickupItem()
{mouse.itemSlot = itemSlot;mouse.sourceItemPanel = this;if (Input.GetKey(KeyCode.LeftShift) && itemSlot.stacks > 1){mouse.splitSize = itemSlot.stacks / 2;}else{mouse.splitSize = itemSlot.stacks;}mouse.SetUI();
}
// 将物品放下到当前物品面板上
public void DropItem()
{itemSlot.item = mouse.itemSlot.item;if (mouse.splitSize < mouse.itemSlot.stacks){itemSlot.stacks = mouse.splitSize;mouse.itemSlot.stacks -= mouse.splitSize;mouse.EmptySlot();}else{itemSlot.stacks = mouse.itemSlot.stacks;inventory.ClearSlot(mouse.itemSlot);}
}

效果
在这里插入图片描述

七、 物品堆叠

修改ItemPanel代码,新增物品堆叠方法

//物品堆叠
public void StackItem(ItemSlotInfo source, ItemSlotInfo destination, int amount)
{// 计算目标物品槽中可用的堆叠空间int slotsAvailable = destination.item.MaxStacks() - destination.stacks;// 如果目标物品槽没有可用的堆叠空间,则直接返回if (slotsAvailable == 0) return;if (amount > slotsAvailable){// 堆叠数量超过可用空间时,从源物品槽中减去可用空间source.stacks -= slotsAvailable;// 目标物品槽的堆叠数量设置为最大堆叠数destination.stacks = destination.item.MaxStacks();}if (amount <= slotsAvailable){// 堆叠数量小于可用空间时,将堆叠数量加到目标物品槽中destination.stacks += amount;// 如果源物品槽中剩余的堆叠数量等于堆叠数量(即所有物品都被堆叠完),则清空源物品槽if (source.stacks == amount) inventory.ClearSlot(source);// 否则,从源物品槽中减去堆叠数量else source.stacks -= amount;  }
}// 当物品面板被点击时调用的方法
void OnClick()
{//。。。// 点击的是同物品类型的已占用槽位else if (itemSlot.stacks < itemSlot.item.MaxStacks()){StackItem(mouse.itemSlot, itemSlot, mouse.splitSize);inventory.RefreshInventory();}
}

运行效果
在这里插入图片描述

八、 拖拽还原

实现拖拽物品时按鼠标右键还原物品
修改Inventory代码

void Update()
{//。。。//拖拽物品时按鼠标右键还原物品if (Input.GetKeyDown(KeyCode.Mouse1) && mouse.itemSlot.item != null){RefreshInventory();}
}

效果
在这里插入图片描述

九、 引入字典存储数据

创建一个用于存储所有物品的字典allItemsDictionary

allItemsDictionary 字典是为了方便根据物品名称来查找对应的物品对象。通常情况下,当你需要添加某个物品时,首先需要根据物品名称从字典中获取对应的物品对象,然后再将其添加到 items 列表中。

使用字典的好处是可以通过物品名称快速索引到对应的物品对象,而不需要遍历整个 items 列表。这在处理大量物品的时候可以提高性能和效率。

修改Inventory代码

// 创建一个用于存储所有物品的字典,其中键为物品名称,值为对应的物品对象
Dictionary<string, Item> allItemsDictionary = new Dictionary<string, Item>();void Start()
{// 初始化物品列表并赋值为 nullfor (int i = 0; i < inventorySize; i++){items.Add(new ItemSlotInfo(null, 0));}// 获取所有可用的物品,并将它们添加到物品字典中List<Item> allItems = GetAllItems().ToList();string itemsInDictionary = "字典条目:";foreach (Item i in allItems){if (!allItemsDictionary.ContainsKey(i.GiveName())){allItemsDictionary.Add(i.GiveName(), i);itemsInDictionary += "," + i.GiveName();}else{// 如果字典中已存在同名的物品,则输出调试信息Debug.Log("" + i + "已存在于与之共享名称的字典中 " + allItemsDictionary[i.GiveName()]);}}itemsInDictionary += ".";Debug.Log(itemsInDictionary);// 添加一些初始物品AddItem("Wood", 40);AddItem("Stone", 40);
}// 获取所有可用的物品
IEnumerable<Item> GetAllItems()
{List<Item> allItems = new List<Item>();// 获取当前应用程序域中的所有程序集Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();// 遍历每个程序集foreach (Assembly assembly in assemblies){// 获取程序集中定义的所有类型Type[] types = assembly.GetTypes();// 遍历每个类型foreach (Type type in types){// 检查类型是否是 Item 类的子类if (type.IsSubclassOf(typeof(Item))){// 创建该类型的实例,并将其转换为 Item 对象Item item = Activator.CreateInstance(type) as Item;// 将物品添加到列表中allItems.Add(item);}}}return allItems;
}   //添加物品
public int AddItem(string itemName, int amount)
{//查找要添加的项目Item item = null;allItemsDictionary.TryGetValue(itemName, out item);//如果未找到任何项,则退出方法if (item == null){Debug.Log("无法在字典中找到要添加到库存中的物品");return amount;}//。。。
}

十、 拾取物品

新增可拾取物品脚本

using UnityEngine;
using TMPro;//物品拾取脚本
public class ItemPickup : MonoBehaviour
{public string itemToDrop;   // 需要拾取的物品名称public int amount = 1;      // 物品数量,默认为1private TextMeshPro text;   //物品文本Inventory playerInventory;  //玩家的背包组件void Start(){text = transform.GetComponentInChildren<TextMeshPro>();text.text = amount.ToString();}void Update(){if (Input.GetKeyDown(KeyCode.C)){PickUpItem();}}// 当碰撞体进入触发器时调用private void OnTriggerStay2D(Collider2D other){if (other.tag == "Player"){// 获取玩家的背包组件playerInventory = other.GetComponent<Inventory>();}}//当碰撞体离开触发器时调用private void OnTriggerExit2D(Collider2D other){if (other.tag == "Player"){// 获取玩家的背包组件playerInventory = null;}}// 拾取物品的方法public void PickUpItem(){// 如果玩家背包组件存在,则拾取物品if (playerInventory == null) return;// 将物品添加到背包,并返回剩余的物品数量amount = playerInventory.AddItem(itemToDrop, amount);// 如果数量小于1,销毁该拾取物品的游戏对象if (amount < 1){Destroy(this.gameObject);}else{//更新texttext.text = amount.ToString();}}
}

创建一个Player主角和可拾取物品
在这里插入图片描述

在这里插入图片描述
给Player添加Player标签,并把Inventory脚本移到Player下
在这里插入图片描述
可拾取物品添加脚本,配置参数
在这里插入图片描述

效果
在这里插入图片描述

十一、 丢弃物品

绘制丢弃物品预制体
在这里插入图片描述
挂载ItemPickup脚本
在这里插入图片描述

修改Inventory代码

public GameObject dropObject;//丢弃物品预制体//丢弃物品
public void DropItem(string itemName)
{Item item = null;// 从字典中查找物品allItemsDictionary.TryGetValue(itemName, out item);if (item == null){Debug.Log("在字典中找不到要添加到掉落的物品");return;}// 在当前位置实例化一个掉落物体GameObject droppedItem = Instantiate(dropObject, transform.position, Quaternion.identity);//修改图片droppedItem.GetComponent<SpriteRenderer>().sprite = item.GiveItemImage();ItemPickup ip = droppedItem.GetComponent<ItemPickup>();if (ip != null){// 设置掉落物品的属性ip.itemToDrop = itemName;ip.amount = mouse.splitSize;mouse.itemSlot.stacks -= mouse.splitSize;//更新物品槽中该物品的剩余数量,及减去将要丢弃的物品数量}if (mouse.itemSlot.stacks < 1) ClearSlot(mouse.itemSlot);// 清空物品槽mouse.EmptySlot();// 清空鼠标上的物品RefreshInventory();// 刷新背包显示
}

Update中调用

void Update()
{//控制丢弃物品 EventSystem.current.IsPointerOverGameObject():该条件判断鼠标当前是否位于UI元素之上if (Input.GetKeyDown(KeyCode.Mouse0) && mouse.itemSlot.item != null && !EventSystem.current.IsPointerOverGameObject()){DropItem(mouse.itemSlot.item.GiveName());}
}

效果
在这里插入图片描述

最终效果

在这里插入图片描述

源码

整理好后,我会放上来

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。点赞越多,更新越快哦!当然,如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

python项目2to3方案预研

目录 官方工具2to3工具安装参数解释基本使用工具缺陷 future工具安装参数解释基本使用工具缺陷 python-modernize工具安装参数解释基本使用工具缺陷 pyupgrade工具安装参数解释基本使用工具缺陷 对比 官方工具2to3 2to3 是Python官方提供的用于将Python 2代码转换为Python 3代…

解决qml编译时出现错误ninja: build stopped: subcommand failed.

qml编译时出现错误ninja: build stopped: subcommand failed. 如下图&#xff1a; 解决这个编译错误其实很简单&#xff0c;我把Window写错了&#xff0c;写成了window, 如果有类似的报错&#xff0c;可以检查一下qml代码是否有问题。当然在Qt Creator里也没有错误提示&#x…

Canal实现Mysql数据同步至Redis、Elasticsearch

文章目录 1.Canal简介1.1 MySQL主备复制原理1.2 canal工作原理 2.开启MySQL Binlog3.安装Canal3.1 下载Canal3.2 修改配置文件3.3 启动和关闭 4.SpringCloud集成Canal4.1 Canal数据结构![在这里插入图片描述](https://img-blog.csdnimg.cn/c64b40c2231a4ea39a95aac81d771bd1.pn…

重装系统(配置环境)

这里写目录标题 0.重装系统1.python1.1 anaconda1.2 pycharm1.3 深度学习环境配置 2.java2.1.安装JDK2.2.配置JDK环境变量2.3IDEA2.4 Maven 3.大数据3.1 虚拟机3.2 Hadoop平台3.3 存储3.4 采集3.5 计算3.6 查询3.7 可视化 0.重装系统 // An highlighted block var foo bar;1.…

【性能优化下】组织结构同步优化二,全量同步/增量同步,断点续传实现方式

看到这一篇文章的 xdm &#xff0c;应该对组织结构同步有一些想法了吧&#xff0c;如果没有&#xff0c;可以看前面两篇文章&#xff0c;可以通过如下地址查看一下&#xff1a; 【性能优化上】第三方组织结构同步优化一&#xff0c;你 get 到了吗&#xff1f; 坑爹&#xff0c…

UE5读取json文件

一、下载插件 在工程中启用 二、定义读取外部json文件的函数&#xff0c;参考我之前的文章 ue5读取外部文件_艺菲的博客-CSDN博客 三、读取文件并解析为json对象 这里Load Text就是自己定义的函数&#xff0c;ResourceBundle为一个字符串常量&#xff0c;通常是读取的文件夹…

数据预处理方式合集

删除空行 #del all None value data_all.dropna(axis1, howall, inplaceTrue) 删除空列 #del all None value data_all.dropna(axis0, howall, inplaceTrue) 缺失值处理 观测缺失值 观测数据缺失值有一个比较好用的工具包——missingno&#xff0c;直接传入DataFrame&…

【Html】用CSS定义咖啡 - 咖啡配料展示

显示效果 代码 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>CodePen - For The Love Of Coffee</title><link rel"stylesheet" href"./style.css">&l…

Jenkins结合Gitlab,实现镜像构建及推送

docker-compose jenkins的docker-compose目录为为/home/jenkins&#xff0c;这个后面写脚本的时候需要对应上 version: 3 services:docker_jenkins:restart: alwaysimage: jenkins/jenkins:ltscontainer_name: docker_jenkinsprivileged: true ports:- 8080:8080- 50000:5000…

MyBatis基础之执行SQL

文章目录 执行 SQL 语句1. 增删改操作insert 元素insert 过程中的主键回填delete 元素 和 update 元素 2. getMapper 方法3. 查操作select 元素select 与 聚合函数 4. 传递多个参数使用 Map 传递多参数使用 JavaBean 传递多参使用注解方式传递多参数 执行 SQL 语句 Mapper 是 …

(2) Java 8 实战第二版——补充 收集数据、并行数据处理能力与性能

第6章 用Collectors类创建和使用收集器将数据流归约为一个值汇总&#xff1a;归约的特殊情况数据分组和分区开发你的自定义收集器 对一个交易列表按货币分组&#xff0c;获得该货币的所有交易额总和&#xff08;返回一个Map<Currency, Integer>&#xff09;。将交易列表…

面向组织分析的内容

声明 本文是学习GB-T 42859-2023 航天产品质量问题三个面向分析方法实施要求. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了航天产品质量问题三个面向分析方法实施的一般要求、程序和分析内容。 本文件适用于承担航天产品研制…

性能测试 —— Tomcat监控与调优:Jconsole监控

JConsole的图形用户界面是一个符合Java管理扩展(JMX)规范的监测工具&#xff0c;JConsole使用Java虚拟机(Java VM)&#xff0c;提供在Java平台上运行的应用程序的性能和资源消耗的信息。在Java平台&#xff0c;标准版(Java SE平台)6&#xff0c;JConsole的已经更新到目前的外观…

阿里云服务器价格表,轻量和服务器最新活动价格表汇总

租用阿里云服务器怎么收费&#xff1f;阿里云服务器配置不同一年价格也不同&#xff0c;阿里云2核2G3M带宽108元一年、2核4G4M带宽297.98元12个月&#xff0c;云服务器u1公网带宽可选1M到5M&#xff0c;系统盘为ESSD云盘40GB起&#xff0c;CPU内存配置可选2核2G、2核4G、4核8G、…

抖音seo矩阵系统源码分享-技术梳理

抖音seo源码&#xff0c;抖音seo矩阵系统源码技术搭建&#xff0c;抖音seo源码技术开发思路梳理搭建 抖音账号矩阵系统部分源代码分享 if (empty($video_item)) {$this->displayJsonError(参数错误);}$curr_platform json_decode($video_item[dv_platform], 1);$curr_plat…

牛客网Verilog刷题 | 快速入门-基础语法

1、VL1 四选一多路器 描述 制作一个四选一的多路选择器&#xff0c;要求输出定义上为线网类型 状态转换&#xff1a; d0 11 d1 10 d2 01 d3 00 信号示意图&#xff1a; 输入描述&#xff1a; 输入信号 d1,d2,d3,d4 sel 类型 wire 输出描述&#xff1a; 输出信号 mux_ou…

vim缓存-交换文件

Catf1agCTF靶场 web swp 题目链接&#xff1a;http://catf1ag.cn/ 个人博客&#xff1a;https://sword-blogs.com/ 题目考点&#xff1a; vim在编辑文档的过程中如果异常退出&#xff0c;会产生缓存文件 vim 交换文件名 参考文章&#xff1a;vim手册 https://yianwillis.…

ROS2 的行为树 — 第 1 部分:解锁高级机器人决策和控制

一、说明 在复杂而迷人的机器人世界中&#xff0c;行为树&#xff08;BT&#xff09;已成为决策过程中不可或缺的一部分。它们提供了一种结构化、模块化和高效的方法来对机器人的行为进行编程。BT起源于视频游戏行业&#xff0c;用于控制非玩家角色&#xff0c;他们在机器人领域…

云原生的简单理解

一、何谓云原生&#xff1f; 一种构建和运行应用软件的方法 应用程序从设计之初即考虑到云的环境&#xff0c;原生为云而设计&#xff0c;在云上以最佳姿势运行&#xff0c;充分利用和发挥云平台的弹性分布式优势。 二、包括以下四个要素 采用容器化部署&#xff1a;实现云平…

机器学习(17)---支持向量机(SVM)

支持向量机 一、概述1.1 介绍1.2 工作原理1.3 三层理解 二、sklearn.svm.SVC2.1 查看数据集2.2 contour函数2.3 画决策边界&#xff1a;制作网格2.4 建模画图 三、非线性情况推广3.1 查看数据集3.2 线性画图3.3 为非线性数据增加维度并绘制3D图像 四、核函数 一、概述 1.1 介绍…