【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 前言
  • 素材下载
  • 图片配置
  • 获取格子坐标
  • 动态控制背包大小
  • 添加物品
  • 移动物品
  • 物品跟随鼠标
  • 创建物品的容器,定义不同物品
  • 修改物品尺寸
  • 修复物品放置位置问题
  • 按物品尺寸占用对应大小的格子
  • 判断物品是否超出边界范围
  • 物品放置重叠,交换物品
  • 放置加入点偏移量
  • 突出显示我们选中的物品
  • 优化
  • 多个背包
  • 自动入库物品
  • 旋转物品
  • 修改旋转高亮背景和占位也跟着旋转
  • 选中拖拽物品排序问题
  • 最终效果
  • 源码
  • 完结

前言

在这一集中我将使用Unity制作基于瓦片的网格库存系统。 就像在《逃离塔科夫》、《暗黑破坏神》或《流放之路》等游戏中一样。

素材下载

https://assetstore.unity.com/packages/2d/gui/icons/gui-parts-159068

图片配置

配置图片为重复
在这里插入图片描述

不懂UI画布适配查看:【Unity小技巧】最简单的UI设置适配方案

修改UI画布适配
在这里插入图片描述

新增UI图片,类型改为平铺,默认图片是256的,太大了,所以我们选择缩小4倍,每单位像素为4,同时注意修改轴心在左上角
在这里插入图片描述

获取格子坐标

新增ItemGrid代码

public class ItemGrid : MonoBehaviour
{// 定义每个格子的宽度和高度const float tileSizeWidth = 256 / 4;const float tileSizeHeight = 256 / 4;// 计算在格子中的位置Vector2 positionOnTheGrid = new Vector2();Vector2Int tileGridPosition = new Vector2Int();RectTransform rectTransform;Canvas canvas;private void Start(){rectTransform = GetComponent<RectTransform>();canvas = FindObjectOfType<Canvas>();}private void Update(){if (Input.GetMouseButtonDown(0)){// 获取当前鼠标位置在网格中的格子坐标,并打印到控制台Debug.Log(GetTileGridPosition(Input.mousePosition));}}// 根据鼠标位置计算在格子中的位置public Vector2Int GetTileGridPosition(Vector2 mousePosition){// 计算鼠标位置相对于 RectTransform 的偏移量positionOnTheGrid.x = mousePosition.x - rectTransform.position.x;positionOnTheGrid.y = rectTransform.position.y - mousePosition.y;// 将偏移量转换为网格位置// 这里假设 tileSizeWidth 和 tileSizeHeight 是单个瓦片的宽度和高度// canvas.scaleFactor 是 Canvas 的缩放因子(通常用于 UI 适配不同分辨率)tileGridPosition.x = (int)(positionOnTheGrid.x / tileSizeWidth / canvas.scaleFactor);tileGridPosition.y = (int)(positionOnTheGrid.y / tileSizeHeight / canvas.scaleFactor);// 返回计算出的网格位置return tileGridPosition;}
}

挂载脚本
在这里插入图片描述
效果,点击格子打印位置
在这里插入图片描述

动态控制背包大小

修改ItemGrid

[SerializeField] int gridSizeWidth = 10;
[SerializeField] int gridSizeHeight = 10;private void Start()
{rectTransform = GetComponent<RectTransform>();canvas = FindObjectOfType<Canvas>();Init(gridSizeWidth, gridSizeHeight);
}void Init(int width, int height){Vector2 size = new Vector2(width * tileSizeWidth, height * tileSizeHeight);rectTransform.sizeDelta = size;
}

配置
在这里插入图片描述
效果
在这里插入图片描述

添加物品

配置物品预制体。修改尺寸和去掉光线投射目标
在这里插入图片描述
新增Item脚本,挂载在物品上

public class Item : MonoBehaviour {}

在这里插入图片描述

动态添加测试物品,修改ItemGrid

Item[,] itemSlot;//存储物品位置信息private void Start()
{itemSlot= new Item[gridSizeWidth, gridSizeHeight];rectTransform = GetComponent<RectTransform>();canvas = FindObjectOfType<Canvas>();Init(gridSizeWidth, gridSizeHeight);//动态添加测试物品Item item = Instantiate(itemPrefab).GetComponent<Item>();PlaceItem(item, 0, 0);item = Instantiate(itemPrefab).GetComponent<Item>();PlaceItem(item, 3, 2);item = Instantiate(itemPrefab).GetComponent<Item>();PlaceItem(item, 2, 4);
}//按格子坐标添加物品
public void PlaceItem(Item item, int posX, int posY){itemSlot[posX, posY] = item;item.transform.SetParent(transform, false);Vector2 positon = new Vector2();positon.x = posX * tileSizeWidth + tileSizeWidth / 2;positon.y = -(posY * tileSizeHeight + tileSizeHeight / 2);item.transform.localPosition = positon;
}

配置
在这里插入图片描述

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

移动物品

修改ItemGrid,按格子坐标获取物品

//按格子坐标获取物品
public Item PickUpItem(int x, int y){Item toReturn = itemSlot[x, y];itemSlot[x, y] = null;return toReturn;
}

新增InventoryController,实现物品交互功能

public class InventoryController : MonoBehaviour
{public ItemGrid selectedItemGrid;//操作的背包Item selectedItem;//选中物品private void Update(){if (selectedItemGrid == null) return;if (Input.GetMouseButtonDown(0)){// 获取当前鼠标位置在网格中的格子坐标,并打印到控制台Debug.Log(selectedItemGrid.GetTileGridPosition(Input.mousePosition));//获取物品Vector2Int tileGridPosition = selectedItemGrid.GetTileGridPosition(Input.mousePosition);if(selectedItem == null){selectedItem = selectedItemGrid.PickUpItem(tileGridPosition.x, tileGridPosition.y);}else{selectedItemGrid.PlaceItem(selectedItem, tileGridPosition.x, tileGridPosition.y);selectedItem = null;}}}
}

新增GridInteract,动态赋值背包数据

[RequireComponent(typeof(ItemGrid))]
public class GridInteract : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{private InventoryController inventoryController;private ItemGrid itemGrid;private void Awake(){inventoryController = FindObjectOfType<InventoryController>();itemGrid = GetComponent<ItemGrid>();}// 鼠标进入触发public void OnPointerEnter(PointerEventData eventData){inventoryController.selectedItemGrid = itemGrid;}// 鼠标退出触发public void OnPointerExit(PointerEventData eventData){inventoryController.selectedItemGrid = null;}
}

挂载
在这里插入图片描述
在这里插入图片描述
效果
在这里插入图片描述

物品跟随鼠标

修改InventoryController

private void Update()
{//物品跟随鼠标if(selectedItem) selectedItem.transform.position = Input.mousePosition;//...
}

效果
在这里插入图片描述

创建物品的容器,定义不同物品

新增ItemData

[CreateAssetMenu]
public class ItemData : ScriptableObject
{public int width = 1;public int height = 1;public Sprite itemIcon;
}

配置物品
在这里插入图片描述

修改Item

public class Item : MonoBehaviour
{public ItemData itemData;public void Set(ItemData itemData){this.itemData = itemData;GetComponent<Image>().sprite = itemData.itemIcon;}
}

修改InventoryController

[SerializeField] List<ItemData> items;
[SerializeField] GameObject itemPrefab;
Canvas canvas;private void Start() {canvas = FindObjectOfType<Canvas>();
}private void Update()
{//TODO: 方便测试,动态随机添加物品if (Input.GetKeyDown(KeyCode.Q)){CreateRandomItem();}//...
}//随机添加物品
private void CreateRandomItem()
{if (selectedItem) return;Item item = Instantiate(itemPrefab).GetComponent<Item>();selectedItem = item;selectedItem.transform.SetParent(canvas.transform, false);int index = UnityEngine.Random.Range(0, items.Count);item.Set(items[index]);
}

配置
在这里插入图片描述

效果,按Q生成不同物品
在这里插入图片描述

修改物品尺寸

修改Item

public void Set(ItemData itemData){this.itemData = itemData;GetComponent<Image>().sprite = itemData.itemIcon;//修改物品尺寸Vector2 size = new Vector2();size.x = itemData.width * ItemGrid.tileSizeWidth;size.y = itemData.height * ItemGrid.tileSizeHeight;GetComponent<RectTransform>().sizeDelta = size;
}

效果
在这里插入图片描述

修复物品放置位置问题

修改ItemGrid

//按格子坐标添加物品
public void PlaceItem(Item item, int posX, int posY){itemSlot[posX, posY] = item;item.transform.SetParent(transform, false);Vector2 positon = new Vector2();positon.x = posX * tileSizeWidth + tileSizeWidth * item.itemData.width / 2;positon.y = -(posY * tileSizeHeight + tileSizeHeight * item.itemData.height / 2);item.transform.localPosition = positon;
}

效果
在这里插入图片描述

按物品尺寸占用对应大小的格子

修改ItemGrid

//按格子坐标添加物品
public void PlaceItem(Item item, int posX, int posY)
{item.transform.SetParent(transform, false);// 按物品尺寸占用对应大小的格子for (int ix = 0; ix < item.itemData.width; ix++){for (int iy = 0; iy < item.itemData.height; iy++){itemSlot[posX + ix, posY + iy] = item;}}item.onGridPositionX = posX;item.onGridPositionY = posY;Vector2 positon = new Vector2();positon.x = posX * tileSizeWidth + tileSizeWidth * item.itemData.width / 2;positon.y = -(posY * tileSizeHeight + tileSizeHeight * item.itemData.height / 2);item.transform.localPosition = positon;
}//按格子坐标获取物品
public Item PickUpItem(int x, int y)
{Item toReturn = itemSlot[x, y];if(toReturn == null) return null;CleanGridReference(toReturn);return toReturn;
}//按物品尺寸取消对应大小的格子的占用
void CleanGridReference(Item item){for (int ix = 0; ix < item.itemData.width; ix++){for (int iy = 0; iy < item.itemData.height; iy++){itemSlot[item.onGridPositionX + ix, item.onGridPositionY + iy] = null;}}
}

运行看是否正常
在这里插入图片描述

判断物品是否超出边界范围

修改ItemGrid

//按格子坐标添加物品
public bool PlaceItem(Item item, int posX, int posY)
{//判断物品是否超出边界if (BoundryCheck(posX, posY, item.itemData.width, item.itemData.height) == false) return false;//...return true;
}//判断物品是否超出边界
bool BoundryCheck(int posX, int posY, int width, int height)
{if (PositionCheck(posX, posY) == false) return false;posX += width - 1;posY += height - 1;if (PositionCheck(posX, posY) == false) return false;return true;
}//判断格子坐标是否超出
bool PositionCheck(int posX, int posY)
{if (posX < 0 || posY < 0) return false;if (posX >= gridSizeWidth || posY >= gridSizeHeight) return false;return true;
}

修改InventoryController

private void Update()
{//...if (Input.GetMouseButtonDown(0)){Vector2Int tileGridPosition = selectedItemGrid.GetTileGridPosition(Input.mousePosition);if (selectedItem == null){//选中物品selectedItem = selectedItemGrid.PickUpItem(tileGridPosition.x, tileGridPosition.y);}else{// 移动物品PlaceItem(tileGridPosition);} }
}//移动物品
void PlaceItem(Vector2Int tileGridPosition){bool complete = selectedItemGrid.PlaceItem(selectedItem, tileGridPosition.x, tileGridPosition.y);if(complete) selectedItem = null;
}

效果

在这里插入图片描述

物品放置重叠,交换物品

修改InventoryController

Item overlapItem;//重叠物品//移动物品
void PlaceItem(Vector2Int tileGridPosition){bool complete = selectedItemGrid.PlaceItem(selectedItem, tileGridPosition.x, tileGridPosition.y, ref overlapItem);if(complete) {selectedItem = null;//如果存在重叠物品if(overlapItem != null) {selectedItem = overlapItem;overlapItem = null;}}
}

修改ItemGrid

//按格子坐标添加物品
public bool PlaceItem(Item item, int posX, int posY, ref Item overlapItem)
{//判断物品是否超出边界if (BoundryCheck(posX, posY, item.itemData.width, item.itemData.height) == false) return false;//检查指定位置和范围内是否存在重叠物品,有多个重叠物品退出if (OverlapCheck(posX, posY, item.itemData.width, item.itemData.height, ref overlapItem) == false) return false;if(overlapItem) CleanGridReference(overlapItem);//...
}//检查指定位置和范围内是否存在重叠物品,并overlapItem返回重叠物品,,有多个重叠物品返回false
private bool OverlapCheck(int posX, int posY, int width, int height, ref Item overlapItem)
{for (int x = 0; x < width; x++){for (int y = 0; y < height; y++){// 如果当前位置有物品if (itemSlot[posX + x, posY + y] != null){// 如果 overlapItem 还未被赋值(第一次找到重叠物品)if (overlapItem == null){overlapItem = itemSlot[posX + x, posY + y];}else{// 如果发现范围有多个重叠物品if (overlapItem != itemSlot[posX + x, posY + y]){overlapItem = null;return false;}}}}}// 如果所有被检查的位置都有相同的重叠物品,则返回 truereturn true;
}

效果
在这里插入图片描述

放置加入点偏移量

修改InventoryController放置时加入点偏移量,让放置效果更好

private void Update()
{//TODO: 方便测试,动态随机添加物品if (Input.GetKeyDown(KeyCode.Q)){CreateRandomItem();}//物品跟随鼠标if (selectedItem) selectedItem.transform.position = Input.mousePosition;if (selectedItemGrid == null) return;if (Input.GetMouseButtonDown(0)){LeftMouseButtonPress();}
}//点击操作
private void LeftMouseButtonPress()
{Vector2 position = Input.mousePosition;if (selectedItem != null){position.x -= (selectedItem.itemData.width - 1) * ItemGrid.tileSizeWidth / 2;position.y += (selectedItem.itemData.height - 1) * ItemGrid.tileSizeHeight / 2;}Vector2Int tileGridPosition = selectedItemGrid.GetTileGridPosition(position);if (selectedItem == null){//选中物品selectedItem = selectedItemGrid.PickUpItem(tileGridPosition.x, tileGridPosition.y);}else{// 移动物品PlaceItem(tileGridPosition);}
}

效果
在这里插入图片描述

突出显示我们选中的物品

修改ItemGrid

//按格子坐标转化为UI坐标位置
public Vector2 CalculatePositionOnGrid(Item item, int posX, int posY)
{Vector2 position = new Vector2();position.x = posX * tileSizeWidth + tileSizeWidth * item.itemData.width / 2;position.y = -(posY * tileSizeHeight + tileSizeHeight * item.itemData.height / 2);return position;
}//按格子坐标获取物品
internal Item GetItem(int x, int y)
{return itemSlot[x, y];
}

新增InventoryHighlight,控制高亮背景显示

//控制高亮背景显示
public class InventoryHighlight : MonoBehaviour
{[SerializeField] RectTransform highlighter;// 设置高亮框大小public void SetSize(Item targetItem){Vector2 size = new Vector2();size.x = targetItem.itemData.width * ItemGrid.tileSizeWidth;size.y = targetItem.itemData.height * ItemGrid.tileSizeHeight;highlighter.sizeDelta = size;}// 设置高亮框位置public void SetPosition(ItemGrid targetGrid, Item targetItem){Vector2 pos = targetGrid.CalculatePositionOnGrid(targetItem, targetItem.onGridPositionX, targetItem.onGridPositionY);highlighter.localPosition = pos;}//显示隐藏public void Show(bool b){highlighter.gameObject.SetActive(b);        }//设置高亮背景父级public void SetParent(ItemGrid targetGrid){highlighter.SetParent(targetGrid.GetComponent<RectTransform>());}//设置高亮框位置public void SetPosition(ItemGrid targetGrid, Item targetItem, int posX, int posY){Vector2 pos = targetGrid.CalculatePositionOnGrid(targetItem, posX, posY);highlighter.localPosition = pos;}}

修改InventoryController

InventoryHighlight inventoryHighlight;
Item itemToHighlight;//高亮显示物品private void Start()
{canvas = FindObjectOfType<Canvas>();inventoryHighlight = GetComponent<InventoryHighlight>();
}private void Update()
{//TODO: 方便测试,动态随机添加物品if (Input.GetKeyDown(KeyCode.Q)){CreateRandomItem();}//物品跟随鼠标if (selectedItem) selectedItem.transform.position = Input.mousePosition;if (selectedItemGrid == null){inventoryHighlight.Show(false);return;}if (Input.GetMouseButtonDown(0)){// 获取当前鼠标位置在网格中的格子坐标,并打印到控制台Debug.Log(selectedItemGrid.GetTileGridPosition(Input.mousePosition));LeftMouseButtonPress();}//高亮显示HandleHighlight();
}//点击操作,选中物品
private void LeftMouseButtonPress()
{Vector2Int tileGridPosition = GetTileGridPosition();if (selectedItem == null){//选中物品selectedItem = selectedItemGrid.PickUpItem(tileGridPosition.x, tileGridPosition.y);}else{// 移动物品PlaceItem(tileGridPosition);}
}//鼠标坐标转化为格子坐标
private Vector2Int GetTileGridPosition()
{Vector2 position = Input.mousePosition;if (selectedItem != null){position.x -= (selectedItem.itemData.width - 1) * ItemGrid.tileSizeWidth / 2;position.y += (selectedItem.itemData.height - 1) * ItemGrid.tileSizeHeight / 2;}Vector2Int tileGridPosition = selectedItemGrid.GetTileGridPosition(position);return tileGridPosition;
}//高亮显示
private void HandleHighlight()
{Vector2Int positionOnGrid = GetTileGridPosition();if (selectedItem == null){itemToHighlight = selectedItemGrid.GetItem(positionOnGrid.x, positionOnGrid.y);if (itemToHighlight != null){inventoryHighlight.Show(true);inventoryHighlight.SetSize(itemToHighlight);inventoryHighlight.SetParent(selectedItemGrid);inventoryHighlight.SetPosition(selectedItemGrid, itemToHighlight);}else{inventoryHighlight.Show(false);}}else{inventoryHighlight.Show(selectedItemGrid.BoundryCheck(positionOnGrid.x,positionOnGrid.y,selectedItem.itemData.width,selectedItem.itemData.height));//防止显示跨界inventoryHighlight.SetSize(selectedItem);inventoryHighlight.SetParent(selectedItemGrid);inventoryHighlight.SetPosition(selectedItemGrid, selectedItem, positionOnGrid.x, positionOnGrid.y);}
}

新增高亮背景
在这里插入图片描述
挂载配置
在这里插入图片描述
效果
在这里插入图片描述

优化

修改InventoryController,节约不必要的计算

Vector2Int oldPosition;//高亮显示
private void HandleHighlight()
{Vector2Int positionOnGrid = GetTileGridPosition();//节约没必要的计算if(oldPosition == positionOnGrid) return;oldPosition = positionOnGrid;//...
}

最好为光线投射添加一些填充,Raycast Padding区域
参考:Unity 显示Raycast Padding区域
在这里插入图片描述

多个背包

只要复制背包,修改尺寸即可
在这里插入图片描述
效果
在这里插入图片描述

自动入库物品

修改ItemGrid

//按格子坐标添加物品
public bool PlaceItem(Item item, int posX, int posY, ref Item overlapItem)
{//判断物品是否超出边界if (BoundryCheck(posX, posY, item.itemData.width, item.itemData.height) == false) return false;//检查指定位置和范围内是否存在重叠物品,有多个重叠物品退出if (OverlapCheck(posX, posY, item.itemData.width, item.itemData.height, ref overlapItem) == false) return false;if (overlapItem) CleanGridReference(overlapItem);PlaceItem(item, posX, posY);return true;
}//按格子坐标添加物品
public void PlaceItem(Item item, int posX, int posY)
{item.transform.SetParent(transform, false);// 按物品尺寸占用对应大小的格子for (int ix = 0; ix < item.itemData.width; ix++){for (int iy = 0; iy < item.itemData.height; iy++){itemSlot[posX + ix, posY + iy] = item;}}item.onGridPositionX = posX;item.onGridPositionY = posY;Vector2 position = CalculatePositionOnGrid(item, posX, posY);item.transform.localPosition = position;
}// 检查指定位置是否有足够的空间来放置物品
private bool CheckAvailableSpace(int posX, int posY, int width, int height)
{for (int x = 0; x < width; x++){for (int y = 0; y < height; y++){if (itemSlot[posX + x, posY + y] != null){return false; // 如果当前位置已经有物品,则返回false}}}return true; // 如果所有位置都空闲,则返回true
}// 在网格中找到适合放置物品的位置Data
public Vector2Int? FindSpaceForObject(ItemData itemData)
{int height = gridSizeHeight - itemData.height + 1;int width = gridSizeWidth - itemData.width + 1;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){if (CheckAvailableSpace(x, y, itemData.width, itemData.height) == true){return new Vector2Int(x, y); // 返回找到的空闲位置}}}return null; // 如果没有找到合适的位置,则返回null
}

修改InventoryController

//TODO:方便测试,随机入库物品
if (Input.GetKeyDown(KeyCode.W))
{InsertRandomItem();
}//随机入库物品
private void InsertRandomItem()
{if(selectedItemGrid == null) return;int index = UnityEngine.Random.Range(0, items.Count);// 在网格中找到适合放置物品的位置Vector2Int? posOnGrid = selectedItemGrid.FindSpaceForObject(items[index]);if (posOnGrid == null) return;Item item = Instantiate(itemPrefab).GetComponent<Item>();item.transform.SetParent(canvas.transform, false);item.Set(items[index]);// 将物品放置到网格中的指定位置selectedItemGrid.PlaceItem(item, posOnGrid.Value.x, posOnGrid.Value.y);
}

效果
在这里插入图片描述

旋转物品

修改Item

public bool rotated = false;//旋转物品
public void Rotate()
{rotated = !rotated;transform.rotation = Quaternion.Euler(0, 0, rotated == true ? 90f : 0f);
}

修改InventoryController

//旋转物品
if (Input.GetKeyDown(KeyCode.R))
{RotateItem();
}//旋转物品
void RotateItem(){if (selectedItem == null) return;selectedItem.Rotate();
}

效果
在这里插入图片描述

修改旋转高亮背景和占位也跟着旋转

修改Item

public int WIDTH{get{if(rotated == false){return itemData.width;}return itemData.height;}
}public int HEIGHT{get{if(rotated == false){return itemData.height;}return itemData.width;}
}

然后修改InventoryController、ItemGrid和InventoryHighlight把
item.itemData.width改为 item.WIDTH
item.itemData.height改为item.HEIGHT

给大家提供一个技巧,可以先修改ItemData宽高注释,这时代码会报错,对应修改位置即可,然后再还原回去
在这里插入图片描述
效果
在这里插入图片描述

选中拖拽物品排序问题

修改InventoryController,大概就是添加selectedItem.transform.SetAsLastSibling();保证选中对象排最后,及排序最靠前

//点击操作,选中物品
private void LeftMouseButtonPress()
{Vector2Int tileGridPosition = GetTileGridPosition();if (selectedItem == null){//选中物品selectedItem = selectedItemGrid.PickUpItem(tileGridPosition.x, tileGridPosition.y);selectedItem.transform.SetAsLastSibling();}else{// 移动物品PlaceItem(tileGridPosition);}
}//移动物品
void PlaceItem(Vector2Int tileGridPosition)
{bool complete = selectedItemGrid.PlaceItem(selectedItem, tileGridPosition.x, tileGridPosition.y, ref overlapItem);if (complete){selectedItem = null;//如果存在重叠物品if (overlapItem != null){selectedItem = overlapItem;overlapItem = null;selectedItem.transform.SetAsLastSibling();}}
}//随机添加物品
private void CreateRandomItem()
{if (selectedItem) return; Item item = Instantiate(itemPrefab).GetComponent<Item>();selectedItem = item;selectedItem.transform.SetParent(canvas.transform, false);selectedItem.transform.SetAsLastSibling();int index = UnityEngine.Random.Range(0, items.Count);item.Set(items[index]);
}

效果

在这里插入图片描述

最终效果

在这里插入图片描述

源码

整理好了我会放上来

完结

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

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

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

深度解析:机器学习如何助力GPT-5实现语言理解的飞跃

文章目录 文章前言机器学习在GPT-5中的具体应用模型训练与优化机器翻译与跨语言交流&#xff1a;情感分析与问答系统&#xff1a;集成机器学习功能&#xff1a;文本生成语言理解任务适应 机器学习对GPT-5性能的影响存在的挑战及解决方案技术细节与示例 文章前言 GPT-5是OpenAI公…

24/06/26(1.1129)动态内存

strtok 字符串分割函数 #include<stdio.h> int main(){ char str[] "this,a sample string."; char* sep ","; char* pch strtok(str, sep); printf("%s\n", pch); while (pch ! NULL){ printf("%s\…

惊天大瓜姬圈天莱女明星出轨风波

#惊天大瓜&#xff01;姬圈天菜女明星出轨风波#近日&#xff0c;娱乐圈掀起了一场前所未有的风暴&#xff01;狗仔队放出重磅消息&#xff0c;直指某位姬圈天菜级别的女明星深陷出轨泥潭。消息一出&#xff0c;引发了网友们的热议和猜测&#xff0c;究竟这位神秘的女明星是谁&a…

各式各样神奇的注意力机制变型

当输入sequence N很大的时候&#xff0c;这个时候self-attention 占据了绝大部分算力 Local Attention / Truncated Attention 只需要关注附近的attention, local attention 和cnn 差不多&#xff0c;可以加速计算&#xff0c;但效果不一定好 Stride attention 空几格attenti…

[保姆级教程]uniapp自定义标签页切换组件

文章目录 导文样式改成动态列表切换点击效果加上点击自动滑动scroll-view加上切换组件效果 导文 unaipp自带的标签页和ui设计相差太大&#xff0c;直接修改组件比手写一个还麻烦&#xff0c;下面手写一个。 样式 先用scroll-view做一个滑动&#xff0c;不然多的话滑动不了。 &l…

神经网络学习8-反向传播

back propagation 拿到前面传回来的L对z的偏导&#xff0c;再分别算损失值对x和w的偏导 反向传播 前馈过程求局部梯度 反向传播 这里的loss&#xff08;wxb-y)^2,第一个关于b的偏导为2(wxb-y),第二个关于w的为2w(wxb-y)

【机器学习300问】128、简述什么Word2Vec?

一、一句话说明Word2Vec是什么&#xff1f; Word2Vec是一种常见的词嵌入技术。Word2Vec的目标是将每个词表示为一个向量&#xff0c;使得这些向量能够反映出词语之间的相似性和关联性。 word2vec算法通过预测中心词和上下文词的共现概率来学习词向量&#xff0c;能够捕捉词语之…

植物大战僵尸杂交版v2.1最新直装版,苹果+安卓+PC+防闪退工具+修改工具+高清工具+通关存档整合包更新

今天我要和各位聊聊一款让全网疯狂的游戏——《植物大战僵尸杂交版》。这可不是简单的游戏&#xff0c;它可是让B站的UP主“潜艇伟伟迷”一夜成名的大作&#xff0c;让无数玩家为之疯狂的魔改神作&#xff01; 记得2009年&#xff0c;《植物大战僵尸》横空出世&#xff0c;那时…

LDO芯片手册,实例应用分析

在进行电路设计时LDO是经常用到的&#xff0c;尤其在为芯片&#xff0c;晶振等敏感电路进行供电时应用更多&#xff0c;下面选取一款比较常用的LDO芯片&#xff0c;一起进行更深入的学习。 SGM2036特点简介 SGM2036&#xff0c;圣邦微一款比较常用的LDO芯片手册 可以先大致看…

【ajax实战04】数据管理平台——富文本编辑器

一&#xff1a;富文本编辑器简介 富文本&#xff1a;带样式&#xff0c;多格式的文本&#xff0c;在前端一般使用标签配合内联样式实现。 富文本编辑器&#xff1a;用于编写富文本内容的容器 二&#xff1a;wangEditor插件 https://www.wangeditor.com/ 对于将富文本编辑器…

CAN通信协议

文章目录 STM32-CAN1. CAN基础知识2. CAN协议2.1. CAN协议与ISO/OSI基本参照模型的关系2.2. CAN协议及标准规格2.3. CAN协议2.3.1. 帧的种类2.3.2. 数据帧2.3.3. 遥控帧2.3.4. 错误帧2.3.5. 过载帧2.3.6. 间隔帧 2.4. 优先级的决定2.5. 位填充2.6. 错误的种类2.7. 位时序 3. CA…

鸿蒙系统最简单安装谷歌服务及软件的方法

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 近日&#xff0c;华为开发者大会在东莞松山湖召开&#xff0c;发布了盘古大模型5.0和纯血版的鸿蒙 HarmonyOS NEXT 全场景智能操作系统&#xff0c;而根据研究机构 Counterpoint Resea…

ITSG、COST-G、Tongji和WHU Level-2数据产品读取绘图(Matlab)

数据介绍&#xff1a; ICGEM International Center for Global Gravity Field Models (gfz-potsdam.de) ITSG 2018&#xff1a;Institute of Geodesy at Graz University of Technolog&#xff08;格拉茨理工大学大地测量研究所&#xff09; 2018版本&#xff0c;最高60阶球谐…

Java导出excel合并行功能

导出的excel需要上下行相同的数据进行行合并的功能。如图显示 这里我使用的是项目框架自带的导出模板代码&#xff0c;是在这套模板基础之上做的修改。 // 我主要演示的就是mergeRows方法的操作&#xff0c;dataList是导出数据的集合。 workbook ExcelTools.expData(workbook…

大厂面试官问我:Redis中热key和大key是怎么解决的?【后端八股文五:Redis热key和大key八股文合集】

往期内容&#xff1a; 大厂面试官问我&#xff1a;Redis处理点赞&#xff0c;如果瞬时涌入大量用户点赞&#xff08;千万级&#xff09;&#xff0c;应当如何进行处理&#xff1f;【后端八股文一&#xff1a;Redis点赞八股文合集】-CSDN博客 大厂面试官问我&#xff1a;布隆过滤…

振兴黄河新生力 打造文旅新地标——全国首家黄河会客厅在山东济南启幕

6月26日&#xff0c;由黄河文化发展工作站组织实施的全国首家黄河会客厅平台发布会暨山东基地启动仪式在济南成功召开。黄河会客厅以“民生黄河、生态动能、中华文明”为核心主题&#xff0c;融汇黄河智库、黄河文明、黄河产域、黄河金融、黄河科创、黄河物贸六大振兴赋能体系&…

计算机视觉:项目实战

目录 SSD1.安装ananconda2.安装cuda和cudnn3.配置Pytorch环境3.1 pytorch环境的配置与激活3.2 pytorch库的安装3.3 其它依赖库的安装 遇到的问题&#xff1a;1.EOFError: Ran out of input.2.No module named dlib. SSD 1.安装ananconda 见另一篇博文&#xff1a;https://blo…

OpenAI API一键搬家,天工推出开发者迁移计划

6月25日&#xff0c;OpenAI宣布称将于今年7月9日开始封锁来自非支持国家和地区的API流量。此后&#xff0c;来自中国大陆、中国香港等地的开发者将无法使用OpenAI API提供服务。 为了助力开发者高效切换至国内大模型&#xff0c;天工开放平台&#xff08;https://model-platfo…

电脑突然提示dll文件丢失,怎么选择正确的恢复方法?

电脑突然提示dll文件丢失&#xff1f;其实当你的电脑使用久了&#xff0c;出现这种dll文件丢失是非常的正常的&#xff0c;毕竟你总会有不恰当的操作吧&#xff1f;这些操作都是会导致dll文件丢失的。丢失了&#xff0c;我们直接进行相关的修复就好了&#xff0c;还是比较简单的…

# linux 系统中,使用 “ ll “ 命令报错 “ bash ll command not found “ 解决方法:

linux 系统中&#xff0c;使用 " ll " 命令报错 " bash ll command not found " 解决方法&#xff1a; 一、错误描述&#xff1a; 报错原因&#xff1a; 1、这个错误表明你尝试在 bash shell 中执行 ll 命令&#xff0c;但是系统找不到这个命令。ll 通常…