Unity3D的简单商店、背包与装备系统

物品元素可以说是所有RPG的必备系统,毕竟,如果没有物品系统就没有消耗,没有消耗哪能骗玩家充钱呢?最简单的物品系统应该是所谓的商店、背包加装备的结构,而这个Demo则主要基于UGUI实现一个简单的上述系统

UI
制作系统的第一步便是UI的绘制了。无论美术资源来自何方,画风如何,应该基本包括如下几个层面:

角色信息界面,用于显示主角的装备槽位以及正在穿戴中的装备
背包界面,用于显示主角拥有的物品集合
金钱标签,用于显示主角当前拥有的钱币
商店界面,用于显示当前售卖的物品集合
(可选)快速物品栏,通常与技能栏合用,让玩家能够快速使用物品
在我的Demo中也基本实现了上述模块

Bag System
一个背包系统的组成很简单,即面板+很多的格子,再贴一个金钱的文本框和几个图标就能够完成,我的背包也是基于上述想法来实现的:

通过Unity3D的Scroll View作为背包系统的主面板
创建Grid对象,并设置其Image为相应的Spirit作为物品图标
实现物品拖动逻辑,主要是在C#脚本实现动画表现,Lua更新数据,即注册onDrag事件,当鼠标拖动一个Grid时,创建一个当前Grid的副本,并在onDraging中不断获取当前鼠标所在的屏幕坐标赋值给副本的Transform,最后进行鼠标弹起位置的判断是否放在有效的区域,若位置合法则移动物品,并将数据写入Lua类,同步到服务器
// copy current grid
public static InventoryUIItemWrapperBase CreateDragObject(InventoryUIItemWrapperBase from)
{
var copy = GameObject.Instantiate(from);
copy.index = from.index;
copy.itemCollection = from.itemCollection;
copy.item = from.item;

var copyComp = copy.GetComponent<RectTransform>();
copyComp.SetParent(InventorySettingsManager.instance.guiRoot.transform);
copyComp.transform.localPosition = new Vector3(copyComp.transform.localPosition.x, copyComp.transform.localPosition.y, 0.0f);
copyComp.sizeDelta = from.GetComponent<RectTransform>().sizeDelta;

group.blocksRaycasts = false;
group.interactable = false;

return copy;

}

//draging event
public static void OnDrag(PointerEventData eventData)
{
if (currentDragHandler != null)
{
currentDragHandler.OnDrag(eventData);

    if (OnDragging != null) OnDragging(currentDragHandler.dragLookup, currentDragHandler.currentlyDragging, eventData);
}

}

//finish drag
public static InventoryUIDragLookup OnEndDrag(PointerEventData eventData)
{
if (currentDragHandler == null)
{
return null;
}
var lookup = currentDragHandler.OnEndDrag(InventoryUIUtility.currentlyHoveringWrapper, eventData);
if (OnEndDragging != null)
{
OnEndDragging(lookup, currentDragHandler.currentlyDragging, eventData);
AppFacade.instance.CallLua(“pg.global.bag.moveItem”, curItemId, eventData.getTargetGrid());
}

return lookup;

}
在初步实现中发现缺少了一个考虑的点,即拖拽到相同的物品应该合并,因此应当加入判断
此外,能合并物品理应能拆分,于是加入左Shift键的监听事件,物品的拆分逻辑可重用拖动逻辑,即直接调用DragItem(curItemId, targetGrid)将物品移入下一格,并创建一个相应的克隆对象,改变其下标的数量。当然,当背包满时直接Return即可
在Lua中应当调用服务器方法将数据写入数据库以保证数据的持久化
function onEndMoveItem(curItemId, grid)
self.server.MoveItem(curItemId, grid)
end
最后实现右键使用物品的逻辑,分消耗品和装备来进行不同的逻辑处理
Advandace Bag System
在上述的第一版实现完成后,其实还存在着一些不足:

背包的格子很多,一次性加载会造成卡顿
没必要每次移动物品后都写入数据库,可以在服务器内存里保留一个Map映射,当玩家下线后再根据此映射将整个背包的数据写入
对于第一个问题,我采用类型WOW里的背包模式,即增加一个仅能装备背包的装备栏,并加入“背包”这个物品,根据玩家选择的背包动态加载格子而非一次性全部加载。第二个问题则在Bag.xml里新增一个属性ItemBagMap保存物品id与格子id的映射
Store and PlayerInfo
商店界面和个人信息界面和背包类似,只不过在每个Grid里加上了价格标签而已,并且点击物品可以弹出购买界面,这只是UI与逻辑的不同罢了,在这里就不详谈了。出于美观,还可以在个人信息界面的中间做一个人物立绘,通过设定相机渲染到一个Reneder Texture便可以实现了

Pick Up Item
有了物品系统,相应的拾取逻辑也是必不可少的。在我的实现中主要基于碰撞检测的回调函数:

人物和掉落在地上的物品具有碰撞检测
当产生碰撞时判断背包是否已满,未满创建物品对应的grid对象并销毁地上物品的GameObject
物品存入背包成功则写入Lua
public virtual void OnTriggerEnter(Collider col)
{
TryPickup(col.gameObject);
}

public virtual void OnTriggerEnter2D(Collider2D col)
{
TryPickup(col.gameObject);
}

protected virtual void TryPickup(GameObject obj)
{

if (obj.layer == InventorySettingsManager.instance.equipmentLayer)
{
    return;
}

if (InventorySettingsManager.instance.itemTriggerOnPlayerCollision || CanPickupGold(obj))
{
    var item = obj.GetComponent<ObjectTriggererItem>();
    if (item != null)
    {
        item.Use(this);
    }
}

}

protected virtual bool CanPickupGold(GameObject obj)
{
return InventorySettingsManager.instance.alwaysTriggerGoldItemPickupOnPlayerCollision && obj.GetComponent() != null;
}

protected virtual void PickUpSucc(itemId, gridId)
{
AppFacade.instance.CallLua(“pg.global.bag.addItem”, curItemId, gridId)
}

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值