使用Unity3D编写ARPG游戏——角色属性的定义与实现(一)
2015-06-03 23:39
567 查看
今天考完了大学最后一门考试,是瞬间感觉轻松了一点,花了一天多的时间预习一本书,马上就去考试了,就结果而言还是不错的。但是不知道是一种解脱,还是马上要戴上的一种新的枷锁。总归还是不错的。好了,闲话少扯,继续谈谈如何制作一款ARPG游戏,sunset在上两篇博客中已经介绍过了几种常见的ARPG游戏的人物控制方式,都比较简单,易于理解。接下来来看看制作ARPG游戏还需要什么,先从玩家可操作的角色出发,我们还需要人物的血量,或者用于释放魔法的魔量,这样就转入一种新的概念——人物属性。下面开始sunset个人编写的可视化人物属性编辑器:
sunset在个人制作的ARPG游戏项目中采用了这样一些属性:等级(LV)、血量(HP)、魔法值(MP)、攻击力(Attack)、防御力(Defend)、强壮(Strength)、敏捷(Agility)、智力(Intelligence)、体力(Power)、移动速度(MoveSpeed)、转身速度(RotationSpeed)、攻击距离(AttackRange)、暴击伤害百分比(CriticalDamage)、暴击概率(CriticalRate)等。这些属性值基本上满足了一款ARPG游戏的属性要求。接下来sunset给出的属性编辑器也基本上是基于这些属性进行编写的。
注释的相当仔细,一看就懂。
然后我们还需要定义一些单独存在的量:比如最高等级,最大经验值、当前等级所需经验,如果有各种动画状态,还需要单独定义步行速度(WalkSpeed)、跑步速度(RunSpeed)、左右转身时向左或向右移动的速度(TurnSpeed),或者还可以定义后退时的移动速度(BackwardSpeed),看个人需求。然后定义出上文代码中定义的类对象的实例对象,编写过程中主要是使用类的实例对象。代码:
嗯,基本需要用到的量都已经定义好了,下一步开始编写方法使用这些量。
然后更新当前经验值:
先判断当前等级是否大于最高等级,再判断当前经验是否达到当前等级所要求的经验量,如果达到就升级,并更新相关属性。升级时恢复血量和魔量到最大值。
接下来是更新相关属性的方法:
这里主要说明一下,sunset个人定义的属性中强壮部分决定了攻击力和血量上限,体力部分决定了防御力,智力部分决定了魔法值上限,敏捷部分决定了各种速度等等,自行理解。
然后在计算更新属性方法中还定义了一种当存在升级点数加成时,计算升级属性相关的方法:
这样更新属性方面的相关方法就差不多了,然后我们还要检测血量等属性值,避免血量等属性值超过总属性值。
这样属性编辑器在原始属性定义方面就差不多完成了,然而现在我们编写的还只是脚本,不能算的上是一种可视化编辑器,还需要编辑一个Editor文件来对上文定义的变量进行值的输入。Editor文件的编写在原理上是十分简单的,就是一味的套用Unity本身的制定的GUIEditor的方法就好了,编写插件也是通过这种方法进行编写的,只是编写的好坏以及是否美观简洁、是否易于输入与识别的区别而已,这当然需要大量的动手编写经验。基本的语法都可以在API文档中找到sunset在这里不再赘述给出sunset个人编写的一个简单的人物属性Editor文件的源代码:
嗯,Editor文件只是一系列重复的语句,修改其中的关键词以符合各种属性就好了,是不是很简单呢?程序编写的脚本能让策划简单易懂的实现值的输入是非常重要的,写的美观简洁易懂不止是给策划方便,也是给自己方便。嗯,今天写的有点多了,现在时间也很晚了至于人物编辑器编写的剩下部分就明天下午更吧,就这样。
人物属性分析
我们不能还没有经过分析或者思考就去动手写代码,这样只会一味给自己增加难度,延后代码编写完成的时间,这也是软件工程的基本理论。在首先编写代码之前,先来分析一下:我们需要什么?一个属性编辑器;这个编辑器中包含哪些属性?只要玩过一定数量的游戏,就会明白游戏人物一般都会有移动速度,攻击速度,攻击力,防御力等等属性值。我举例一款对属性比较看重的游戏——《Dota2》。虽然这款游戏是一款Moba游戏,但是丝毫不妨碍我们对属性经行分析,《Dota2》里英雄的属性包括:力量、敏捷、智力、攻击力、护甲、移动速度、转身速率、攻击速度、攻击距离等等等等。通过一款优秀的游戏可以得出我们所需要的解决的问题的答案,我们是否也需要敏捷、智力等等属性呢?一切都由你来决定,因为这是你的游戏。sunset在个人制作的ARPG游戏项目中采用了这样一些属性:等级(LV)、血量(HP)、魔法值(MP)、攻击力(Attack)、防御力(Defend)、强壮(Strength)、敏捷(Agility)、智力(Intelligence)、体力(Power)、移动速度(MoveSpeed)、转身速度(RotationSpeed)、攻击距离(AttackRange)、暴击伤害百分比(CriticalDamage)、暴击概率(CriticalRate)等。这些属性值基本上满足了一款ARPG游戏的属性要求。接下来sunset给出的属性编辑器也基本上是基于这些属性进行编写的。
编辑器编写思考
经过属性中基本的属性量的定义后,我们还要进一步思考脚本该怎么编写才能使其更加易用与将来可能出现的武器属性加成或者被动技能属性加成等问题。所以将属性又分别分成几种类型:1)基础属性(BaseAttribute);2)额外(附加)属性(AdditiveAtribute);3)当前属性(CurrentAttribute);4)升级属性(GrowthAttribute);5)总属性(SumAttribute)等。这部分必须进行仔细思考,当写到一半才发觉还需要定义新的属性类型才能完成编写而不得不回头的时候,你会感觉非常无奈而致使完成时间向后拖延,所以经过仔细思考后再动手会事半功倍(个人经验)。编写第一步——定义属性类
C#是面向对象的编程语言,所以我们直接定义“属性”类,并定义类属性,针对每个类的实例对象编写实现方法。代码如下:[System.Serializable] public class BaseAttribute { //等级 public int LV; /// <summary> ///血量,魔量 /// </summary> public float HP, MP; /// <summary> ///攻击力, 防御力, 力量, 智力, 敏捷, 体力 /// </summary> public float Attack, Defend, Strong, Intelligence, Agility, Power; /// <summary> /// 攻击速度,散步速度,跑步速度,后退速度,转身移动速度,转身速度,攻击范围,经验值,暴击概率,暴击伤害百分比; /// </summary> public float AttackSpeed, MoveSpeed, RotationSpeed, AttackRange, Exp, CriticalRate, CriticalDamage; /// <summary> /// 每秒血量回复,每秒魔量回复 /// </summary> public float HPRecoverPerSecond, MPRecoverPerSecond; } [System.Serializable] public class AdditionAttribute { /// <summary> ///血量,魔量 /// </summary> public float HP, MP; /// <summary> ///攻击力, 防御力, 力量, 智力, 敏捷, 体力 /// </summary> public float Attack, Defend, Strong, Intelligence, Agility, Power; /// <summary> /// 攻击速度,散步速度,跑步速度,后退速度,转身移动速度,转身速度,攻击范围,暴击概率,暴击伤害百分比;//暴击概率和攻击范围仅由装备影响。 /// </summary> public float AttackSpeed, MoveSpeed, RotationSpeed, AttackRange, CriticalRate,CriticalDamage; /// <summary> /// 每秒血量回复,每秒魔量回复 /// </summary> public float HPRecoverPerSecond, MPRecoverPerSecond; } [System.Serializable] public class CurAttribute { /// <summary> ///血量,魔量 /// </summary> public float CurHP, CurMP; /// <summary> ///攻击力, 防御力, 力量, 智力, 敏捷, 体力 /// </summary> public float CurAttack, CurDefend, CurStrong, CurIntelligence, CurAgility, CurPower; /// <summary> /// 当前攻击速度,当前散步速度,当前跑步速度,当前后退速度,当前转身移动速度,当前转身速度,当前攻击范围,当前暴击概率, 当前暴击伤害百分比; /// </summary> public float CurAttackSpeed, CurMoveSpeed, CurRotationSpeed, CurAttackRange, CurCriticalRate, CurCriticalDamage; /// <summary> /// 每秒血量回复,每秒魔量回复 /// </summary> public float HPRecoverPerSecond, MPRecoverPerSecond; } [System.Serializable] public class SumAttribute { /// <summary> ///血量,魔量 /// </summary> public float HP, MP; /// <summary> ///攻击力, 防御力, 力量, 智力, 敏捷, 体力 /// </summary> public float Attack, Defend, Strong, Intelligence, Agility, Power; /// <summary> /// 攻击速度,移动速度,转身速度,攻击范围,暴击概率,暴击伤害百分比; /// </summary> public float AttackSpeed, MoveSpeed, RotationSpeed, AttackRange, CriticalRate, CriticalDamage; /// <summary> /// 每秒血量回复,每秒魔量回复 /// </summary> public float HPRecoverPerSecond, MPRecoverPerSecond; } [System.Serializable] public class AttributeGrowth { /// <summary> ///血量,魔量 /// </summary> public float HP, MP; /// <summary> ///攻击力, 防御力, 力量, 智力, 敏捷, 体力 /// </summary> public float Attack, Defend, Strong, Intelligence, Agility, Power; }
注释的相当仔细,一看就懂。
然后我们还需要定义一些单独存在的量:比如最高等级,最大经验值、当前等级所需经验,如果有各种动画状态,还需要单独定义步行速度(WalkSpeed)、跑步速度(RunSpeed)、左右转身时向左或向右移动的速度(TurnSpeed),或者还可以定义后退时的移动速度(BackwardSpeed),看个人需求。然后定义出上文代码中定义的类对象的实例对象,编写过程中主要是使用类的实例对象。代码:
/// <summary> /// 最高等级 /// </summary> public int MaxLV; /// <summary> /// 当前等级所需要的经验总量 /// </summary> public float NeedExpPerLV; //当前等级到下一个等级还需要的经验量 public float EXP2NextLV; //到当前为止所获得的所有经验量 public float MaxExp; //各类的实例对象: public BaseAttribute BaseStatus; public AdditionAttribute AddStatus; public CurAttribute CurStatus; public SumAttribute SumStatus; public AttributeGrowth attributeGrowth, growthPoint; //定义各种速度: public float RunSpeed; public float WalkSpeed; public float TurnSpeed; public float BackSpeed;
嗯,基本需要用到的量都已经定义好了,下一步开始编写方法使用这些量。
编写第二步——实施方法
我们首先来编写人物经验的计算方法,这里sunset个人所用的经验计算公式是:基数A * 当前等级 * 当前等级 + 基数B * 当前等级。这算是一种较为简单的计算方法了,一个一元二次方程。这个可以自行决定。先计算到当前为止所获得的所有经验量(包括当前等级到下一级),然后计算当前等级所需经验:(这里所采用的基数A和B分别为40和60)void CalculateExp() { //更新到当前等级为止的所有经验,包括本级到下一级 MaxExp = 40.0f * BaseStatus.LV * BaseStatus.LV + 60.0f * BaseStatus.LV; //更新本级到下一级所需要的经验值; NeedExpPerLV = MaxExp - (40.0f * (BaseStatus.LV - 1) * (BaseStatus.LV - 1) + 60.0f * (BaseStatus.LV - 1)); }
然后更新当前经验值:
public void UpdateExp()//更新经验值 { if (BaseStatus.LV >= MaxLV) { BaseStatus.Exp = NeedExpPerLV; BaseStatus.LV = MaxLV; } else { if(BaseStatus.Exp >= NeedExpPerLV) { GetLvUp = true; //更新当前在本级拥有经验 BaseStatus.Exp = BaseStatus.Exp - NeedExpPerLV; //更新等级 BaseStatus.LV += 1; CalculateExp(); GrowthisAdd = false; //更新属性 UpdateAttribute(); CurStatus.CurHP = SumStatus.HP; CurStatus.CurMP = SumStatus.MP; } } }
先判断当前等级是否大于最高等级,再判断当前经验是否达到当前等级所要求的经验量,如果达到就升级,并更新相关属性。升级时恢复血量和魔量到最大值。
接下来是更新相关属性的方法:
void UpdateAttribute() { if (!GrowthisAdd) { CalculateAttributePointGrowth (); BaseStatus.HP += attributeGrowth.HP; BaseStatus.MP += attributeGrowth.MP; BaseStatus.Attack += attributeGrowth.Attack; BaseStatus.Defend += attributeGrowth.Defend; BaseStatus.Strong += attributeGrowth.Strong; BaseStatus.Intelligence += attributeGrowth.Intelligence; BaseStatus.Agility += attributeGrowth.Agility; BaseStatus.Power += attributeGrowth.Power; GrowthisAdd = true; } SumStatus.Strong = BaseStatus.Strong + AddStatus.Strong; SumStatus.Intelligence = BaseStatus.Intelligence + AddStatus.Intelligence; SumStatus.Agility = BaseStatus.Agility + AddStatus.Agility; SumStatus.Power = BaseStatus.Power + AddStatus.Power; SumStatus.Attack = BaseStatus.Attack + AddStatus.Attack + Mathf.FloorToInt(SumStatus.Strong * 0.2f); SumStatus.Defend = BaseStatus.Defend + AddStatus.Defend + Mathf.FloorToInt(SumStatus.Power * 0.2f); SumStatus.HP = BaseStatus.HP + AddStatus.HP + Mathf.FloorToInt(SumStatus.Strong * 0.4f); SumStatus.MP = BaseStatus.MP + AddStatus.MP + Mathf.FloorToInt(SumStatus.Intelligence * 0.4f); SumStatus.AttackSpeed = BaseStatus.AttackSpeed + AddStatus.AttackSpeed + Mathf.FloorToInt(SumStatus.Agility * 0.2f); SumStatus.MoveSpeed = BaseStatus.MoveSpeed + AddStatus.MoveSpeed + Mathf.FloorToInt(SumStatus.Agility * 0.3f); SumStatus.RotationSpeed = BaseStatus.RotationSpeed + AddStatus.RotationSpeed + Mathf.FloorToInt(SumStatus.Agility * 0.2f); SumStatus.CriticalRate = BaseStatus.CriticalRate + AddStatus.CriticalRate; SumStatus.CriticalDamage = BaseStatus.CriticalDamage + AddStatus.CriticalDamage; CurStatus.CurAttack = SumStatus.Attack; CurStatus.CurDefend = SumStatus.Defend; CurStatus.CurStrong = SumStatus.Strong; CurStatus.CurIntelligence = SumStatus.Intelligence; CurStatus.CurAgility = SumStatus.Agility; CurStatus.CurPower = SumStatus.Power; CurStatus.CurCriticalRate = SumStatus.CriticalRate; CurStatus.CurCriticalDamage = SumStatus.CriticalDamage; }
这里主要说明一下,sunset个人定义的属性中强壮部分决定了攻击力和血量上限,体力部分决定了防御力,智力部分决定了魔法值上限,敏捷部分决定了各种速度等等,自行理解。
然后在计算更新属性方法中还定义了一种当存在升级点数加成时,计算升级属性相关的方法:
void CalculateAttributePointGrowth() { if (growthPoint.HP > 0) { attributeGrowth.HP += 2 * growthPoint.HP; } if (growthPoint.Attack > 0) { attributeGrowth.Attack += 2 * growthPoint.Attack; } if(growthPoint.MP > 0) { attributeGrowth.MP += 2 * growthPoint.MP; } if(growthPoint.Defend > 0) { attributeGrowth.Defend += 2 * growthPoint.Defend; } if(growthPoint.Strong > 0) { attributeGrowth.Strong += 2 * growthPoint.Strong; } if(growthPoint.Intelligence > 0) { attributeGrowth.Intelligence += 2 * growthPoint.Intelligence; } if(growthPoint.Agility > 0) { attributeGrowth.Agility += 2 * growthPoint.Agility; } if(growthPoint.Power > 0) { attributeGrowth.Power += 2 * growthPoint.Power; } }
这样更新属性方面的相关方法就差不多了,然后我们还要检测血量等属性值,避免血量等属性值超过总属性值。
//检测HP、MP的当前值是否超出规定,每帧调用 void CheckHPMP() { AnimatorStateInfo H_CurrentState = H_Animator.GetCurrentAnimatorStateInfo (0); if (!H_CurrentState.IsName ("Base.H_Death")) { CurStatus.CurHP += Mathf.FloorToInt(BaseStatus.HPRecoverPerSecond * 0.33f); CurStatus.CurMP += Mathf.FloorToInt(BaseStatus.MPRecoverPerSecond * 0.50f); } else { CurStatus.CurHP = 0; CurStatus.CurMP = 0; } if (CurStatus.CurHP < 0) { CurStatus.CurHP = 0; } if (CurStatus.CurMP < 0) { CurStatus.CurMP = 0; } if (CurStatus.CurHP >= SumStatus.HP) { CurStatus.CurHP = SumStatus.HP; } if (CurStatus.CurMP >= SumStatus.MP) { CurStatus.CurMP = SumStatus.MP; } }
这样属性编辑器在原始属性定义方面就差不多完成了,然而现在我们编写的还只是脚本,不能算的上是一种可视化编辑器,还需要编辑一个Editor文件来对上文定义的变量进行值的输入。Editor文件的编写在原理上是十分简单的,就是一味的套用Unity本身的制定的GUIEditor的方法就好了,编写插件也是通过这种方法进行编写的,只是编写的好坏以及是否美观简洁、是否易于输入与识别的区别而已,这当然需要大量的动手编写经验。基本的语法都可以在API文档中找到sunset在这里不再赘述给出sunset个人编写的一个简单的人物属性Editor文件的源代码:
using UnityEditor; using UnityEngine; using System.Collections; [CustomEditor(typeof(HeroStatus))] public class HeroStatusEditor : Editor { public bool ShowBaseAttribute = true; public bool ShowAddtitionAttribute = true; public bool ShowCurAttribute = true; public bool ShowSumAttribute = true; public bool ShowAttributeGrowth = true; public override void OnInspectorGUI() { HeroStatus heroStatus = (HeroStatus)target; heroStatus.HeroName = EditorGUILayout.TextField ("Hero Name:", heroStatus.HeroName); heroStatus.BaseStatus.LV = EditorGUILayout.IntField ("Hero Lv:", heroStatus.BaseStatus.LV); heroStatus.MaxLV = EditorGUILayout.IntField ("Max LV:", heroStatus.MaxLV); heroStatus.BaseStatus.Exp = EditorGUILayout.FloatField ("Hero Current Exp:", heroStatus.BaseStatus.Exp); heroStatus.EXP2NextLV = EditorGUILayout.FloatField ("Need Exp To Next LV:", (heroStatus.NeedExpPerLV - heroStatus.BaseStatus.Exp)); heroStatus.CurrentPoint = EditorGUILayout.IntField ("Growth Point:", heroStatus.CurrentPoint); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Walk Speed:" , heroStatus.WalkSpeed.ToString()); EditorGUILayout.LabelField ("Run Speed:" , heroStatus.RunSpeed.ToString()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Back Speed:" , heroStatus.BackSpeed.ToString()); EditorGUILayout.LabelField ("Turn Speed:" , heroStatus.TurnSpeed.ToString()); EditorGUILayout.EndHorizontal (); ShowCurAttribute = EditorGUILayout.Foldout (ShowCurAttribute, "Current Status:"); if (ShowCurAttribute) { EditorGUI.indentLevel++; EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("HP:", heroStatus.CurStatus.CurHP.ToString ()); EditorGUILayout.LabelField ("MP:", heroStatus.CurStatus.CurMP.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Attack:", heroStatus.CurStatus.CurAttack.ToString ()); EditorGUILayout.LabelField ("Defend:", heroStatus.CurStatus.CurDefend.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Strong:", heroStatus.CurStatus.CurStrong.ToString ()); EditorGUILayout.LabelField ("Intelligence:", heroStatus.CurStatus.CurIntelligence.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Agility:", heroStatus.CurStatus.CurAgility.ToString ()); EditorGUILayout.LabelField ("Power:", heroStatus.CurStatus.CurPower.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Attack Speed:", heroStatus.CurStatus.CurAttackSpeed.ToString ()); EditorGUILayout.LabelField ("Attack Range:", heroStatus.CurStatus.CurAttackRange.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Move Speed:", heroStatus.CurStatus.CurMoveSpeed.ToString ()); EditorGUILayout.LabelField ("Rotation Range:", heroStatus.CurStatus.CurRotationSpeed.ToString ().ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal (); EditorGUILayout.LabelField ("Cur Critical Damage:", heroStatus.CurStatus.CurCriticalDamage.ToString ()); EditorGUILayout.LabelField ("Critical Rate:", heroStatus.CurStatus.CurCriticalRate.ToString ()); EditorGUILayout.EndHorizontal (); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Cur HP Recover Per Second:", heroStatus.CurStatus.HPRecoverPerSecond.ToString()); EditorGUILayout.LabelField("Cur MP Recover Per Second:", heroStatus.CurStatus.MPRecoverPerSecond.ToString()); EditorGUILayout.EndHorizontal(); } EditorGUI.indentLevel--; EditorGUILayout.Space(); ShowBaseAttribute = EditorGUILayout.Foldout (ShowBaseAttribute, "Base Attribute"); EditorGUI.indentLevel++; if (ShowBaseAttribute) { heroStatus.BaseStatus.HP = (float)EditorGUILayout.Slider("Base HP:", heroStatus.BaseStatus.HP, 0.0f, 9999.0f); ProgressBar(heroStatus.BaseStatus.HP/9999f,"Base HP"); heroStatus.BaseStatus.MP = (float)EditorGUILayout.Slider("Base MP:", heroStatus.BaseStatus.MP, 0.0f, 9999.0f); ProgressBar(heroStatus.BaseStatus.MP/9999f,"Base MP"); heroStatus.BaseStatus.Attack = (float)EditorGUILayout.Slider("Base Attack", heroStatus.BaseStatus.Attack, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Attack/999.0f,"Base Attack"); heroStatus.BaseStatus.Defend = (float)EditorGUILayout.Slider("Base Defend", heroStatus.BaseStatus.Defend, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Defend/999.0f,"Base Defend"); heroStatus.BaseStatus.Strong = (float)EditorGUILayout.Slider("Base Strong", heroStatus.BaseStatus.Strong, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Strong/999.0f,"Base Strong"); heroStatus.BaseStatus.Intelligence = (float)EditorGUILayout.Slider("Base Intelligence", heroStatus.BaseStatus.Intelligence, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Intelligence/999.0f,"Base Intelligence"); heroStatus.BaseStatus.Agility = (float)EditorGUILayout.Slider("Base Agility", heroStatus.BaseStatus.Agility, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Agility/999.0f,"Base Agility"); heroStatus.BaseStatus.Power = (float)EditorGUILayout.Slider("Base Power", heroStatus.BaseStatus.Power, 0.0f, 999.0f); ProgressBar(heroStatus.BaseStatus.Power/999.0f,"Base Power"); heroStatus.BaseStatus.AttackSpeed = (float)EditorGUILayout.Slider("Base AttackSpeed", heroStatus.BaseStatus.AttackSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.AttackSpeed/100.0f,"Base AttackSpeed"); heroStatus.BaseStatus.MoveSpeed = (float)EditorGUILayout.Slider("Base MoveSpeed", heroStatus.BaseStatus.MoveSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.MoveSpeed/100.0f,"Base MoveSpeed"); heroStatus.BaseStatus.RotationSpeed = (float)EditorGUILayout.Slider("Base RotationSpeed", heroStatus.BaseStatus.RotationSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.RotationSpeed/100.0f,"Base RotationSpeed"); heroStatus.BaseStatus.AttackRange = (float)EditorGUILayout.Slider("Base AttackRange", heroStatus.BaseStatus.AttackRange, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.AttackRange/100.0f,"Base AttackRange"); heroStatus.BaseStatus.CriticalRate = (float)EditorGUILayout.Slider("Base CriticalRate", heroStatus.BaseStatus.CriticalRate, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.CriticalRate/100.0f,"Base CriticalRate"); heroStatus.BaseStatus.CriticalDamage = (float)EditorGUILayout.Slider("Base CriticalDamage", heroStatus.BaseStatus.CriticalDamage, 0.0f, 100.0f); ProgressBar(heroStatus.BaseStatus.CriticalDamage/100.0f,"Base CriticalDamage"); heroStatus.BaseStatus.HPRecoverPerSecond = EditorGUILayout.FloatField("HP Recover Per Second:", heroStatus.BaseStatus.HPRecoverPerSecond); ProgressBar(heroStatus.BaseStatus.HPRecoverPerSecond / 100.0f, "Base HP Recover Per Second:"); heroStatus.BaseStatus.MPRecoverPerSecond = EditorGUILayout.FloatField("MP Recover Per Second:", heroStatus.BaseStatus.MPRecoverPerSecond); ProgressBar(heroStatus.BaseStatus.MPRecoverPerSecond / 100.0f, "Base MP Recover Per Second:"); } EditorGUI.indentLevel--; EditorGUILayout.Space (); ShowAddtitionAttribute = EditorGUILayout.Foldout (ShowAddtitionAttribute, "Addtition Attribute:"); EditorGUI.indentLevel++; if (ShowAddtitionAttribute) { heroStatus.AddStatus.HP = (float)EditorGUILayout.Slider("Addtition HP:", heroStatus.AddStatus.HP, 0.0f, 9999.0f); ProgressBar(heroStatus.AddStatus.HP/9999f,"Addtition HP"); heroStatus.AddStatus.MP = (float)EditorGUILayout.Slider("Addtition MP:", heroStatus.AddStatus.MP, 0.0f, 9999.0f); ProgressBar(heroStatus.AddStatus.MP/9999f,"Addtition MP"); heroStatus.AddStatus.Attack = (float)EditorGUILayout.Slider("Addtition Attack", heroStatus.AddStatus.Attack, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Attack/999.0f,"Addtition Attack"); heroStatus.AddStatus.Defend = (float)EditorGUILayout.Slider("Addtition Defend", heroStatus.AddStatus.Defend, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Defend/999.0f,"Addtition Defend"); heroStatus.AddStatus.Strong = (float)EditorGUILayout.Slider("Addtition Strong", heroStatus.AddStatus.Strong, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Strong/999.0f,"Addtition Strong"); heroStatus.AddStatus.Intelligence = (float)EditorGUILayout.Slider("Addtition Intelligence", heroStatus.AddStatus.Intelligence, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Intelligence/999.0f,"Addtition Intelligence"); heroStatus.AddStatus.Agility = (float)EditorGUILayout.Slider("Addtition Agility", heroStatus.AddStatus.Agility, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Agility/999.0f,"Addtition Agility"); heroStatus.AddStatus.Power = (float)EditorGUILayout.Slider("Addtition Power", heroStatus.AddStatus.Power, 0.0f, 999.0f); ProgressBar(heroStatus.AddStatus.Power/999.0f,"Addtition Power"); heroStatus.AddStatus.AttackSpeed = (float)EditorGUILayout.Slider("Addtition AttackSpeed", heroStatus.AddStatus.AttackSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.AttackSpeed/100.0f,"Addtition AttackSpeed"); heroStatus.AddStatus.MoveSpeed = (float)EditorGUILayout.Slider("Addtition MoveSpeed", heroStatus.AddStatus.MoveSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.MoveSpeed/100.0f,"Addtition MoveSpeed"); heroStatus.AddStatus.RotationSpeed = (float)EditorGUILayout.Slider("Addtition RotationSpeed", heroStatus.AddStatus.RotationSpeed, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.RotationSpeed/100.0f,"Addtition RotationSpeed"); heroStatus.AddStatus.AttackRange = (float)EditorGUILayout.Slider("Addtition AttackRange", heroStatus.AddStatus.AttackRange, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.AttackRange/100.0f,"Addtition AttackRange"); heroStatus.AddStatus.CriticalRate = (float)EditorGUILayout.Slider("Addtition CriticalRate", heroStatus.AddStatus.CriticalRate, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.CriticalRate/100.0f,"Addtition CriticalRate"); heroStatus.AddStatus.CriticalDamage = (float)EditorGUILayout.Slider("Addtition CriticalDamage", heroStatus.AddStatus.CriticalDamage, 0.0f, 100.0f); ProgressBar(heroStatus.AddStatus.CriticalDamage/100.0f,"Addtition CriticalDamage"); } EditorGUI.indentLevel--; EditorGUILayout.Space (); ShowAttributeGrowth = EditorGUILayout.Foldout (ShowAttributeGrowth, "Growth Attribute:"); EditorGUI.indentLevel++; if (ShowAttributeGrowth) { EditorGUILayout.BeginHorizontal(); heroStatus.attributeGrowth.HP = EditorGUILayout.FloatField("HP:", heroStatus.attributeGrowth.HP); heroStatus.attributeGrowth.MP = EditorGUILayout.FloatField("MP:", heroStatus.attributeGrowth.MP); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); heroStatus.attributeGrowth.Attack = EditorGUILayout.FloatField("Attack:", heroStatus.attributeGrowth.Attack); heroStatus.attributeGrowth.Defend = EditorGUILayout.FloatField("Defend:", heroStatus.attributeGrowth.Defend); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); heroStatus.attributeGrowth.Strong = EditorGUILayout.FloatField("Strong:", heroStatus.attributeGrowth.Strong); heroStatus.attributeGrowth.Intelligence = EditorGUILayout.FloatField("Intelligence:", heroStatus.attributeGrowth.Intelligence); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); heroStatus.attributeGrowth.Agility = EditorGUILayout.FloatField("Agility:", heroStatus.attributeGrowth.Agility); heroStatus.attributeGrowth.Power = EditorGUILayout.FloatField("Power:", heroStatus.attributeGrowth.Power); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); heroStatus.attributeGrowth.Agility = EditorGUILayout.FloatField("Agility:", heroStatus.attributeGrowth.Agility); heroStatus.attributeGrowth.Power = EditorGUILayout.FloatField("Power:", heroStatus.attributeGrowth.Power); EditorGUILayout.EndHorizontal(); } EditorGUI.indentLevel--; EditorGUILayout.Space (); ShowSumAttribute = EditorGUILayout.Foldout (ShowSumAttribute, "Total Attribute:"); EditorGUI.indentLevel++; if (ShowSumAttribute) { EditorGUILayout.LabelField("Total HP:", heroStatus.SumStatus.HP.ToString()); ProgressBar(heroStatus.SumStatus.HP/9999f,"Total HP"); EditorGUILayout.LabelField("Total MP:", heroStatus.SumStatus.MP.ToString()); ProgressBar(heroStatus.SumStatus.MP/9999f,"Total MP"); EditorGUILayout.LabelField("Total Attack", heroStatus.SumStatus.Attack.ToString()); ProgressBar(heroStatus.SumStatus.Attack/999.0f,"Total Attack"); EditorGUILayout.LabelField("Total Defend", heroStatus.SumStatus.Defend.ToString()); ProgressBar(heroStatus.SumStatus.Defend/999.0f,"Total Defend"); EditorGUILayout.LabelField("Total Strong", heroStatus.SumStatus.Strong.ToString()); ProgressBar(heroStatus.SumStatus.Strong/999.0f,"Total Strong"); EditorGUILayout.LabelField("Total Intelligence", heroStatus.SumStatus.Intelligence.ToString()); ProgressBar(heroStatus.SumStatus.Intelligence/999.0f,"Total Intelligence"); EditorGUILayout.LabelField("Total Agility", heroStatus.SumStatus.Agility.ToString()); ProgressBar(heroStatus.SumStatus.Agility/999.0f,"Total Agility"); EditorGUILayout.LabelField("Total Power", heroStatus.SumStatus.Power.ToString()); ProgressBar(heroStatus.SumStatus.Power/999.0f,"Total Power"); EditorGUILayout.LabelField("Addtition AttackSpeed", heroStatus.SumStatus.AttackSpeed.ToString()); ProgressBar(heroStatus.SumStatus.AttackSpeed/100.0f,"Addtition AttackSpeed"); EditorGUILayout.LabelField("Addtition MoveSpeed", heroStatus.SumStatus.MoveSpeed.ToString()); ProgressBar(heroStatus.SumStatus.MoveSpeed/100.0f,"Addtition MoveSpeed"); EditorGUILayout.LabelField("Total RotationSpeed", heroStatus.SumStatus.RotationSpeed.ToString()); ProgressBar(heroStatus.SumStatus.RotationSpeed/100.0f,"Total RotationSpeed"); EditorGUILayout.LabelField("Total AttackRange", heroStatus.SumStatus.AttackRange.ToString()); ProgressBar(heroStatus.SumStatus.AttackRange/100.0f,"Total AttackRange"); EditorGUILayout.LabelField("Total CriticalRate", heroStatus.SumStatus.CriticalRate.ToString()); ProgressBar(heroStatus.SumStatus.CriticalRate/100.0f,"Total CriticalRate"); EditorGUILayout.LabelField("Total CriticalDamage", heroStatus.SumStatus.CriticalDamage.ToString()); ProgressBar(heroStatus.SumStatus.CriticalDamage/100.0f,"Total CriticalDamage"); EditorGUILayout.LabelField("Total HP Recover Per Second:", heroStatus.SumStatus.HPRecoverPerSecond.ToString()); ProgressBar(heroStatus.SumStatus.HPRecoverPerSecond / 100.0f, "Total HP Recover Per Second:"); EditorGUILayout.LabelField("Total MP Recover Per Second:", heroStatus.SumStatus.MPRecoverPerSecond.ToString()); ProgressBar(heroStatus.SumStatus.MPRecoverPerSecond / 100.0f, "Total MP Recover Per Second:"); } } public void ProgressBar (float val,string label) { Rect rect = GUILayoutUtility.GetRect (18, 18, "TextField"); EditorGUI.ProgressBar (rect, val, label); EditorGUILayout.Space (); } }
嗯,Editor文件只是一系列重复的语句,修改其中的关键词以符合各种属性就好了,是不是很简单呢?程序编写的脚本能让策划简单易懂的实现值的输入是非常重要的,写的美观简洁易懂不止是给策划方便,也是给自己方便。嗯,今天写的有点多了,现在时间也很晚了至于人物编辑器编写的剩下部分就明天下午更吧,就这样。
相关文章推荐
- unity, 内置shader下载地址
- Unity3d_用PlayerPrefs保存和读取数组
- Unity3d_UGUI加载场景进度条
- C#Socket服务器开发(Unity)
- unity3d_角色与障碍物遮挡
- Unity自定义定时器
- unity, 忽略碰撞
- unity3d ngui-TweenRotation-TweenPosition-TweenScale
- unity3d Ngui UISlider
- 開始Unity3D的学习之旅
- 【Unity3D ugui】简单控件的事件监听
- Unity Camera
- Unity Rigidbody
- Unity3D开发 - Unity3d与iOS交互开发(接入平台SDK)
- Unity中实现全局管理类的几种方式
- Unity5.0与Android交互
- Unity3D开发 - 生成unitypackage包
- Unity3D开发 - 导出iOS项目
- 高通AR增强现实多卡识别和扩展跟踪Unity
- Unity3d_Stats和优化