unity拖拽背包物体,并交换两个物体的信息

这篇具有很好参考价值的文章主要介绍了unity拖拽背包物体,并交换两个物体的信息。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前几天看了一个教程,背包物品交换。由于教程中使用的是ngui,很多代码需要使用UGUI重新写,因此苦恼了几天。

我遇到了以下问题,在此详细罗列,以记录错误的原因和修改的方法,供日后阅读查找。

一、背包中的物品在拖拽之后放入指定的空格子(问题1:不知道该怎么获得指定的空格子;问题3:更新格子内的物品信息时找不到该物品);
二、背包中的物品在拖拽之后放入原来的格子(问题2:少了两行代码);
三、背包中的物品在拖拽之后,与另一个物品交换位置,并将自身信息更新在新的格子中(问题3:更新格子内的物品信息时找不到该物品;问题4:被交换的物体还在原来的位置待着)。

解决这些问题所参考的资料(原创者:不在同一频道上的呆子)

交换背包格子中的物体

要实现的功能是:
1.在开始拖拽时,保证被拖拽的UI对象(以下称该对象为A)始终显示在其他UI的上方;
2.在拖拽时,保证A在屏幕中始终在鼠标的位置处;
3.拖拽结束,释放鼠标之后,A存放在目标格子中(即,把目标格子设置为A的父物体)。分为三种情况:(1)如果目标格子中没有物体且不是A的原位置,则直接放入;(2)如果目标格子是原位置,则视觉上不做更改;(3)如果目标格子中有物品B,则A与B交换位置,并交换父物体。

unity拖放UI对象需要引入命名空间和接口:

using UnityEngine.EventSystems;
public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler,IPointerEnterHandler,IPointerExitHandler

主要实现以下三个接口,实现方法分别是:

    public void OnBeginDrag(PointerEventData eventData) { }
    public void OnDrag(PointerEventData eventData) { }
    public void OnEndDrag(PointerEventData eventData) { }

问题1:不知道该怎么获得指定的空格子:
解决方法:让被拖拽的物体屏蔽射线检测,这样就能获得鼠标悬停下的UI对象

transform.GetComponent<Image>().raycastTarget = false;

问题2:将A放入原格子:

//nowParent是A被拖拽前的父物体
 transform.SetParent(nowParent);
 transform.localPosition = Vector3.zero;

问题:4:被交换的物体还在原来的位置待着
这是因为将被拖拽的物体A的位置重新设置,但是没有将被交换的物品B的位置重新设置。只需要加上一行语句即可:

Transform tmpItem = dropTarget.transform;

tmpItem.localPosition = Vector3.zero;

交换物品后更新格子内的物品信息

要实现的功能是:
在交换完成后,相应的背包格子内部关于物品的信息也要进行更新。

问题3:更新格子内的物品信息时找不到该物品

这是因为在调用另一个脚本时,一个临时变量为空导致的。在拖拽A时,A的原来的父物体找不到A,导致报空指针,因而出错。为了解决这个问题,需要将A的父亲进行更新(如果与B交换,则B的父亲需要同时更新)

dropTarget.transform.SetParent(nowParent);

完整的脚本如下:

unity拖拽背包物体,并交换两个物体的信息,问题记录,unity,游戏引擎,bug
InventoryItemGrid是背包的物品格子,InventoryItemCount是记录该格子中的物品数量。InventoryItem(Clone)是背包内的物品。

InventoryItem脚本挂载在每一个背包物品上面:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 管理背包格子内的物品
/// </summary>
public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler,IPointerEnterHandler,IPointerExitHandler
{
    public Image sprite;
    /// <summary>
    /// 物品id
    /// </summary>
    private int itemId;
    /// <summary>
    /// 鼠标指针是否悬浮于物品上方
    /// </summary>
    private bool isHover = false;

    /// <summary>
    /// 图标的RectTransform组件
    /// </summary>
    private RectTransform rectTransform;
    /// <summary>
    /// Canvas组件,用于确定拖拽的缩放因子
    /// </summary>
    private Canvas canvas;

    /// <summary>
    /// 物体的目前父物体
    /// </summary>
    private Transform nowParent;
    
    private void Start()
    {
        rectTransform = GetComponent<RectTransform>(); // 获取图标的RectTransform组件
        canvas = GetComponentInParent<Canvas>(); // 获取父级Canvas组件

        //originalPosition = rectTransform.anchoredPosition; // 记录图标的初始位置
    }

    private void Update()
    {
        if (isHover)
        {
            if (Input.GetMouseButtonDown(1))
            {
                bool success = EquipmentPanel._instance.Dress(itemId);
                if (success)
                {
                    transform.parent.GetComponent<InventoryItemGrid>().MinusNumber();
                }
            }
        }
    }

    public void SetId(int id)
    {
        ObjectInfo info = ObjectsInfo._instance.GetObjectInfoById(id);

        //更新显示
        sprite.name = info.iconName;
    }

    public void SetIconName(int id, string iconName)
    {
        sprite.sprite = Resources.Load<Sprite>(Path.itemPath+iconName);
        itemId = id;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (transform.GetComponent<Image>().raycastTarget)
        {
            //让被拖拽的物体屏蔽射线检测,这样就能获得鼠标悬停下的UI对象
            transform.GetComponent<Image>().raycastTarget = false;
        }
        nowParent = transform.parent;  //nowparent为被拖拽物体的当前父物体        

        transform.SetParent(canvas.transform);//将当前拖拽的物体放在canvas下
    }

    public void OnDrag(PointerEventData eventData)
    {
        rectTransform.anchoredPosition += eventData.delta / canvas.scaleFactor; // 根据鼠标移动更新图标位置
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //用于存放鼠标当前悬停位置下的物体
        GameObject dropTarget = eventData.pointerCurrentRaycast.gameObject;

        if (dropTarget != null)
        {
            if (dropTarget.CompareTag(S_Tags.inventoryItemGrid)) // 当拖放到了一个空的格子里面
            {
                if (dropTarget.transform == nowParent)
                {
                    transform.SetParent(nowParent);
                }
                else
                {
                    // 处理拖拽到空格子的逻辑
                    InventoryItemGrid oldSlot = nowParent.GetComponent<InventoryItemGrid>();
                    transform.SetParent(dropTarget.transform);
                    ResetLocalPosition();
                    InventoryItemGrid newSlot = dropTarget.GetComponent<InventoryItemGrid>();
                    //int oldId = oldSlot.itemId;
                    //int oldCount = oldSlot.itemCount;
                    newSlot.SetId(oldSlot.itemId, oldSlot.itemCount);
                    oldSlot.CleanInfo();
                }
            }
            else if (dropTarget.CompareTag(S_Tags.inventoryItem)) // 当拖放到了一个有物品的格子里面
            {
                // 处理拖拽到有物品的格子里面的逻辑
                InventoryItemGrid slot1 = nowParent.GetComponent<InventoryItemGrid>();
                InventoryItemGrid slot2 = dropTarget.transform.parent.GetComponent<InventoryItemGrid>();

                Transform tmpItem = dropTarget.transform;
                Transform tmpParent = dropTarget.transform.parent;

                //交换父亲
                //将被拖拽的物体的父亲更新为当前指针悬停位置物品的父亲
                transform.SetParent(tmpParent);
                //将指针悬停位置物品的父亲更新为被拖拽物品的原父亲
                dropTarget.transform.SetParent(nowParent);

                int id = slot1.itemId;
                int num = slot1.itemCount;
                slot1.SetId(slot2.itemId, slot2.itemCount);
                slot2.SetId(id, num);
                tmpItem.localPosition = Vector3.zero;
            }
            else
            {
                transform.SetParent(nowParent);
            }
        }
        else
        {
            transform.SetParent(nowParent);
        }
        transform.GetComponent<Image>().raycastTarget = true;

        ResetLocalPosition();
    }
    /// <summary>
    /// 被拖拽物体返回原位置
    /// </summary>
    private void ResetLocalPosition()
    {
        transform.localPosition = Vector3.zero;
        transform.SetAsFirstSibling();
    }

    /// <summary>
    /// 鼠标指针进入时
    /// </summary>
    /// <param name="eventData"></param>
    public void OnPointerEnter(PointerEventData eventData)
    {
        InventoryDes._instance.ShowDes(itemId);
        isHover = true;
    }

    /// <summary>
    /// 鼠标指针退出时
    /// </summary>
    /// <param name="eventData"></param>
    public void OnPointerExit(PointerEventData eventData)
    {
        InventoryDes._instance.HideDes();
        isHover = false;
    }
}

InventoryItemGrid 挂载在每一个背包格子上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 管理背包格子
/// </summary>
public class InventoryItemGrid : MonoBehaviour
{
    /// <summary>
    /// 表示当前背包格子里面存储了什么物品.默认为0,表示当前背包格子中什么也没有
    /// </summary>
    public int itemId = 0;
    /// <summary>
    /// 表示当前背包格子中的物品的数量。默认为0.
    /// </summary>
    public int itemCount = 0;
    /// <summary>
    /// 当前背包格子中的物品的信息
    /// </summary>
    private ObjectInfo info = null;
    
    private Text txt_itemCount;

    private void Start()
    {
        txt_itemCount = transform.Find("InventoryItemCount").GetComponent<Text>();
    }
    /// <summary>
    /// 当背包格子中的物品发生变化时(包括类型、图标、数量等),就更新背包格子中关于物品的显示。
    /// </summary>
    /// <param name="id">物品的属性:id</param>
    /// <param name="num">物品的数量,默认为1</param>
    public void SetId(int id, int num = 1)
    {
        itemId = id;
        //先得到物品信息
        info = ObjectsInfo._instance.GetObjectInfoById(id);
        //更新背包格子中的显示
        InventoryItem item = GetComponentInChildren<InventoryItem>();
        //用于检测是哪个格子失去了子物体
        if (item == null)
        {
            print(transform.name);
        }
        item.SetIconName(id, info.iconName);//info.iconName是从txt文件中解析得来的

        txt_itemCount.gameObject.SetActive(true);
        itemCount = num;
        txt_itemCount.text = itemCount.ToString();
        txt_itemCount.gameObject.transform.SetAsLastSibling();
    }

    /// <summary>
    /// 背包格子中的物体数目增加,相应的显示数字也应当变化
    /// </summary>
    /// <param name="num">物品增加的数量</param>
    public void PlusNumber(int num = 1)
    {
        itemCount += num;
        txt_itemCount.text = itemCount.ToString();
    }

    /// <summary>
    /// 用于减去背包中物品的数量
    /// </summary>
    /// <param name="num"></param>
    /// <return>是否减量成功</return>
    public bool MinusNumber(int num = 1)
    {
        if (itemCount >= num)
        {
            itemCount -= num;
            txt_itemCount.text = itemCount.ToString();
            if (itemCount == 0)
            {
                //清空物品格子
                CleanInfo();
                //销毁物品
                Destroy(GetComponentInChildren<InventoryItem>().gameObject);
            }
            return true;
        }
        return false;
    }

    /// <summary>
    /// 清空背包格子中的物品信息
    /// </summary>
    public void CleanInfo()
    {
        itemId = 0;
        info = null;
        itemCount = 0;
        txt_itemCount.gameObject.SetActive(false);
    }
}

其中ObjectsInfo用于读取txt文本文件(记录了物品的各个属性)。文章来源地址https://www.toymoban.com/news/detail-851892.html

到了这里,关于unity拖拽背包物体,并交换两个物体的信息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity中拖拽3D物体并放入到指定位置

    1.新建一个cube作为我们用来拖拽的物体:  2.给该cube添加我们刚刚编写的脚本: 3.场景中新建几个cube命名为Taget3D,摆在不同的位置并将这些新的cube传入到ListTartgets中:    4.新建几个Image命名为TargetUI,放在不同的位置并传入到ListUITarget中 : 5.新建两个Button分别对应传入buttonU

    2024年02月11日
    浏览(99)
  • Unity3D实现背包系统、物品的拖拽、拾取物品功能

    要在Unity中实现背包系统,你可以创建一个脚本来管理库存和物品。 首先,在Unity中创建一个名为“InventoryManager”的C#脚本。在这个脚本中,你可以创建一个将存储在背包中的物品列表。

    2024年02月16日
    浏览(45)
  • unity2d里实现鼠标拖拽物体的功能

    在 Unity 中实现鼠标拖拽物体的功能需要使用到 Unity 的 Physics 系统。 要实现鼠标拖拽物体,你需要在场景中添加以下内容: 一个 Rigidbody 2D 组件,用于控制物体的运动。 一个 Box Collider 2D 组件,用于检测鼠标与物体的碰撞。 一个脚本,用于监听鼠标的输入,并在鼠标按下时拖

    2024年02月11日
    浏览(45)
  • unity中 使用IDragHandler拖动交换子物体

    using DG.Tweening; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using VRSightCheck.Scripts; public class SwapPanel : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {     /// summary     /// 是否已经响应拖拽     /// /summary     public static bool isDrag = false;     priv

    2024年02月05日
    浏览(35)
  • unity存储信息的方式,保存读取背包、游戏进度,连接MySQL数据库

    为了在Unity中存储信息,有几种方法可供选择。最常见的方法是 PlayerPrefs、Serialization和Database 。 PlayerPrefs是一种简单的存储小量数据(如玩家偏好或游戏设置)的方法。它易于使用,不需要任何外部库。但是,不建议用于存储大量数据或敏感信息。 Serialization是另一种在Unit

    2024年02月09日
    浏览(63)
  • Unity3D实现鼠标悬浮UI或物体上显示文字信息

    Unity工具 大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 本篇文章实现一个鼠标悬浮在ui或者物体上显示文字的功能 unity鼠标悬浮ui显示文字 鼠标进入UI执行的 鼠标离开UI执行的 鼠标在ui里滑动执行的 1. 2. 搭建比较简单,各位顺便搭建吧。

    2024年02月04日
    浏览(95)
  • 信息学奥赛一本通——1267:【例9.11】01背包问题

    一个旅行者有一个最多能装 M M M 公斤的背包,现在有 n n n 件物品,它们的重量分别是 W 1 , W 2 , . . . , W n W_1,W_2,...,W_n W 1 ​ , W 2 ​ , ... , W n ​ ,它们的价值分别为 C 1 , C 2 , . . . , C n C_1,C_2,...,C_n C 1 ​ , C 2 ​ , ... , C n ​ ,求旅行者能获得最大总价值。 第一行:两个整

    2024年02月13日
    浏览(36)
  • 记录--Vue3问题:如何实现组件拖拽实时预览功能?

    实现一个CMS内容管理系统,在后台进行内容编辑,在官网更新展示内容。 关于后台的编辑功能,大致分为两部分: 组件拖拽预览 、 组件内容编辑实时预览 。 对于组件拖拽预览,用户可以在含有各种功能组件的列表中,选择需要的组件进行拖拽。将组件拖拽到预览画布中后

    2024年02月04日
    浏览(44)
  • 【Unity脚本开源】记录鼠标按下的位置和移动的距离来进行物体的旋转,并在鼠标释放后将物体恢复到初始旋转位置

    ♥️作者:白日参商 🤵‍♂️个人主页:白日参商主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油! 加油! 加油 🎈欢迎评论 💬点赞👍🏻 收藏 📂加关注+! 提针对这个需求,以下是示例脚本代码: ♥️作者

    2024年02月12日
    浏览(44)
  • Unity视角拉近时物体缺失的问题处理

    在Unity的开发过程中,我们可能会遇到以下情况:         就是在场景的不断编辑中,突然又一次打开场景,再拉近或拉远场景视角时,会出现场景中的对象会显示不全的问题。  出现了这样的情况会让场景的预览很不友好。 出现这个问题的原因是Unity生成的场景对应的文件

    2024年02月16日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包