2021-08-18

Posted giegie界清流

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-08-18相关的知识,希望对你有一定的参考价值。

利用unity制作背包系统

首先介绍一下我自己,本人是个在读大学生,正在学习unity,为加深自己印象,所以在CSDN上写写博客,欢迎大家来讨论探讨,也欢迎大佬指教,争取大家都能获得进步!

搭建UI

在网上找了点图片并裁剪,搭建好了UI背包系统的界面
UI如下,注意设置好tag和父子对象关系以及布局,例如背包栏中需加入Grid Layout Group。

代码部分

  1. 首先对每个格子添加tag:cell,并规定装备栏中的cellltype分别为TouJia,Weapon,Shoes,Gloves,FangJu,ShiPin,背包栏中的格子celltype均为None。(利用枚举类)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public enum CellType
{
    TouJia,
    Weapon,
    Shoes,
    Gloves,
    FangJu,
    ShiPin,
    None
}

public class Cell : MonoBehaviour
{
    public CellType celltype;
}

将代码挂载到每一个格子对象中

  1. 每一个装备都需要设置tag为equip,挂载的代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Equip : Cell,  IBeginDragHandler, IDragHandler,  IEndDragHandler
{
    private GameObject Panel;
    private Transform PreviousCell;
    private GameObject Role;

    public int Attack;
    public int Defense;
    public int Health;
    public int Agile;
    public int Lucky;

    private void Awake()
    {
        Panel = GameObject.FindGameObjectWithTag("panel");
        Role = GameObject.FindGameObjectWithTag("role");
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        //先暂时关闭拖动装备的射线检测,可以检测到后方是格子,装备还是其他
        GetComponent<Image>().raycastTarget = false;
        //标记拖动前的父物体,以便拖动不符合条件,回到原父对象
        PreviousCell = transform.parent;
        //将装备的父对象设置为画板,这样就不会被其他东西压住
        transform.SetParent(Panel.transform);
    }

    public void OnDrag(PointerEventData eventData)
    {
        //装备的位置随鼠标的位置而移动,实现拖拽效果
        transform.position = Input.mousePosition;
    }

    /// <summary>
    /// 只有两种情况,从装备栏中拖拽装备和从背包栏中拖拽装备,其他对象不支持拖拽
    /// </summary>
    /// <param name="装备拖拽至什么地方"></param>
    public void OnEndDrag(PointerEventData eventData)
    {
        //从背包栏中拖拽装备
        if (PreviousCell.parent.tag == "bag")
        {
            //装备拖动后放入的是格子的情况,则格子接收装备
            if (eventData.pointerEnter.tag == "cell")
            {
                //放入的格子在背包中,则直接接收装备
                if (eventData.pointerEnter.transform.parent.tag == "bag")
                {
                    Receive(eventData.pointerEnter.transform, this);
                }
                //放入的格子在装备中,且装备类型匹配,则接收装备并更新属性
                else if (eventData.pointerEnter.transform.parent.tag == "currentequip" &&
                    eventData.pointerEnter.GetComponent<Cell>().celltype == GetComponent<Equip>().celltype)
                {
                    Receive(eventData.pointerEnter.transform, this);
                    UpdateProperties1(this);
                }
                //其他情况,回到原位置
                else
                {
                    Receive(PreviousCell, this);
                }
            }
            //装备拖动后放入的是装备的情况下,则装备交换
            else if (eventData.pointerEnter.tag == "equip")
            {
                //放入背包中的装备上,则直接交换
                if (eventData.pointerEnter.transform.parent.parent.tag == "bag")
                {
                    Receive(eventData.pointerEnter.transform.parent, this);
                    Receive(PreviousCell, eventData.pointerEnter.GetComponent<Equip>());
                }
                //放入的是装备中的装备上,则交换并更新属性
                else if (eventData.pointerEnter.transform.parent.parent.tag == "currentequip" &&
                     eventData.pointerEnter.GetComponent<Equip>().celltype == GetComponent<Equip>().celltype)
                {
                    Receive(eventData.pointerEnter.transform.parent, this);
                    Receive(PreviousCell, eventData.pointerEnter.GetComponent<Equip>());
                    UpdateProperties3(eventData.pointerEnter.GetComponent<Equip>(), this);
                }
                //其他情况,回到原位置
                else
                {
                    Receive(PreviousCell, this);
                }
            }
            // 其他情况,则回到原位置
            else
            {
                Receive(PreviousCell, this);
            }
            //将射线检测重新设置为true,以便下次拖动
            GetComponent<Image>().raycastTarget = true;
        }
        //从装备栏中拖拽装备
        else if(PreviousCell.parent.tag == "currentequip")
        {
            //将装备拖动至背包栏的格子中,则格子接收装备,属性减少
            if (eventData.pointerEnter.tag == "cell" && eventData.pointerEnter.transform.parent.tag == "bag")
            {
                Receive(eventData.pointerEnter.transform, this);
                UpdateProperties2(this);
            }
            //将装备拖动至背包栏的装备上,则交换装备,先减去原装备属性,再加上新装备属性
            else if(eventData.pointerEnter.tag == "equip" && 
                GetComponent<Equip>().celltype == eventData.pointerEnter.GetComponent<Equip>().celltype)
            {
                Receive(eventData.pointerEnter.transform.parent, this);
                Receive(PreviousCell, eventData.pointerEnter.GetComponent<Equip>());
                UpdateProperties3(this, eventData.pointerEnter.GetComponent<Equip>());
            }
            //其他情况下,均返回原来位置
            else
            {
                Receive(PreviousCell, this);
            }
            //将射线检测重新设置为true,以便下次拖动
            GetComponent<Image>().raycastTarget = true;
        }
    }

    //格子接收装备
    public void Receive(Transform cell, Equip equip)
    {
        equip.transform.SetParent(cell);
        equip.transform.localPosition = Vector3.zero;
    }

    //穿上装备属性更新
    private void UpdateProperties1(Equip equip)
    {
        Role.GetComponent<Properties>().EquipBonus(equip);
    }

    //卸载装备属性更新
    private void UpdateProperties2(Equip equip)
    {
        Role.GetComponent<Properties>().EquipReduction(equip);
    }

    //更换装备属性更新
    private void UpdateProperties3(Equip equip1, Equip equip2)
    {
        Role.GetComponent<Properties>().EquipReduction(equip1);
        UpdateProperties1(equip2);
    }
}

创建Equip类继承Cell类,以便于装备类型是否匹配,不然会出现头甲装备上武器这种混乱的情况。
装备的属性面板中的各个属性设置为了public,可以自己来设置装备的属性了。

  1. 关于属性的更新:既然要分别更新五个属性,不如将属性面板全部放在一个对象的子对象中,这里我选择的是这张图片,将其tag设置为role,以便更新属性面板。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Properties : MonoBehaviour
{
    private GameObject Attack;
    private GameObject Defense;
    private GameObject Health;
    private GameObject Agile;
    private GameObject Lucky;
    private int attack;
    private int defense;
    private int health;
    private int agile;
    private int lucky;

    private void Awake()
    {
        Attack = GameObject.FindGameObjectWithTag("attack");
        Defense = GameObject.FindGameObjectWithTag("defense");
        Health = GameObject.FindGameObjectWithTag("health");
        Agile = GameObject.FindGameObjectWithTag("agile");
        Lucky = GameObject.FindGameObjectWithTag("lucky");
        attack =int.Parse(Attack.GetComponent<Text>().text);
        defense = int.Parse(Defense.GetComponent<Text>().text);
        health = int.Parse(Health.GetComponent<Text>().text);
        agile = int.Parse(Agile.GetComponent<Text>().text);
        lucky = int.Parse(Lucky.GetComponent<Text>().text);
    }

    /// <summary>
    /// 穿上装备的属性增益
    /// </summary>
    /// <param name="带装备的装备"></param>
    public void EquipBonus(Equip equip)
    {
        attack += equip.GetComponent<Equip>().Attack;
        defense += equip.GetComponent<Equip>().Defense;
        health += equip.GetComponent<Equip>().Health;
        agile += equip.GetComponent<Equip>().Agile;
        lucky += equip.GetComponent<Equip>().Lucky;

        //更新面板属性
        Attack.GetComponent<Text>().text = attack.ToString();
        Defense.GetComponent<Text>().text = defense.ToString();
        Health.GetComponent<Text>().text = health.ToString();
        Agile.GetComponent<Text>().text = agile.ToString();
        Lucky.GetComponent<Text>().text = lucky.ToString();
    }


    /// <summary>
    /// 卸载装备的属性减少
    /// </summary>
    /// <param name="待卸载的装备"></param>
    public void EquipReduction(Equip equip)
    {
        attack -= equip.GetComponent<Equip>().Attack;
        defense -= equip.GetComponent<Equip>().Defense;
        health -= equip.GetComponent<Equip>().Health;
        agile -= equip.GetComponent<Equip>().Agile;
        lucky -= equip.GetComponent<Equip>().Lucky;

        //更新面板属性
        Attack.GetComponent<Text>().text = attack.ToString();
        Defense.GetComponent<Text>().text = defense.ToString();
        Health.GetComponent<Text>().text = health.ToString();
        Agile.GetComponent<Text>().text = agile.ToString();
        Lucky.GetComponent<Text>().text = lucky.ToString();
    }
}

总结

  1. 本来想用继承来重写方法,还是用了virtual虚方法,override重写方法来显示多态性的,结果写了好几次都不对,只能暂时放弃了。
  2. C#语言本身是哥面向对象的语言,而我写的第二个装备上的代码有点过于面向过程了,导致判断过多,还有很多重复代码。这点还需要改进!
  3. 后期role需要一个3D建模,而不止是张图片,应该穿上装备要有显示出穿上装备的样子,而不止是面板属性的更新。这样就需要改变画布显示的模式,让2D面板和3D人物并存,以及利用键盘输入或者easytouch实现人物旋转效果,后期学习后会有添加的!

最后放几张效果图吧

欢迎各位大佬批评指正!!!谢谢!

以上是关于2021-08-18的主要内容,如果未能解决你的问题,请参考以下文章

2021-08-18

2021-08-18

2021-08-18

C#基础2021-08-18

C#基础2021-08-18

2021-08-18