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

news2024/10/9 14:19:28

最终效果

在这里插入图片描述

文章目录

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

前言

在这一集中我将使用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;
                    }
                }
            }
        }
    }
    // 如果所有被检查的位置都有相同的重叠物品,则返回 true
    return 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.coloradmin.cn/o/1863256.html

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

相关文章

全景图片/老照片/动漫图片一键无损放大与修复

在日常生活中&#xff0c;我们经常使用系统自带的图片处理软件来对图片进行缩放操作&#xff0c;从而实现放大或缩小图片。然而&#xff0c;这种方法会带来一个问题&#xff1a;如果原始图片较小&#xff0c;放大后会导致精度损失&#xff0c;使图片变得模糊。 近年来&#xf…

SD-WAN带宽对使用的影响及如何规划

SD-WAN&#xff08;软件定义广域网&#xff09;是一种创新技术&#xff0c;旨在优化和提升企业网络的性能、可靠性和安全性。带宽在SD-WAN的使用中起着关键作用&#xff0c;而确定SD-WAN专线所需的带宽大小需要综合考虑多个因素。本文将深入探讨SD-WAN带宽对使用的影响以及如何…

革新城市景观:轻空间设计团队呈现“淄博会展中心”

“淄博会展中心”&#xff0c;作为国内最大的气膜会展建筑群&#xff0c;自启用以来已经成为淄博市的亮丽新名片和经济引擎。该会展中心在第二十届中国&#xff08;淄博&#xff09;国际陶瓷博览会上首次亮相&#xff0c;其独特的设计和先进的建筑理念吸引了广泛关注。今天&…

xxl-job 分布式任务调度 基本使用

xxl-job 是一个分布式任务调度平台&#xff0c;使用非常方便。 官网&#xff1a;https://gitee.com/xuxueli0323/xxl-job 工作原理类似于nacos 执行器注册到调度中心 调度中心分配任务 执行器执行任务 docker-compose 配置 version: 3 services:xxl-job:image: xuxueli/xxl-…

【神经网络】深入理解多层神经网络(深度神经网络

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&#xff01; 深入理解多层神经网络&#x…

【C++题解】1712. 输出满足条件的整数2

问题&#xff1a;1712. 输出满足条件的整数2 类型&#xff1a;简单循环 题目描述&#xff1a; 有这样的三位数&#xff0c;其百位、十位、个位的数字之和为偶数&#xff0c;且百位大于十位&#xff0c;十位大于个位&#xff0c;请输出满所有满足条件的整数。 输入&#xff1…

博客solo!bolo-solo让博客创作更自由。

bolo-solo&#xff1a;独行侠的数字笔录&#xff0c; 你的博客新伙伴- 精选真开源&#xff0c;释放新价值。 概览 bolo-solo是GitHub 上一个开源的个人博客系统&#xff1a;Bolo Solo&#xff0c;简单易部署&#xff0c;自带精致主题、数据统计表、邮件提醒、自定义图床、功能…

利用Linked SQL Server提权

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 利用Linked SQL Server提权 Linked SQL server是一个SQL Server数据库中的对象&#xff0c;它可以连接到另一个SQL Server或非SQL Server数据源&#xff08;如Oracle&a…

规则引擎-Aviator 表达式校验是否成立

目录 介绍特性使用更多文献支持 介绍 Aviator是一个轻量级、高性能的Java表达式执行引擎&#xff0c;它动态地将表达式编译成字节码并运行。 特性 支持绝大多数运算操作符&#xff0c;包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(~)、三元表达式(?:…

Java学习十一—Java8特性之Stream流

一、Java8新特性简介 2014年3月18日&#xff0c;JDK8发布&#xff0c;提供了Lambda表达式支持、内置Nashorn JavaScript引擎支持、新的时间日期API、彻底移除HotSpot永久代。 ​ Java 8引入了许多令人兴奋的新特性&#xff0c;其中最引人注目的是Lambda表达式和Stream API。以…

【redis】redis概述

1、定义 Redis&#xff08;Remote Dictionary Server&#xff09;&#xff0c;即远程字典服务&#xff0c;是一个开源的、内存中的数据结构存储系统。redis是一个key-value存储系统。和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)…

电脑开机启动项在哪里设置?3个方法教你轻松找到!

“有朋友知道电脑开机启动项在哪里设置吗&#xff1f;我想在里面结束一些程序&#xff0c;但是不知道怎么找到这个功能&#xff0c;请大家帮帮我&#xff01;” 电脑开机启动项的设置对于优化系统启动速度、管理后台运行程序具有重要意义。通过合理配置启动项&#xff0c;我们可…

《Windows API每日一练》6.2 客户区鼠标消息

第五章已经讲到&#xff0c;Windows只会把键盘消息发送到当前具有输入焦点的窗口。鼠标消息则不同&#xff1a;当鼠标经过窗口或在窗口内被单击&#xff0c;则即使该窗口是非活动窗口或不带输入焦点&#xff0c; 窗口过程还是会收到鼠标消息。Windows定义了 21种鼠标消息。不过…

github无法访问,下载慢的解决方法

GitHub是一个存储分享无数的开源项目和代码的宝库网站。然而&#xff0c;由于一些原因&#xff0c;国内用户在访问GitHub时常常遭遇无法访问或下载速度缓慢的问题。这不仅影响了开发者的工作效率&#xff0c;也使一些想要访问下载github文件的普通用户遇到困难。下面小编就来和…

什么是CMSIS || 标准库与HAL库

一&#xff0c;ARM&#xff08;Cortex Microcontroller Software Interface Standard&#xff09; ARM Cortex™ 微控制器软件接口标准&#xff08;Cortex Microcontroller Software Interface Standard&#xff09;是 CortexM 处理器系列的与供应商无关的硬件抽象层。…

Access Levels in Swift

Access Levels (访问级别) Swift provides six different access levels for entities(实体) within your code. These access levels are relative to the source file in which an entity is defined, the module(模块) that source file belongs to, and the package that …

hive架构详解:HQL案例解析(第15天)

系列文章目录 一、Hive基础架构&#xff08;重点&#xff09; 二、Hive数据库,表操作&#xff08;重点&#xff09; 三、Hadoop架构详解(hdfs)&#xff08;补充&#xff09; 四、Hive环境准备&#xff08;操作&#xff09;(补充) 文章目录 系列文章目录前言一、Hive基础架构1、…

【Excel】单元格如何设置可选项、固定表头

设置可选项 固定表头&#xff1a;视图---冻结窗口

Python | Leetcode Python题解之第198题打家劫舍

题目&#xff1a; 题解&#xff1a; class Solution:def rob(self, nums: List[int]) -> int:if not nums:return 0size len(nums)if size 1:return nums[0]first, second nums[0], max(nums[0], nums[1])for i in range(2, size):first, second second, max(first nu…

wps的domain转为shp矢量

wps的namelist制作、python出图和转矢量 简介 wps&#xff08;WRF Preprocessing System&#xff09;是中尺度数值天气预报系统WRF(Weather Research and Forecasting)的预处理系统。 wps的安装地址在GitHub上&#xff1a;https://github.com/wrf-model/WPS 下载完成后&…