arpg游戏 unity3d
2018-09-26 20:09:00 weixin_30316097 阅读数 4

百度网盘下载

课程目录:

1网络连接 (unity NetWork与socket的对比)(流畅)

2登陆UI制作 (登录协议与模型定制 及流程开发)

3U注册面板制作(流畅)

4警告弹窗制作(流畅)

5流程与状态控制

6登陆按钮脚的添加、协议定制、消息发送及json编码解码(流畅)

7注册通信功能制作及消息解析

8登陆流程添加以及loading条界面制作(流畅)

9登陆成功跳转场景以及loading的制作(流畅)

10角色选择UI及创建面板制作(一)(流畅)

11角色选择UI及创建面板制作(二)(流畅)

12角色选择UI及创建面板制作(三)

13角色选择UI及创建面板制作(四)

14角色选择UI及创建面板制作(五)

15角色选择UI及创建面板制作(六)

16角色选择UI及创建面板制作(七)

17地图功能--进入协议监听

18地图功能-角色进入地图对象生成

19角色模型制作

20角色相机绑定

21游戏操控UI制作(推荐使用方式)

22移动UI操作逻辑及消息处理流程

23移动监听及角色状态、动画管理器定义

24让大家一起跑起来

25下线处理、聊天UI制作及功能实现

 

下载地址:百度网盘下载

转载于:https://www.cnblogs.com/zd-aw123/p/9709330.html

2015-05-27 21:54:39 jcracker 阅读数 1157


2018-09-26 20:09:00 weixin_30663391 阅读数 3

百度网盘下载

课程目录:

1网络连接 (unity NetWork与socket的对比)(流畅)

2登陆UI制作 (登录协议与模型定制 及流程开发)

3U注册面板制作(流畅)

4警告弹窗制作(流畅)

5流程与状态控制

6登陆按钮脚的添加、协议定制、消息发送及json编码解码(流畅)

7注册通信功能制作及消息解析

8登陆流程添加以及loading条界面制作(流畅)

9登陆成功跳转场景以及loading的制作(流畅)

10角色选择UI及创建面板制作(一)(流畅)

11角色选择UI及创建面板制作(二)(流畅)

12角色选择UI及创建面板制作(三)

13角色选择UI及创建面板制作(四)

14角色选择UI及创建面板制作(五)

15角色选择UI及创建面板制作(六)

16角色选择UI及创建面板制作(七)

17地图功能--进入协议监听

18地图功能-角色进入地图对象生成

19角色模型制作

20角色相机绑定

21游戏操控UI制作(推荐使用方式)

22移动UI操作逻辑及消息处理流程

23移动监听及角色状态、动画管理器定义

24让大家一起跑起来

25下线处理、聊天UI制作及功能实现

 

下载地址:百度网盘下载

转载于:https://www.cnblogs.com/zd-aw123/p/9709330.html

2015-06-04 21:44:38 sunsetv8 阅读数 3759

在上一篇博客中,已经编写了人物属性编辑器的大部分,但是光有一些属性的定义并没有什么卵用,我们还需要添加在角色受到伤害时,反映在人物属性上的变化,或者状态的变化。其实说到底,这部分也就是编写两个方法来接收值,改变值得概念罢了,并没有什么神奇之处。但是,在接收到值之前,值在两个模块之间进行传递的方法则根据不同的设计模式而各有不同,在这篇博客的内容,sunset也不打算对设计模式进行详细深究先明白怎么编写基础的函数方法,至于这个方面等以后再特别开一篇博客仔细介绍,如果对“设计模式”这种东西有特别感情,特别想知道,sunset推荐一本书籍《C++设计模式》,作者是一名老外,名字叫什么记不清了,可以参阅或者自行度娘。先声明sunset在这里使用的设计模式是单例模式,是比较常用也比较简单易于理解的一种设计模式。
简单的说,单例模式用法就是:A与B之间只知道对方的存在,但对于对方的信息全然不知,两者之间的交互关系仅仅通过第三方进行。也就是说,A不拥有B的信息,B也不拥有A的信息,信息传递是通过第三方(Camera)进行的。嗯,先进性简单大概的了解,详细以后再说。
回归正题,先编写一个角色接收普通伤害的方法,直接给代码吧:

public void HeroGetDamage(float Damage)
    {
        if (CurStatus.CurAgility < EnemyPower)
        {
            Hit = 100.0f;
        }
        else if (CurStatus.CurAgility > EnemyPower)
        {
            Hit = 40;
        }
        else if (CurStatus.CurAgility == EnemyPower)
        {
            Hit = 80.0f;
        }
        if (Random.Range(0.0f, 100.0f) <= Hit)//决定是否闪避
        {
            if (CurStatus.CurDefend > EnemyAttack)//根据敌人攻击力和自己防御力决定普通伤害
            {
                Damage = Damage * 0.75f;
            }
            CurStatus.CurHP -= Damage;
        }

    }

解释一下,sunset在编写这个方法时使用的规则,即个人制定的简单伤害计算方式:
普通攻击伤害计算方式:
根据双方的敏捷与体力进行判断,
例如A收到伤害:
如果A的敏捷大于B的Power, 那么击中值(Hit)为40;
如果A的敏捷等于B 的power, 那么击中值(Hit)为80;
如果A的敏捷小于B的power, 那么击中值(Hit)为100, 即百分百命中;
之后如果判定命中,再根据双方的攻击力和防御力经行判断
如果A的防御力大于B的攻击力
那么伤害为原始普通伤害的75%;
通过这种方式进行计算与编写后就会得出上述的代码。但是代码中的Damage值不是直接由Enemy攻击时传递过来的,上文已经大概介绍过原理了,不再赘述。同时,在Enemy发出攻击时,还应将Enemy自身的各项属性进行传递,以利用于进行上述方法。所以还需要这样一个方法,代码:

public void GetParametersFromEnemy(float _EnemyHP, float _EnemyMP, float _EnemyAttack, float _EnemyDefend, float _EnemyStrong, float _EnemyIntelligence, float _EnemyAgility, float _EnemyPower, int _EnemyLv)
    {
        EnemyHP = _EnemyHP;
        EnemyMP = _EnemyMP;
        EnemyAttack = _EnemyAttack;
        EnemyDefend = _EnemyDefend;
        EnemyStrong = _EnemyStrong;
        EnemyIntelligence = _EnemyIntelligence;
        EnemyAgility = _EnemyAgility;
        EnemyPower = _EnemyPower;
    }

很简单,不解释。
然后是受到某些Debuff技能时,角色属性的变化,比如受到降低敏捷,攻击力,防御力等技能时需要用到的方法,但是首先得先枚举出所有可能受到降低的属性,只需要在该脚本中编写一个枚举就好了,举例代码:

public enum AddAttribute
    {
        /// <summary>
        /// 直接影响血量上限
        /// </summary>
        HP,

        /// <summary>
        /// 直接影响魔法值上限
        /// </summary>
        MP,

        /// <summary>
        /// 攻击力
        /// </summary>
        Attack,

        /// <summary>
        /// 防御力
        /// </summary>
        Defend,

        /// <summary>
        /// 力量,影响每秒HP的恢复速率;影响HP上限
        /// </summary>
        Strong,

        /// <summary>
        /// 智力,影响魔法值MP上限,以及每秒魔法的恢复速率,
        /// </summary>
        Intelligence,

        /// <summary>
        /// 敏捷,影响攻击速度AttackSpeed;转身速率RotationSpeed;移动速度MoveSpeed
        /// </summary>
        Agility,
        /// <summary>
        /// 体力,影响HP的上限
        /// </summary>
        Power,
        /// <summary>
        /// 攻击范围
        /// </summary>
        AttackRange,

    }
public void HeroGetDebuff(AddAttribute attribute, float Value)
    {
        if (attribute == AddAttribute.HP) 
        {
            AddStatus.HP -= Value;
        }
        if (attribute == AddAttribute.MP) 
        {
            AddStatus.MP -= Value;
        }
        if (attribute == AddAttribute.Attack) 
        {
            AddStatus.Attack -= Value;
        }
        if (attribute == AddAttribute.Defend) 
        {
            AddStatus.Defend -= Value;
        }
        if (attribute == AddAttribute.Strong) 
        {
            AddStatus.Strong -= Value;
        }
        if (attribute == AddAttribute.Intelligence) 
        {
            AddStatus.Intelligence -= Value;
        }
        if (attribute == AddAttribute.Agility) 
        {
            AddStatus.Agility -= Value;
        }
        if (attribute == AddAttribute.Power) 
        {
            AddStatus.Power -= Value;
        }

        GrowthisAdd = true;

        UpdateAttribute ();
    }

收到Debuff后,开始相应属性的变化。然而debuff只可能时暂时性的,不可能一直存在,所以,我们还需要编写一个方法来设定debuff结束时恢复各项属性到原值的方法。代码:

public void DebuffComplete(AddAttribute attribute, float Value)
    {
        if (attribute == AddAttribute.HP) 
        {
            AddStatus.HP += Value;
        }
        if (attribute == AddAttribute.MP) 
        {
            AddStatus.MP += Value;
        }
        if (attribute == AddAttribute.Attack) 
        {
            AddStatus.Attack += Value;
        }
        if (attribute == AddAttribute.Defend) 
        {
            AddStatus.Defend += Value;
        }
        if (attribute == AddAttribute.Strong) 
        {
            AddStatus.Strong += Value;
        }
        if (attribute == AddAttribute.Intelligence) 
        {
            AddStatus.Intelligence += Value;
        }
        if (attribute == AddAttribute.Agility) 
        {
            AddStatus.Agility += Value;
        }
        if (attribute == AddAttribute.Power) 
        {
            AddStatus.Power += Value;
        }

        GrowthisAdd = true;

        UpdateAttribute ();
    }
}

同样,debuff时间结束后,根据相应的属性进行恢复。其中,什么该给予debuff,什么时候该结束debuff,是由发出者进行计算并且判断的。接收者只负责接收并且做出改变。当角色为发出者,Enemy作为接收者时,也是同样的道理。
嗯,人物属性编辑器写到这里就差不多了,这个是sunset自己写的角色属性编辑器的Inspector面板样式:
角色属性编辑器
详细内容:角色属性编辑器详细
大致完成后就是这样的编辑器,是不是有一种在使用插件感觉呢?
角色属性编辑器的编写就差不多到这里结束了,在明后天,sunset会继续给出编写一款ARPG游戏的流程代码,今天就先到这里为止了吧。

2015-06-03 23:39:34 sunsetv8 阅读数 8492

今天考完了大学最后一门考试,是瞬间感觉轻松了一点,花了一天多的时间预习一本书,马上就去考试了,就结果而言还是不错的。但是不知道是一种解脱,还是马上要戴上的一种新的枷锁。总归还是不错的。好了,闲话少扯,继续谈谈如何制作一款ARPG游戏,sunset在上两篇博客中已经介绍过了几种常见的ARPG游戏的人物控制方式,都比较简单,易于理解。接下来来看看制作ARPG游戏还需要什么,先从玩家可操作的角色出发,我们还需要人物的血量,或者用于释放魔法的魔量,这样就转入一种新的概念——人物属性。下面开始sunset个人编写的可视化人物属性编辑器:

人物属性分析

我们不能还没有经过分析或者思考就去动手写代码,这样只会一味给自己增加难度,延后代码编写完成的时间,这也是软件工程的基本理论。在首先编写代码之前,先来分析一下:我们需要什么?一个属性编辑器;这个编辑器中包含哪些属性?只要玩过一定数量的游戏,就会明白游戏人物一般都会有移动速度,攻击速度,攻击力,防御力等等属性值。我举例一款对属性比较看重的游戏——《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文件只是一系列重复的语句,修改其中的关键词以符合各种属性就好了,是不是很简单呢?程序编写的脚本能让策划简单易懂的实现值的输入是非常重要的,写的美观简洁易懂不止是给策划方便,也是给自己方便。嗯,今天写的有点多了,现在时间也很晚了至于人物编辑器编写的剩下部分就明天下午更吧,就这样。

unity3D 游戏工具类

阅读数 473

Unity3d 游戏物体

阅读数 1019

没有更多推荐了,返回首页