道具系统设计 2道具的设计.docx
《道具系统设计 2道具的设计.docx》由会员分享,可在线阅读,更多相关《道具系统设计 2道具的设计.docx(10页珍藏版)》请在冰豆网上搜索。
道具系统设计2道具的设计
好了,言归正传,我们正式开始道具系统的设计,第一部分将会是核心系统(code)的设计部分,这个部分将会分成2个部分,道具和道具管理器。
顾名思义,所以不多解释了。
我们马上开始道具的设计。
首先,打开你的unity,然后使用现有的或新建工程,然后在Project中,新建一个C#脚本,重命名为:
Item_Profile。
文章来自【狗刨学习网】
在正式编码之前,我们需要了解我们的需求,我们需要设计出什么样子的道具,道具的种类,道具之间的共享属性等等,一般的做法是,设计一个父类,然后根据不同的道具种类需求,然后派生出不同的道具出来,例如Item下派生出Weapon,Armor,Bomb等等,然后你会发现,你会派生出N多个类出来。
而作为独立制作人,我们(请允许我加入你们的队伍里)的通常的做法是,边设计,边编码,然后再设计,再编码,所以,在实际开发中,你会发现,需求在不断的变化,如果真的派生出这么多类出来,肯定要疯掉了,所以,小弟的设计是,将所有属性写在同一个类中,然后根据实际需求,来选择性读写某些属性。
这两种做法各有优略,而单一类最大的优势就是,懒!
好了,说了半天,其实就是懒,OK。
现在打开刚才的新建的Item_Profile文件,然后开始编码
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
[System.Serializable]
publicclassItem_Profile:
MonoBehaviour
{
}
作为道具的一员,之间肯定有某些共同的元素,例如名字,买卖价格,稀有程度等等。
所以,我们首先要设计的是这些共同的元素。
item_id ID,这个ID有系统自动分配,所以不需要对齐作出设计,保留为public,只是为了方便查看而已。
icon 2D图标。
comment 道具的描述。
type 道具类型,武器或护甲之类的。
rare 稀有度。
color 颜色,关联稀有度,白色到紫色之类的可视化等级。
[size=13.63636302948px]
buy,sell 买卖价格。
limit_stack 堆栈上线,例如20个一组的面包,或且无法叠加的武器或护甲。
model 3D模型。
#regioncommon
//*********commonvalues************//
//publicstringname="";
publicintitem_id=-1;//thisidassignedbyitemdatabasemanager
//publicstringitem_name;//usethegameobject'snameaswell
publicTexture2Dicon;
publicstringcomment;
publicenumTYPE
{
None,
Weapon,
Shield,
Armor,
Recipe,
Parts,
Consumables,
Bomb
};
publicTYPEtype;
publicintrare=1000;//therarelevel
publicColorcolor=Color.white;
publicintbuy,sell;
publicintlimit_stack=1;//maximun#ofstack
publicGameObjectmodel;
#endregion
然后就是武器属性的设计
weapon_type 武器的类型,单手剑或双手剑。
damage 攻击力,物理攻击或各种元素攻击。
damage_r 攻击力的波动范围。
#regionweapon
//*********weaponvalues************//
publicenumWEAPON_TYPE
{
None,
Single_Sword
};
publicWEAPON_TYPEweapon_type;
publicintdamage;
publicintdamage_r;//randomlyrange
publicintdamage_metal;
publicintdamage_metal_r;
publicintdamage_wood;
publicintdamage_wood_r;
publicintdamage_water;
publicintdamage_water_r;
publicintdamage_fire;
publicintdamage_fire_r;
publicintdamage_earth;
publicintdamage_earth_r;
//////////////////////////////////////////
#endregion
接着就是护盾和护驾的设计了,将他们放一起,是因为他们都属于防具,属性都一样。
clan 种族,精灵或且兽人,如果装备有指定种族的话,这个属性能帮上忙。
armor_type 护甲类型,头部,手部还是护盾。
def 防御力,各种元素防御力。
#regionshield&armor
//*********shield&armorvalues************//
//publicMaterialarmor_material;
//onlyforarmor
publicenumCLAN_TYPE
{
None,
Elven,
Orc
};
publicCLAN_TYPEclan=CLAN_TYPE.Orc;
//onlyforarmor
publicenumARMOR_TYPE
{
None,
Chest,
Head,
Shoulder,
Belt
};
publicARMOR_TYPEarmor_type;
publicintdef;
publicintdef_metal;
publicintdef_wood;
publicintdef_water;
publicintdef_fire;
publicintdef_earth;
//////////////////////////////////////////
#endregion
主要的道具我们都已经设计好了,下面让我们来搞点新意。
小弟就拿大家都比较感兴趣的合成配方这个部分来举例吧。
parts 合成所需的道具及数量。
这里可能大家会有个疑问,为什么不用item_id而要使用Item_Profile来关联道具,这个问题在设计道具管理器的时候会有解释。
final_product 终于的合成品。
#regionrecipe
//*********recipevalues************//
[System.Serializable]
publicclassRecipe_Parts
{
publicItem_Profilepart;
publicintnumber;
};
publicRecipe_Parts[]parts;
publicItem_Profilefinal_product;
//////////////////////////////////////////
#endregion
好了,差不多了,大致设计的方向就是这样了,再说下去估计大家都要无聊死了,所以,大家可以根据自身的需求来修改或扩写此类。
现在,大家伙应该是迫不及待的要看看目前的设计成果了,OK,去吧,比卡丘。
马上新建一个EmptyGameObject,然后挂载Item_Profile,然后你会发现,OMG,Inspector各种凌乱,完全无法继续设计下去了,这就是单一类带给我们的快乐,当然,今天绝对不会是这样结束的,我们接着下来要做的就是,改变这这一切。
现在,小弟假设大家都有对Editor编程有一定的了解,如果你不知道什么是Editor变成,请参考官网:
OK,新建一个C#脚本,并重命名为:
Item_Profile_Editor。
//这里是需要改变指定的类在Inspector中的布局,这里我们需要改变的类就是Item_Profile。
[CustomEditor(typeof(Item_Profile))]
publicclassItem_Profile_Editor:
Editor
{
voidOnEnable()
{
}
//这个函数,看名字就觉得很NB,这个就是在编辑状态下,Inspector的GUI的布局。
publicoverridevoidOnInspectorGUI()
{
//target是Editor里的一个属性,指的就是我们需要改变的那个类,这里做强转换,不解释。
Item_Profileitem=targetasItem_Profile;
//序列化更新,不解释。
serializedObject.Update();
//Addyourcodehere.
//……
//更新编辑后的数据。
serializedObject.ApplyModifiedProperties();
}
}
这段代码可以说是Editor编程的固定格式,不做过多的解释了,反正直接复制过去就对了,哈哈哈哈。
如果编译成功,你可能会发现,Inspector什么都没有了,嗯,这就是成功的第一步了。
现在开始显示道具们的共同元素。
//*********commonvalues**********//
item.item_id=EditorGUILayout.IntField("auto_id",item.item_id);
item.icon=EditorGUILayout.ObjectField("icon",item.icon,typeof(Texture2D))asTexture2D;
item.name=EditorGUILayout.TextField("name",item.name);
ment=EditorGUILayout.TextField("comment",ment);
GUILayout.Space(5f);
EditorGUILayout.PropertyField(serializedObject.FindProperty("type"));
GUILayout.Space(5f);
item.rare=EditorGUILayout.IntField("rare",item.rare);
EditorGUILayout.PropertyField(serializedObject.FindProperty("color"));
GUILayout.Space(5f);
item.buy=EditorGUILayout.IntField("buy",item.buy);
item.sell=EditorGUILayout.IntField("sell",item.sell);
GUILayout.Space(5f);
item.limit_stack=EditorGUILayout.IntField("limitstack",item.limit_stack);
item.model=EditorGUILayout.ObjectField("model",item.model,typeof(GameObject))asGameObject;
这段代码没有什么可以解释的,我们就抽选几个作为举例吧。
简单数据类型的处理方法:
item.item_id=EditorGUILayout.IntField("auto_id",item.item_id); //显示并更新item.item_id,“auto_id”为在Inspector中显示的名称。
内置的对象的处理方法:
item.icon=EditorGUILayout.ObjectField("icon",item.icon,typeof(Texture2D))asTexture2D;
对枚举类型的处理方法:
EditorGUILayout.PropertyField(serializedObject.FindProperty(“type"));
GUILayout函数是GUI的布局函数而已,不必太在意。
编译成功后,看看目前的成果吧。
成功的第二步,现在Type值的改变还会没有为我们带来什么实际上的效果,现在,要搞的就是这部分
//*********corevalues**********//
GUILayout.Space(10f);
if(NGUIEditorTools.DrawHeader("Info:
"))
{
NGUIEditorTools.BeginContents();
//GUILayout.BeginVertical();
switch(item.type)
{
caseItem_Profile.TYPE.Weapon:
Show_Weapon(item);
break;
caseItem_Profile.TYPE.Armor:
caseItem_Profile.TYPE.Shield:
Show_Armor_Shield(item);
break;
caseItem_Profile.TYPE.Recipe:
Show_Recipe(item);
break;
caseItem_Profile.TYPE.Parts:
Show_Parts(item);
break;
caseItem_Profile.TYPE.Consumables:
break;
caseItem_Profile.TYPE.Bomb:
break;
}
//GUILayout.EndVertical();
NGUIEditorTools.EndContents();
}
你会发现这里有几个是NGUI的函数,如果你还没有NGUI插件的话,可以忽略这些,这只是个布局函数而已,好了,如果真的没有NGUI的话,直接从switch语句开始就好了。
你会发现,switch的参数就是item.type,猜对了,Inspector会根据type的值,来显示其余的属性。
这里就不做过多的贴代码行为了,都是大同小异的,这里特别想贴出来的是,Show_Recipe(item)。
voidShow_Recipe(Item_Profileitem)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("parts"),true);
EditorGUILayout.PropertyField(serializedObject.FindProperty("final_product"),true);
}
特别想指出的是,因为这里包含了一个自定义数据的处理方法:
EditorGUILayout.PropertyField(serializedObject.FindProperty("parts"),true);
好了,编译通过后,你会发现,当你修改Type值的时候,后续的内容也会跟着改变,现在是不是编辑起来方便和许多。
(单一类和众派生类的做法基本相同,不同的就是需要根据type的值,来改变target的转换类型而已。
单有道具类还不够,我们需要有效的管理起成千上万的道具,下篇,我们将设计一个道具管理器,并将它设计成一个单一类,在整个游戏过程中,确保它是我们唯一能获取道具信息的唯一类,保证游戏进程中道具的信息统一