Unity3D 物品系统结合MVC框架设计之装备[1]

10 篇文章 0 订阅
1 篇文章 0 订阅
前瞻

首先声明这个都是个人想法,无好坏之分,合适就好。个人分析,里面难免有错误或者漏洞,请”不“要留言指出。0.0

物品分类:装备,材料,道具(各种,可细分)

大体所有的物品具备的属性:
见图



个人把物品分三大类:
1.材料,合成装备等等。
2.装备,穿在身上。
3.道具,装在身上的逼格。[这里面其实可以细分很多,宝石,各种奇怪的东东]
这样主要是不想所有的东西都在物品里面,想单独区分出来处理。具体优势不知道,个人想法。




装备

具体UI怎么做成的不详叙述。
界面图:


利用NGUI摆弄成的。


对象结构:



效果图:
1.拖拽卡槽


2.相同装备替换


3.装备装备



4.不同装备替换



主要的还是来自于代码的设计,依旧基于框架MVC,来处理UI和模块之间。
因为之前有2篇都是有关框架,但是有很多说框架在处理UI与原生到底好坏,其实我只是表示这样好处理模块之间,并咩有说不用MONO的东西
如果,我们能够结合岂不是更好。

如何不绑定脚本且不继承MonoBehaviour做U3D的开发
http://www.unitymanual.com/thread-34296-1-1.html


http://www.unitymanual.com/thread-34464-1-1.html
【客户端PureMVC框架与轻型U3D服务器Tnet结合图解 】

设计


1.替换装备UI端消息处理,采用点面原则,多有的点处理都需要经过面进行转发处理,就像需要功能传输时,点对点会使得代码很乱,
例如:点击BUTTON事件,需要那个处理某个事件,不是直接在onPress下去处理,而是传输,需要处理的相关数据,给面,然后面再去处理,如果这个 处理会连带处理其他消息,那么在通过面到点。这样就可以避免两个本来毫无关联的按钮事件,混迹一起。



2.结合框架分析模块处理任务,对于pureMVC来说,Mediator是直接处理view的,但是考虑界面很多简单效果都是需要mono,所以
对于mediator来说,我只需要面板的结果,而不参与如何操作,就想什么拖拽、移动等等,框架完全不管,只要把处理数据的那块交给我好了,你要什么,来拿,你要存储什么,传过来。




代码结构:
[个人不完全设计]
ItemDefine是一个数据类型同一规范类。

[mw_shl_code=csharp,true]using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

/*******************************/
/*          物品数据的定义                 */
/*******************************/
namespace Assets.Script.item
{
    /*
     *  物品类型
     */
    enum ITEM_TYPE_ENUM
    {
        ITEM_TYPE_OTHER,          //其他
        ITEM_TYPE_EQUIPMENT,      //装备
        ITEM_TYPE_GEM,                          //宝石
        ITEM_TYPE_MATERIAL,       //材料
        ITEM_TYPE_HEART_SPELL,          //心法
        ITEM_TYPE_CHEATS,                  //秘籍
        ITEM_TYPE_FASHIONABLE_DRESS//时装
    };

    //品质颜色
    enum QUALITY_EMUM
    {
        QUALITY_WHITE = 0,          //白色
        QUALITY_GREEN,          //绿色
        QUALITY_BLUE,           //蓝色
        QUALITY_YELLOW,         //黄色
        QUALITY_PUREPLE,        //紫色
        QUALITY_ORANGE,         //橙色
        QUALITY_GOLDEN,         //暗金

        QUALITY_TOTAL
    };

    //品质颜色结构体
    class QualityStruct
    {
        public string name;
        public Color color;

        public QualityStruct(string _name, Color _color)
        {
            name = _name;
            color = _color;
        }
    }

    //装备部件
    public enum EQUIP_POSITION_ENUM
    {
        EUQIP_POSITION_NONE,//非装备
        EQUIP_POSITION_WEAPON,//武器
        EQUIP_POSITION_HAT,//头盔
        EQUIP_POSITION_CLOTHES,//衣服
        EQUIP_POSITION_GLOVES,//手套
        EQUIP_POSITION_TROUSERS,//裤子
        EQUIP_POSITION_BELT,//腰带
        EQUIP_POSITION_SHOES,//鞋子
        EQUIP_POSITION_RING,//戒指
        EQUIP_POSITION_FASHION//时装
    };

    //装备属性结构体
    class EquipPropertyStruct
    {
        EQUIP_POSITION_ENUM etype;
        int rank;//品阶
        float hp;//气血
        float mp;//内里
        float atk;//攻击力
        float def;//防御力
        float defDec;//破甲
        float damageDec;//减伤
        float crit;//会心
        float critResi;//精通
        float critDamage;//会心伤害
        float mpRestore;//精神
    }

    //背包物品类型
    enum PACK_TYPE_ENUM
    {
        PACK_TYPE_EQUIP = 0,    //装备
        PACK_TYPE_MATERIAL,     //材料
        PACK_TYPE_DROP,         //道具
        PACK_TYPE_NONE          //无效类型
    };
}
[/mw_shl_code]

1.与mediator紧密联系的是Item,Equipment,EnquipManager.
(1).Item是一个基类,物品基类。

[mw_shl_code=csharp,true]using UnityEngine;
using System.Collections;

namespace Assets.Script.item
{
    public class Item
    {
        private int id;       //物品ID
        private string name;  //物品名称
        private Texture2D icon;//物品图标
        private float price;   //物品价格
        private string comment;//物品介绍

        public Item() { }

        public virtual void initData(int _id, string _name, Texture2D _icon, float _price, string _comment)
        {
            this.id = _id;
            this.name = _name;
            this.icon = _icon;
            this.price = _price;
            this.comment = _comment;
        }

        public virtual int getId() { return id; }

        public virtual string getName() { return name; }

        public virtual Texture2D getIcon() { return icon; }

        public virtual float getPrice() { return price; }

        public virtual string getComment() { return comment; }

        public virtual void setIcon(Texture2D _icon){ icon = _icon; }
    }
}[/mw_shl_code]
用于多态实现各种物品类的东东。

2.Equipment是一个具体的装备个体类。
时间原因,暂时还没作处理数据的逻辑。

[mw_shl_code=csharp,true]using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Assets.Script.item
{
    public class Equipment : Item
    {
        public bool isDress = false;//是否穿戴
        public Equipment() { }
    
    }
}[/mw_shl_code]


3.EquipManager是一个用于管理装备的类。
部分处理数据想法。

[mw_shl_code=csharp,true]using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Assets.Script.item
{
    class EquipManager
    {
        //存储玩家自己的ID,以及查看好友的ID,其他路径可获得信息的ID
        Dictionary<string, List<Equipment>> equipList; //userID, 准备包【所有的】

        private static EquipManager instance = null;

        public EquipManager() { }

        public static EquipManager getInstance()
        {
            if (instance == null)
            {
                return new EquipManager();
            }
            return instance;
        }

        public void init()
        {

        }

        public List<Equipment> getEquipmentList(string id)
        {
            if (equipList.Keys.Contains(id))
            {
                return equipList[id];
            }
            return null;
        }
    }
}[/mw_shl_code]

暂时只想到这么多数据。

UI基于MONO代码结构:
[纯粹个人设计]

1.WinPanelController是一个处理装备槽的类。或者还有处理PackPanelController的类,处理背包的

[mw_shl_code=csharp,true]using UnityEngine;
using System.Collections;
using Assets.Script.item;

public class WinPanelController : MonoBehaviour {

    public static WinPanelController instance;

        // Use this for initialization
        void Start () 
    {
        instance = this;
        }
        
        // Update is called once per frame
        void Update () 
    {
        
        }
}[/mw_shl_code]


2.EquipItem是处理单个装备拖拽等等功能。
有一些小的问题。
[mw_shl_code=csharp,true]
using UnityEngine;using System.Collections;
using Assets.Script.item;

public class EquipItem : UIDragDropItem {

    private Vector3 position;
    public EQUIP_POSITION_ENUM postionType;
    public Equipment equipment = new Equipment(); //数据对象

    public UISprite bg;
    public UISprite title;

    protected override void OnDragDropStart()
    {
       base.OnDragDropStart();
    }

    protected override void OnDragDropRelease(GameObject surface)
    {
        //当放进卡槽之后判断类型是否一致
        //1.改变父节点,并且改变坐标
        //2.设置拖拽不复制,cloneOnDrag为false.
        //3.碰撞打开,取消初始化touchID

        if (surface == null)
        {
            rePosition(surface);
            return;
        }

        WinItem item = null;

        if (surface.GetComponent<WinItem>() != null)
        {
             item = surface.GetComponent<WinItem>();
             item.handleWin(this.gameObject);
        }
        else if(surface.GetComponent<EquipItem>() != null)
        {
            if (surface.GetComponent<EquipItem>().postionType == postionType && !equipment.isDress)
            {
                //交换功能
                //实质上去改变背包中属性
                newPostion(surface);
                //因为是clone出来的对象,所以替换掉实际上可以删除原有的那个,这个只是针对装备来说【有些只是可以直接拖拽】
                Destroy(surface);
                return;
            }
            else
            {
                Debug.Log("已装备了同一个!");
            }
        }
        else
        {
            rePosition(surface);
            return;
        }

        if (item.postionType == postionType && item != null)
        {
            newPostion(surface);
        }
        else
        {
            rePosition(surface);
        }
    }

    private void rePosition(GameObject surface)
    {
        if (!this.cloneOnDrag)
        {
            this.transform.localPosition = position;
            this.collider.enabled = true;
            this.mTouchID = int.MinValue;
            Debug.Log("位置不合适");
        }
        else
        {
            base.OnDragDropRelease(surface);
        }
    }

    private void newPostion(GameObject surface)
    {
        Debug.Log("位置合适");
        bg.GetComponent<UISprite>().depth = 2;
        title.GetComponent<UISprite>().depth = 3;
        this.transform.FindChild("title").gameObject.SetActive(true);
        equipment.isDress = true;
        this.transform.parent = surface.transform.parent;
        this.transform.localPosition = surface.transform.localPosition;
        position = this.transform.localPosition;
        this.cloneOnDrag = false;
        this.collider.enabled = true;
        this.mTouchID = int.MinValue;
    }
}
[/mw_shl_code]
3.WinItem这个事处理装备的单个插槽的类,暂时事项用槽来记录谁插进来了,为了处理替换装备功能,但是其实可以通过一个类来管理,
例如前面的WinPanelController,暂时还没设计完成。


[mw_shl_code=csharp,true]using UnityEngine;
using System.Collections;
using Assets.Script.item;
using System.Collections.Generic;

public class WinItem : MonoBehaviour {

    public EQUIP_POSITION_ENUM postionType;

    private GameObject equipObj;

        // Use this for initialization
        void Start () 
    {
            
        }
        
    public void handleWin(GameObject go)
    {
        equipObj = go;
    }

    public GameObject getEquipObj()
    {
        return equipObj;
    }
}[/mw_shl_code]


4.顺便贴一下NGUI自带的这个类,功能不错,但是需要真正用的时候,改动还是挺多的,例如clone出来的装备,是否有必要这样设计,
根据不同需求吧,已装备的部件在背包需要显示的时候,是直接用代码同步控制两个对象,还是说对象之间,传递什么达到同步。
UIDragDropItem.cs


[mw_shl_code=csharp,true]//----------------------------------------------
//            NGUI: Next-Gen UI kit
// Copyright © 2011-2014 Tasharen Entertainment
//----------------------------------------------

using UnityEngine;
using System.Collections;

/// <summary>
/// UIDragDropItem is a base script for your own Drag & Drop operations.
/// </summary>

[AddComponentMenu("NGUI/Interaction/Drag and Drop Item")]
public class UIDragDropItem : MonoBehaviour
{
        public enum Restriction
        {
                None,
                Horizontal,
                Vertical,
                PressAndHold,
        }

        /// <summary>
        /// What kind of restriction is applied to the drag & drop logic before dragging is made possible.
        /// </summary>

        public Restriction restriction = Restriction.None;

        /// <summary>
        /// Whether a copy of the item will be dragged instead of the item itself.
        /// </summary>

        public bool cloneOnDrag = false;

        /// <summary>
        /// How long the user has to press on an item before the drag action activates.
        /// </summary>

        [HideInInspector]
        public float pressAndHoldDelay = 1f;

#region Common functionality

        protected Transform mTrans;
        protected Transform mParent;
        protected Collider mCollider;
        protected Collider2D mCollider2D;
        protected UIButton mButton;
        protected UIRoot mRoot;
        protected UIGrid mGrid;
        protected UITable mTable;
        protected int mTouchID = int.MinValue;
        protected float mPressTime = 0f;
        protected UIDragScrollView mDragScrollView = null;

        /// <summary>
        /// Cache the transform.
        /// </summary>

        protected virtual void Start ()
        {
                mTrans = transform;
                mCollider = collider;
                mCollider2D = collider2D;
                mButton = GetComponent<UIButton>();
                mDragScrollView = GetComponent<UIDragScrollView>();
        }

        /// <summary>
        /// Record the time the item was pressed on.
        /// </summary>

        void OnPress (bool isPressed) { if (isPressed) mPressTime = RealTime.time; }

        /// <summary>
        /// Start the dragging operation.
        /// </summary>

        void OnDragStart ()
        {
                if (!enabled || mTouchID != int.MinValue) return;

                // If we have a restriction, check to see if its condition has been met first
                if (restriction != Restriction.None)
                {
                        if (restriction == Restriction.Horizontal)
                        {
                                Vector2 delta = UICamera.currentTouch.totalDelta;
                                if (Mathf.Abs(delta.x) < Mathf.Abs(delta.y)) return;
                        }
                        else if (restriction == Restriction.Vertical)
                        {
                                Vector2 delta = UICamera.currentTouch.totalDelta;
                                if (Mathf.Abs(delta.x) > Mathf.Abs(delta.y)) return;
                        }
                        else if (restriction == Restriction.PressAndHold)
                        {
                                if (mPressTime + pressAndHoldDelay > RealTime.time) return;
                        }
                }

                if (cloneOnDrag)
                {
                        GameObject clone = NGUITools.AddChild(transform.parent.gameObject, gameObject);
                        clone.transform.localPosition = transform.localPosition;
                        clone.transform.localRotation = transform.localRotation;
                        clone.transform.localScale = transform.localScale;

                        UIButtonColor bc = clone.GetComponent<UIButtonColor>();
                        if (bc != null) bc.defaultColor = GetComponent<UIButtonColor>().defaultColor;

                        UICamera.currentTouch.dragged = clone;

                        UIDragDropItem item = clone.GetComponent<UIDragDropItem>();
                        item.Start();
                        item.OnDragDropStart();
                }
                else OnDragDropStart();
        }

        /// <summary>
        /// Perform the dragging.
        /// </summary>

        void OnDrag (Vector2 delta)
        {
                if (!enabled || mTouchID != UICamera.currentTouchID) return;
                OnDragDropMove((Vector3)delta * mRoot.pixelSizeAdjustment);
        }

        /// <summary>
        /// Notification sent when the drag event has ended.
        /// </summary>

        void OnDragEnd ()
        {
                if (!enabled || mTouchID != UICamera.currentTouchID) return;
                OnDragDropRelease(UICamera.hoveredObject);
        }

#endregion

        /// <summary>
        /// Perform any logic related to starting the drag & drop operation.
        /// </summary>

        protected virtual void OnDragDropStart ()
        {
                // Automatically disable the scroll view
                if (mDragScrollView != null) mDragScrollView.enabled = false;

                // Disable the collider so that it doesn't intercept events
                if (mButton != null) mButton.isEnabled = false;
                else if (mCollider != null) mCollider.enabled = false;
                else if (mCollider2D != null) mCollider2D.enabled = false;

                mTouchID = UICamera.currentTouchID;
                mParent = mTrans.parent;
                mRoot = NGUITools.FindInParents<UIRoot>(mParent);
                mGrid = NGUITools.FindInParents<UIGrid>(mParent);
                mTable = NGUITools.FindInParents<UITable>(mParent);

                // Re-parent the item
                if (UIDragDropRoot.root != null)
                        mTrans.parent = UIDragDropRoot.root;

                Vector3 pos = mTrans.localPosition;
                pos.z = 0f;
                mTrans.localPosition = pos;

                TweenPosition tp = GetComponent<TweenPosition>();
                if (tp != null) tp.enabled = false;

                SpringPosition sp = GetComponent<SpringPosition>();
                if (sp != null) sp.enabled = false;

                // Notify the widgets that the parent has changed
                NGUITools.MarkParentAsChanged(gameObject);

                if (mTable != null) mTable.repositionNow = true;
                if (mGrid != null) mGrid.repositionNow = true;
        }

        /// <summary>
        /// Adjust the dragged object's position.
        /// </summary>

        protected virtual void OnDragDropMove (Vector3 delta)
        {
                mTrans.localPosition += delta;
        }

        /// <summary>
        /// Drop the item onto the specified object.
        /// </summary>

        protected virtual void OnDragDropRelease (GameObject surface)
        {
                if (!cloneOnDrag)
                {
                        mTouchID = int.MinValue;

                        // Re-enable the collider
                        if (mButton != null) mButton.isEnabled = true;
                        else if (mCollider != null) mCollider.enabled = true;
                        else if (mCollider2D != null) mCollider2D.enabled = true;

                        // Is there a droppable container?
                        UIDragDropContainer container = surface ? NGUITools.FindInParents<UIDragDropContainer>(surface) : null;

                        if (container != null)
                        {
                                // Container found -- parent this object to the container
                                mTrans.parent = (container.reparentTarget != null) ? container.reparentTarget : container.transform;

                                Vector3 pos = mTrans.localPosition;
                                pos.z = 0f;
                                mTrans.localPosition = pos;
                        }
                        else
                        {
                                // No valid container under the mouse -- revert the item's parent
                                mTrans.parent = mParent;
                        }

                        // Update the grid and table references
                        mParent = mTrans.parent;
                        mGrid = NGUITools.FindInParents<UIGrid>(mParent);
                        mTable = NGUITools.FindInParents<UITable>(mParent);

                        // Re-enable the drag scroll view script
                        if (mDragScrollView != null)
                                StartCoroutine(EnableDragScrollView());

                        // Notify the widgets that the parent has changed
                        NGUITools.MarkParentAsChanged(gameObject);

                        if (mTable != null) mTable.repositionNow = true;
                        if (mGrid != null) mGrid.repositionNow = true;
                }
                else NGUITools.Destroy(gameObject);
        }

        /// <summary>
        /// Re-enable the drag scroll view script at the end of the frame.
        /// Reason: http://www.tasharen.com/forum/index.php?topic=10203.0
        /// </summary>

        protected IEnumerator EnableDragScrollView ()
        {
                yield return new WaitForEndOfFrame();
                if (mDragScrollView != null) mDragScrollView.enabled = true;
        }
}[/mw_shl_code]

源码下载:
[attach]64164[/attach]

以上仅代表个人分析,犹豫自己也是在学习,目前暂时还没设计完全,但是大体思想差不多,如果后续可以的话,将最后出最优方案。来实现
框架+MONO方案。

转载请注明出处。

作者: 大帅纷纭

微博:http://weibo.com/2357191704/profile?topnav=1&wvr=6

博客:http://blog.csdn.net/dashuaifenyun1991

邮箱:bandit_empire@163.com

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值