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

    前瞻

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

    有帮助就分享一下吧!

    转载请注明:少狼 – 敬畏知识的顽皮狗 » Unity3D 物品系统结合MVC框架设计之装备[1]

    喜欢 1

*

已经有1 人抢在你前面了~

  • 氯化橡胶漆 4年前 (2015-05-03)

    不错的文章,内容才思敏捷.禁止此消息:nolinkok@163.com