2021-08-18
Posted giegie界清流
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-08-18相关的知识,希望对你有一定的参考价值。
利用unity制作背包系统
首先介绍一下我自己,本人是个在读大学生,正在学习unity,为加深自己印象,所以在CSDN上写写博客,欢迎大家来讨论探讨,也欢迎大佬指教,争取大家都能获得进步!
搭建UI
在网上找了点图片并裁剪,搭建好了UI背包系统的界面
UI如下,注意设置好tag和父子对象关系以及布局,例如背包栏中需加入Grid Layout Group。
代码部分
- 首先对每个格子添加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;
}
将代码挂载到每一个格子对象中
- 每一个装备都需要设置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,可以自己来设置装备的属性了。
- 关于属性的更新:既然要分别更新五个属性,不如将属性面板全部放在一个对象的子对象中,这里我选择的是这张图片,将其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();
}
}
总结
- 本来想用继承来重写方法,还是用了virtual虚方法,override重写方法来显示多态性的,结果写了好几次都不对,只能暂时放弃了。
- C#语言本身是哥面向对象的语言,而我写的第二个装备上的代码有点过于面向过程了,导致判断过多,还有很多重复代码。这点还需要改进!
- 后期role需要一个3D建模,而不止是张图片,应该穿上装备要有显示出穿上装备的样子,而不止是面板属性的更新。这样就需要改变画布显示的模式,让2D面板和3D人物并存,以及利用键盘输入或者easytouch实现人物旋转效果,后期学习后会有添加的!
最后放几张效果图吧
欢迎各位大佬批评指正!!!谢谢!
以上是关于2021-08-18的主要内容,如果未能解决你的问题,请参考以下文章