Unity学习日志_NGUI背包系统基本功能实现
功能展示:
1. 拖拽:
2. 不同物体交换:
3. 相同物体叠加:
背包界面搭建:
1. 整体层级逻辑:
2. 细节:
-
关于BackPack:使用了Scroll View脚本,便于背包的上下滑动
-
关于BackPackBackground:使用了Grid脚本来实现自动布局
-
关于Cell:使用的BackPackCellTest脚本继承于UIDragScrollView
-
关于Items:使用的BackPackTest脚本继承于UIDragDropItem
背包逻辑实现:
在这里说一下发现的NGUI2018.3的bug:当将物体拖向背包外时,概率发生surface = 物体自身的情况,这倒是如果不做限制就会发生物体拖出去回不来的情况。
using UnityEngine;
using UnityTools;
public class BackPackTest : UIDragDropItem
{
/// <summary>
/// 存储当前拖拽目的地检测道德物体坐标。
/// </summary>
private Vector2 _surfacePosition;
/// <summary>
/// 存储当前位置的装备格脚本,此脚本继承自UIDragScrollView,并新加_hasItems属性。
/// </summary>
private backPackCellTest _backPackCellTest;
/// <summary>
/// 存储上个位置的装备格脚本,此脚本继承自UIDragScrollView,并新加_hasItems属性。
/// </summary>
private backPackCellTest _lastParentBackPackCellTest;
/// <summary>
/// 存储游戏物体的本名,不受相同物体多次拖拽出现的括号影响
/// </summary>
[SerializeField]
private string _itemName;
/// <summary>
/// 存储surface的BackPackTest脚本
/// </summary>
private BackPackTest _backPackTest;
/// <summary>
/// 存储物体个数
/// </summary>
[SerializeField]
private int _itemNum;
/// <summary>
/// 存储surface的父物体,用于物体交换方法
/// </summary>
private Transform _tempParent;
/// <summary>
/// 存储当前拖拽物体的父物体,用于物体交换方法
/// </summary>
private Transform _thisTempParent;
/// <summary>
/// 获取子类label组件,用于更新物品数字
/// </summary>
private UILabel _myLabel;
protected override void Start()
{
base.Start();
//初始化上次装备所在位置的装备格
_lastParentBackPackCellTest = this.GetComponentInParent<backPackCellTest>();
//将当前装备所在的装备格的hasItems设为true
_lastParentBackPackCellTest._hasItems = true;
//获得装备本名
_itemName = this.name.StringSlip();
//可以从文件中读取数据
_itemNum = 1;
//初始化物品数字
_myLabel = GetComponentInChildren<UILabel>();
_myLabel.text = _itemNum.ToString();
}
protected override void OnDragDropStart()
{
base.OnDragDropStart();
//每次开始拖拽装备时获得当前装备格
_lastParentBackPackCellTest = this.GetComponentInParent<backPackCellTest>();
}
protected override void OnDragDropRelease(GameObject surface)
{
//每次结束拖拽时获得结束位置的装备格
_backPackCellTest = surface.GetComponent<backPackCellTest>();
_backPackTest = surface.GetComponent<BackPackTest>();
base.OnDragDropRelease(surface);
//拖拽到不同的格子逻辑
DragItemsController(surface);
}
private void DragItemsController(GameObject surface)
{
//使用变量临时存储一下当前结束拖拽后被拖拽物体下方物体的位置信息。
_surfacePosition = surface.transform.position;
//如果装备格组件不为空说明当前拖拽到的位置是一个装备格
if (_backPackCellTest != null)
{
//执行拖拽逻辑
DragItems(surface);
}
//如果为空说明当前拖拽位置有物体或者被拖拽到了背包外,需要进一步判断
else
{
//如果装备游戏物体名字相同,说明在向背包外拖拽时发生了NGUI2018.3的bug,返回之前的位置即可
if (surface.name == this.transform.name)
{
this.transform.position = this.transform.parent.position;
}
//如果名字不相同说明没有触发bug,而是拖拽目的地存在物体,需要进一步判断
else
{
//如果装备本名不同说明是不同的装备,需要交换位置
if (_backPackTest._itemName != this._itemName)
{
SwitchItems(surface);
}
//否则装备数量++
else
{
AddItems();
}
}
}
}
//拖拽逻辑
private void DragItems(GameObject surface)
{
/*如果当前拖拽到的装备格为空而且游戏物体名称不同说明:
1. 此装备格没有物体
2. 没有触发NGUI2018.3的bug
3. 可以进行位置更新
*/
if ((!_backPackCellTest._hasItems) && surface.name != this.transform.name)
{
//将当前拖拽到的装备格的位置信息赋值给当前物体
this.transform.position = _surfacePosition;
//更改当前物体的父物体
this.transform.SetParent(surface.transform);
//将当前装备格的hasItems设置为true,表示此装备格有物体
_backPackCellTest._hasItems = true;
//将上一装备格的hasItems改为false,表示装备格没有物体
_lastParentBackPackCellTest._hasItems = false;
}
//当前装备格不为空或者游戏名字相同触发了bug,返回上个位置
else
{
this.transform.position = this.transform.parent.position;
}
}
//交换逻辑
private void SwitchItems(GameObject surface)
{
//存储交换物体的父物体信息
_tempParent = surface.transform.parent;
//存储当前物体的父物体
_thisTempParent = this.transform.parent;
//交换位置信息
surface.transform.position = _thisTempParent.position;
this.transform.position = _tempParent.position;
//重设父物体
surface.transform.SetParent(_thisTempParent);
//重设父物体
this.transform.SetParent(_tempParent);
}
//叠加逻辑
private void AddItems()
{
//目标物体数量与拖拽物体数量相加;
_backPackTest._itemNum += this._itemNum;
_backPackTest._myLabel.text = _backPackTest._itemNum.ToString();
//销毁拖拽物体
Destroy(this.gameObject);
//重置上个装备格
_lastParentBackPackCellTest._hasItems = false;
}
}
BackPackCellTest类:
public class backPackCellTest : UIDragScrollView
{
public bool _hasItems = false;
}
另附StringSlip方法的代码:
namespace UnityTools
{
public static class GenericTools
{
public static string StringSlip(this string str)
{
string finalString = "";
char[] charArray = str.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
if (charArray[i] != '(')
{
finalString += charArray[i].ToString();
}
else
{
break;
}
}
//合成的string最后会莫名多一个空格,使用trim去掉。
return finalString.TrimEnd();
}
}
}