7

游戏物品系统通用架构

 3 years ago
source link: http://www.luzexi.com/2013/12/31/%E6%B8%B8%E6%88%8F%E7%89%A9%E5%93%81%E7%B3%BB%E7%BB%9F%E9%80%9A%E7%94%A8%E6%9E%B6%E6%9E%84
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

游戏物品系统通用架构

游戏物品系统通用架构,物品系统是游戏中最最常用的功能之一,面对各种纷繁复杂的游戏物品系统,在具体项目中如何顺手拈来、驾驭自如?请容我一一到来。在内容前我有必要说明几点,所有内容都是基于我最大的架构思想之下,其中 客户端U3D架构思想的文章地址为 Unity3D游戏架构 ,以及服务器架构:《王图霸业》战争策略游戏服务器架构

首先,我们先归纳一下物品的基本属性。 物品基本属性:名字,描述,数量,最大可叠加数,图标 装备物品扩展属性:装备位置,攻击力,防御力,暴击率,魔力,血量,等等 消耗物品扩展属性:BUFF增加,HP增加,最大HP增加,等等

在游戏项目中,把这些物品的扩展属性,单个提取出来组合成各种游戏中需要的物品,如何做到?

1.把所有属性都写进物品数据配置表中?数据表过大,导致最终项目人员更改数据缓慢,错误不断,甚至连写此系统的程序员自己也吃不消。

2.把每个物品都按单各类进行特殊处理?假设物品有100种,那程序员就得写100各类实例,每增加一个写一个,浪费人力浪费时间。

3.以物品基类的继承的形式,将各种物品分类处理,归类,派生?繁琐,分类时间过长,效率过低,程序员最终会为物品该归到哪一类和策划人员而打起来。

如何才能做到物品系统适应不同的游戏需要,又能使得物品配置方便扩展性强?在这里我引入一个Action概念,Action以动作的概念来理解。当物品使用时,就调用不同的Action来达到不同的效果,例如:加血100加魔法200的物品,点击后,该物品执行加血100的Action实例,接着执行加魔200的实例,完毕后我们就能看到我们需要的效果了。所以物品只需要对应N各Action就可以完全做到你想做的,甚至可以做到你想不到的。

我们能发现,其实物品的很多功能是可以用不同单个功能组合起来的,比如加血,比如加魔,比如加BUFF状态,把这些相同功能的Action都做成一个,然后把不同的Action做成一个集合是多么完美的事,既达到了数据持续化存储和更新能力,又可使得物品功能完全由策划人员自行配置,发挥他们的无限想象力。

现在来看看实际中Action是如何编写的。把加血动作写成 类ActionAddHp,类中参数一个:HP,把加魔法动作写成 类ActionAddMP,类中参数一个:MP,这两个Action从数据表中读取相应的参数数据,变成众多Action实例里的一个,由ActionManager管理存储。到此回头看看,所有继承自Action类的扩展类拥有几个共同的属性:ID(唯一标识,用来区分所有Action),RunType(用来区分不同类型的Action),Read接口(用来读取数据),Excute接口(用来执行Action)。我在此之上加上一个Action类型,把所有Action拆分为条件类Action和执行类Action,条件类Action主要用来判断该物品的使用条件是否满足,执行类Action主要用来执行该动作的效果。因此Action基类就成了这样:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  

//  CAction.cs  
//  Author: Lu Zexi  
//  2013-12-24    
  
//base action  
public abstract class CAction : IAction  
{  
    private int m_iID;  //id  
  
    // id (0-99999) , actionType(0-99) , runType(0-99)  
    public CAction(int id, int actionType, int runType)  
    {  
        this.m_iID = actionType*10000000 + runType*100000 + id;  
    }  
  
    public abstract ActionError Excute(ActionInput input);  
  
    //roll back action  
    public virtual ActionError RollBack(ActionInput input)  
    {  
        return ActionError.NoError;  
    }  
  
    //get id  
    public int ID  
    {  
        get  
        {  
            return this.m_iID;  
        }  
    }  
}

有人会问,那如何让物品对应好几个Action呢?我再引入一个Action事件类,把它定义为类EventAction,他里面存储着16个Action ID,前8个ActionID是条件型动作,后8个ActionID为执行型动作。物品的数据中就有一个EventAction的ID,由这个EventAction来判断该执行那些Action,是否满足物品执行条件。当EventAction执行时,首先执行前8个Action,看看是否满足物品执行条件,如果不满足,则不执行后8个效果,如果满足再去执行后8个Action效果。因此EventAction也有很多各实例,由ID来区分不同的EventAction,由EventActionManager来管理所有事件Action。EventAction类结构:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
  
//  EventAction.cs  
//  Author: Lu zexi  
//  2013-12-24  
  
  
  
/// <summary>  
/// Action event  
/// </summary>  
public class EventAction  
{  
    private int m_iID; //ID  
    private int[] m_vecActions; //Action ID list  
    private int[] m_vecReqActions; //Require Action ID list  
  
    public EventAction()  
    {  
        this.m_vecActions = new int[8];  
        this.m_vecReqActions = new int[8];  
    }  
  
    // id (0-99999) , actionType(0-99) , runType(0-99)  
    public EventAction( int id , int eventType , int runType)  
    {  
        this.m_iID = eventType * 10000000 + runType*100000 + id;  
    }  
  
    //get id  
    public int ID  
    {  
        get  
        {  
            return this.m_iID;  
        }  
    }  
  
    //set action  
    public void SetAction( int[] act )  
    {  
        this.m_vecActions = act;  
    }  
  
    //set require  
    public void SetRequire( int[] req )  
    {  
        this.m_vecReqActions = req;  
    }  
  
    //excute action  
    public ActionError Excute( ActionInput input  )  
    {  
        for (int i = 0; i < this.m_vecActions.Length; i++)  
        {  
            CAction action = ActionManager.sInstance.GetAction(this.m_vecActions[i]);  
            if (action != null)  
            {  
                ActionError error = action.Excute(input);  
                if ( error != null && error.code != ACTION_ERROR_CODE.NONE)  
                    return error;  
            }  
        }  
        return ActionError.NoError;  
    }  
  
    //action require  
    public ActionError Require( ActionInput input)  
    {  
        for (int i = 0; i < this.m_vecReqActions.Length; i++)  
        {  
            CAction action = ActionManager.sInstance.GetAction(this.m_vecReqActions[i]);  
            if (action != null)  
            {  
                ActionError error = action.Excute(input);  
                if ( error != null && error.code != ACTION_ERROR_CODE.NONE)  
                    return error;  
            }  
        }  
        return ActionError.NoError;  
    }  
  
    //action roll back  
    public ActionError RollBack(ActionInput input)  
    {  
        for (int i = 0; i < this.m_vecActions.Length; i++)  
        {  
            CAction action = ActionManager.sInstance.GetAction(this.m_vecActions[i]);  
            if (action != null)  
            {  
                ActionError error = action.RollBack(input);  
                if (error != null && error.code != ACTION_ERROR_CODE.NONE)  
                    return error;  
            }  
        }  
        return ActionError.NoError;  
    }  
}

以上描述解决了物品中消耗品的问题,物品素材本身就是没有功能的消耗品,在这里我就不介绍了。而下面,我们来看看如何解决物品装备。 装备物品在消耗品上多了几样关于英雄角色的属性,这些属性有的明,有的暗,那我们就把那些明的属性提取出来,例如加增攻击力,增加防御力。而那些暗的属性,再拆分两种,一种是直接写进明的配置表中而不显示在界面上,另一个是直接写进动作Action里,当需要时执行相应EventAction实例。

最后,我们看看整个物品系统数据配置和系统源码。
物品类:名字,物品类型(消耗品,装备,素材),描述,数量,最大叠加数量,使用等级,EventActionID,装备位置,攻击力,防御力,HP,MP
Action表: ID , 描述 , ActionType , RunType , 参数1,参数2...
EventAction表: ID,描述,
ReqActionID1,ReqActionID2,...ReqActionID8,
ActionID9,ActionID10,...ActionID16.

源码:https://github.com/luzexi/Unity3DItemSystem

测试案例:https://github.com/luzexi/Unity3DItemSystem-Test

转载请注明出处:http://www.luzexi.com

December 31, 2013 · Unity3D, 游戏架构, 游戏通用模块

感谢您的耐心阅读

Thanks for your reading

版权申明

本文为博主原创文章,未经允许不得转载:

游戏物品系统通用架构

Copyright attention

Please don't reprint without authorize.

qrcode_for_gzh.jpg

微信公众号,文章同步推送,致力于分享一个资深程序员在北上广深拼搏中对世界的理解

QQ交流群: 777859752 (高级程序书友会)


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK