概述
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。
CSDN视频网址:http://edu.csdn.net/lecturer/144
前面已经给读者介绍了两个类,这两个类并没有具体对象的行为表示,给人的感觉就是一个抽象的类,接下来它们的孩子类的编写,也就是具体的类了。在这里介绍一下设计思路,游戏中的角色和怪物也有共同的属性,比如Buff、Debuff、伤害、移动等等,将这些共同的属性可以放在我们已经规划好的BaseCharacter类中,该类主要实现的就是英雄和怪物的基础属性和方法,代码如下所示:
public class BaseCharacter:BaseActor
{
public GameObject m_MPoint;
/// <summary>
/// 攻击特效最长持续时间
/// </summary>
protected float m_AttackedEffTimeMax;
/// <summary>
///
/// </summary>
protected bool m_bCameraFrustum;
/// <summary>
/// 标识碰撞后是否移动
/// </summary>
protected bool m_bCollisionMove;
protected bool m_bMute;
protected int m_BulletUidCount;
/// <summary>
///
/// </summary>
protected CapsuleCollider m_CapsuleCol;
/// <summary>
/// 移动朝向
/// </summary>
protected Vector3 m_MoveDirection;
/// <summary>
/// 移动至向量位置
/// </summary>
protected Vector3 m_MoveToPos;
/// <summary>
/// 屏幕向量
/// </summary>
protected Vector3 m_ScreenPos;
/// <summary>
/// 打昏特效
/// </summary>
protected GameObject m_StunEff;
/// <summary>
///
/// </summary>
protected float m_StunTimeMax;
/// <summary>
/// 队伍Id
/// </summary>
protected int m_TeamId;
protected float m_TurnTimeMax;
/// <summary>
/// 角色状态
/// </summary>
protected CharStat m_Stat = new CharStat();
/// <summary>
/// Buff 列表
/// </summary>
protected List<BaseBuff> m_Buffs = new List<BaseBuff>();
/// <summary>
/// DeBuff 列表
/// </summary>
protected List<BaseDeBuff> m_Debuffs = new List<BaseDeBuff>();
public override void Init(int uid)
{
base.Init(uid);
this.m_bMute = false;
this.m_FBX.SendMessage("SetParent", gameObject);
this.m_CapsuleCol = this.gameObject.GetComponent<CapsuleCollider>();
}
public override void Enable(Vector3 pos)
{
base.Enable(pos);
this.m_MoveDirection = Vector3.zero;
this.m_BulletUidCount = 0;
this.m_bCameraFrustum = true;
this.m_AttackedEffTimeMax = 0f;
this.m_StunTimeMax = 0f;
this.m_bCollisionMove = true;
this.m_Buffs.Clear();
this.m_Debuffs.Clear();
}
protected override void UpdateObj(float delta)
{
base.UpdateObj(delta);
this.UpdateBuffs(delta);
this.UpdateDebuffs(delta);
this.CheckInCameraFrustum();
//if(this.GetCurState() != 13 && this.m_bCollisionMove &&
// Application.loadedLevelName != "03_LobbyScene" &&
// gameObject.GetComponent<Rigidbody>().velocity.magnitude <= 0.1f)
//{
// gameObject.rigidbody.velocity = GetDirection() * delta * 3f;
//}
}
public override void OnObjectDestroy()
{
this.m_StunEff = null;
base.OnObjectDestroy();
}
/// <summary>
/// 更新增益buff
/// </summary>
/// <param name="delta"></param>
protected void UpdateBuffs(float delta)
{
for (int i = 0; i < this.m_Buffs.Count; i++)
{
this.m_Buffs[i].OnUpdate(delta);
}
for (int j = this.m_Buffs.Count - 1; j >= 0; j--)
{
BaseBuff buff = this.m_Buffs[j];
buff.m_Time -= delta;
if (this.m_Buffs[j].m_Time < 0f)
{
this.m_Buffs[j].OnDestroy();
this.m_Buffs.RemoveAt(j);
}
}
}
/// <summary>
/// 更新减益buff
/// </summary>
/// <param name="delta"></param>
protected void UpdateDebuffs(float delta)
{
for (int i = 0; i < this.m_Debuffs.Count; i++)
{
this.m_Debuffs[i].OnUpdate(delta);
}
for (int j = this.m_Debuffs.Count - 1; j >= 0; j--)
{
BaseDeBuff debuff = this.m_Debuffs[j];
debuff.m_Time -= delta;
if (this.m_Debuffs[j].m_Time < 0f)
{
this.m_Debuffs[j].OnDestroy();
this.m_Debuffs.RemoveAt(j);
}
}
}
public void EnableCapsuleCol(bool flag)
{
if (this.m_CapsuleCol != null)
this.m_CapsuleCol.enabled = flag;
}
/// <summary>
/// 获取英雄角色的身体半径
/// </summary>
/// <returns></returns>
public float GetBodyRadius()
{
if (this.m_CapsuleCol != null)
return this.m_CapsuleCol.radius;
return 0f;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public int GetBulletUid()
{
return this.m_BulletUidCount++;
}
public void SetTeamId(int teamId)
{
this.m_TeamId = teamId;
}
public int GetTeamId()
{
return this.m_TeamId;
}
/// <summary>
/// 设定等级
/// </summary>
/// <param name="level"></param>
public void SetLevel(int level)
{
if (m_ObjType == EnumDefine.ObjType.Mon)
{
}
this.SetGrowth(EnumDefine.GrowthT.Min, level);
this.SetStatusByLevel(level);
}
/// <summary>
/// 增加buff
/// </summary>
/// <param name="type"></param>
/// <param name="time"></param>
/// <param name="value"></param>
protected void AddBuff(EnumDefine.BuffType type, float time, float value)
{
BaseBuff buff = this.m_Buffs.Find(x => x.GetBuffType() == type);
if (buff != null)
{
buff.OnInit(type, time, this, value);
}
else
{
BaseBuff instance = BaseBuff.GetInstance(type);
instance.OnInit(type, time, this, value);
this.m_Buffs.Add(instance);
}
;
}
/// <summary>
/// 增加Debuff
/// </summary>
/// <param name="type"></param>
/// <param name="time"></param>
/// <param name="value"></param>
protected void AddDebuff(EnumDefine.DeBuffT type, float time, float value)
{
BaseDeBuff debuff = this.m_Debuffs.Find(x => x.GetDebuffType() == type);
if (debuff != null)
{
debuff.OnInit(type, time, this, value);
}
else
{
BaseDeBuff instance = BaseDeBuff.GetInstance(type);
instance.OnInit(type, time, this, value);
this.m_Debuffs.Add(instance);
}
}
/// <summary>
/// 获取Buff 值
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
protected float GetBuffValue(EnumDefine.BuffType type)
{
BaseBuff buff = this.m_Buffs.Find(x => x.GetBuffType() == type);
if (buff != null)
return buff.GetValue();
return 0f;
}
/// <summary>
/// 获取 DeBuff 值
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
protected float GetDeBuffValue(EnumDefine.DeBuffT type)
{
BaseDeBuff debuff = this.m_Debuffs.Find(x => x.GetDebuffType() == type);
if (debuff != null)
return debuff.GetValue();
return 0f;
}
/// <summary>
/// 检查是否在摄像机视锥体范围内
/// (视锥体(frustum),是指场景中摄像机的可见的一个锥体范围。它有上、下、左、右、近、远,共6个面组成。在视锥体内的景物可见,反之则不可见。为提高性能,只对其中与视锥体有交集的对象进行绘制。)
/// </summary>
protected void CheckInCameraFrustum()
{
this.m_ScreenPos = Camera.main.WorldToScreenPoint(gameObject.transform.localPosition);
if (this.m_ScreenPos.z <= 0f)
{
this.m_ScreenPos.x *= -1f;
this.m_ScreenPos.y *= -1f;
}
if ((this.m_ScreenPos.x > Screen.width) || (this.m_ScreenPos.x < 0f))
{
this.m_bCameraFrustum = false;
}
else
{
this.m_bCameraFrustum = true;
}
}
/// <summary>
/// 获得屏幕向量
/// </summary>
/// <returns></returns>
public Vector3 GetScreenPos()
{
return this.m_ScreenPos;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool IsInnerCameraFrustum()
{
return this.m_bCameraFrustum;
}
/// <summary>
/// 是否可以被攻击
/// </summary>
/// <returns></returns>
public virtual bool IsPossibleAttacked()
{
if (m_CurState == 1) //
{
return false;
}
if (m_CurState == 13) //死亡状态
return false;
return true;
}
/// <summary>
/// 根据当前状态判定是否在Move
/// </summary>
/// <returns></returns>
public virtual bool IsPossibleMoveTo()
{
switch (m_CurState)
{
case 1:
case 13: //Die
case 9: //Slide 滑动
case 10: //Down 打到
case 12: //Stun 打昏
case 7: //CriticalStiff
return false;
}
return true;
}
/// <summary>
/// 是否在使用技能
/// </summary>
/// <returns></returns>
public virtual bool IsPossibleSkill()
{
switch (m_CurState)
{
case 1:
case 13:
case 9:
case 10:
case 12:
case 7:
return false;
}
return true;
}
/// <summary>
///
/// </summary>
/// <param name="flag"></param>
public void SetCollisionMove(bool flag)
{
this.m_bCollisionMove = flag;
}
/// <summary>
///
/// </summary>
/// <param name="growthT"></param>
/// <returns></returns>
protected bool CheckGrowth(EnumDefine.GrowthT growthT)
{
if ((growthT >= EnumDefine.GrowthT.Min) && (growthT < EnumDefine.GrowthT.Max))
{
return true;
}
return false;
}
/// <summary>
/// 设置成长属性
/// </summary>
/// <param name="growthT"></param>
/// <param name="value"></param>
public void SetGrowth(EnumDefine.GrowthT growthT, int value)
{
if (this.CheckGrowth(growthT))
{
this.m_Stat.GrowthEnc[(int)growthT] = AhHelper.XEncInt(value);
}
}
/// <summary>
/// 获取成长
/// </summary>
/// <param name="growthT"></param>
/// <returns></returns>
public virtual int GetGrowth(EnumDefine.GrowthT growthT)
{
if (!this.CheckGrowth(growthT))
{
return 0;
}
return AhHelper.XDecToInt(this.m_Stat.GrowthEnc[(int)growthT]);
}
/// <summary>
///
/// </summary>
/// <param name="baseStatT"></param>
/// <param name="value"></param>
public void SetStatusBase(EnumDefine.BaseStatT baseStatT,float value)
{
if (this.CheckStatusBase(baseStatT))
{
this.m_Stat.BaseStr[(int)baseStatT] = AhHelper.EncFloat(value);
}
}
/// <summary>
/// 设定等级状态
/// </summary>
/// <param name="level"></param>
protected virtual void SetStatusByLevel(int level)
{
//Debug.Log("Virtual Func");
}
public void SetStatusOption(EnumDefine.OptT optT, float value)
{
if (CheckStatusOption(optT))
{
this.m_Stat.OptStr[(int)optT] = AhHelper.EncFloat(value);
}
}
/// <summary>
///
/// </summary>
/// <param name="baseStateType"></param>
/// <returns></returns>
protected bool CheckStatusBase(EnumDefine.BaseStatT baseStateType)
{
if ((baseStateType >= EnumDefine.BaseStatT.MIN) && (baseStateType < EnumDefine.BaseStatT.MAX))
{
return true;
}
return false;
}
protected bool CheckStatusOption(EnumDefine.OptT optionType)
{
if (optionType >= EnumDefine.OptT.Min && optionType < EnumDefine.OptT.Max)
{
return true;
}
return false;
}
/// <summary>
/// 获取基础状态属性
/// </summary>
/// <param name="baseType"></param>
/// <returns></returns>
public virtual float GetStatusBase(EnumDefine.BaseStatT baseType)
{
if (!this.CheckStatusBase(baseType))
{
return 0f;
}
float num = AhHelper.DecToFloat(this.m_Stat.BaseStr[(int)baseType]);
float statusBaseP = 0f;
if (PlayerHelper.IsPvPMode())
{
statusBaseP = this.GetStatusBaseP(baseType, true);
}
else
{
statusBaseP = this.GetStatusBaseP(baseType, false);
}
if (baseType == EnumDefine.BaseStatT.MPC)
{
return (num + statusBaseP);
}
return num + (num * (statusBaseP / 100f));
}
/// <summary>
///
/// </summary>
/// <param name="baseType"></param>
/// <returns></returns>
public virtual float GetStatusBaseOrg(EnumDefine.BaseStatT baseType)
{
if (!this.CheckStatusBase(baseType))
{
return 0f;
}
return AhHelper.DecToFloat(this.m_Stat.BaseStr[(int)baseType]);
}
/// <summary>
/// 获取基础状态(PVP)
/// </summary>
/// <param name="baseType"></param>
/// <param name="addPvp"></param>
/// <returns></returns>
public virtual float GetStatusBaseP(EnumDefine.BaseStatT baseType, bool addPvp = false)
{
if (!CheckStatusBase(baseType))
{
return 0f;
}
float statusOption = 0f;
switch (baseType)
{
case EnumDefine.BaseStatT.MPC:
return this.GetStatusOption(EnumDefine.OptT.MPA);
case EnumDefine.BaseStatT.MHP:
statusOption = this.GetStatusOption(EnumDefine.OptT.HPU);
if (addPvp)
{
statusOption += this.GetStatusOption(EnumDefine.OptT.HPU_PVP);
}
return statusOption;
case EnumDefine.BaseStatT.MMP:
return this.GetStatusOption(EnumDefine.OptT.MPU);
case EnumDefine.BaseStatT.ATT:
statusOption = this.GetStatusOption(EnumDefine.OptT.ATTR);
if (addPvp)
statusOption += this.GetStatusOption(EnumDefine.OptT.ATTR_PVP);
return statusOption;
case EnumDefine.BaseStatT.DEF:
statusOption = this.GetStatusOption(EnumDefine.OptT.DEFR);
if (addPvp)
statusOption += this.GetStatusOption(EnumDefine.OptT.DEFR_PVP);
return statusOption;
case EnumDefine.BaseStatT.MS:
return this.GetStatusOption(EnumDefine.OptT.MSR);
}
return statusOption;
}
/// <summary>
///
/// </summary>
/// <param name="optionType"></param>
/// <returns></returns>
public virtual float GetStatusOption(EnumDefine.OptT optionType)
{
if (!this.CheckStatusOption(optionType))
return 0f;
float num = AhHelper.DecToFloat(this.m_Stat.OptStr[(int)optionType]);
switch (optionType)
{
case EnumDefine.OptT.ATTR:
num += this.GetBuffValue(EnumDefine.BuffType.MIN);
break;
case EnumDefine.OptT.DEFR:
num += this.GetBuffValue(EnumDefine.BuffType.DEF_UP);
break;
case EnumDefine.OptT.ASR:
num += this.GetBuffValue(EnumDefine.BuffType.AS_UP);
break;
case EnumDefine.OptT.MSR:
num += this.GetDeBuffValue(EnumDefine.DeBuffT.IC);
break;
}
if(HasDebuff(EnumDefine.DeBuffT.CS) && optionType == EnumDefine.OptT.DEFR){
num+= this.GetDeBuffValue(EnumDefine.DeBuffT.CS);
}
return num;
}
/// <summary>
///
/// </summary>
/// <param name="outDmgAttT"></param>
/// <param name="outValue"></param>
public void GetDmgAttT(out EnumDefine.DmgAttT outDmgAttT, out float outValue)
{
float statusOption = 0f;
statusOption = GetStatusOption(EnumDefine.OptT.Min);
if (statusOption > 0f)
{
outDmgAttT = EnumDefine.DmgAttT.PS;
outValue = statusOption;
}
else
{
statusOption = this.GetStatusOption(EnumDefine.OptT.IDR);
if (statusOption > 0f)
{
outDmgAttT = EnumDefine.DmgAttT.IC;
outValue = statusOption;
}
else
{
statusOption = this.GetStatusOption(EnumDefine.OptT.FDR);
if (statusOption > 0f)
{
outDmgAttT = EnumDefine.DmgAttT.FR;
outValue = statusOption;
}
else
{
statusOption = this.GetStatusOption(EnumDefine.OptT.TDR);
if (statusOption > 0f)
{
outDmgAttT = EnumDefine.DmgAttT.TD;
outValue = statusOption;
}
else
{
outDmgAttT = EnumDefine.DmgAttT.Min;
outValue = 0f;
}
}
}
}
}
public virtual EnumDefine.AttackedEffT ResearchAttEffType(EnumDefine.AttackedEffT srcType)
{
return srcType;
}
protected bool HasDebuff(EnumDefine.DeBuffT type)
{
return (this.m_Debuffs.Find(x => x.GetDebuffType() == type) != null);
}
public bool IsDead()
{
return m_CurState == 13;
}
/// <summary>
/// 播放受击效果
/// </summary>
/// <param name="attackerPos"></param>
/// <param name="effId"></param>
/*
public void PlayAttackedEff(Vector3 attackerPos, int effId)
{
Vector3 vector = gameObject.transform.position - attackerPos;
vector.Normalize();
Vector3 pos = gameObject.transform.position - this.m_CapsuleCol.radius * vector;
pos += this.m_CapsuleCol.center;
FxManager.PlayEff(effId, pos, 0f);
ShineEff(0.15f);
}
*/
public virtual void PlayAttackedEff(Vector3 pos, int effId, EnumDefine.EffT efft = EnumDefine.EffT.HeroEffect) {
if (m_MPoint != null) {
GameObject effObj = FxManager.PlayEff(effId, GetDirection(), m_MPoint.transform.position, 0.5f, efft);
effObj.transform.parent = m_MPoint.transform;
effObj.transform.localPosition = Vector3.zero;
effObj.transform.localEulerAngles = Vector3.zero;
//DebugLog.Log("PlayAttackedEff:" + effId);
}
}
/// <summary>
/// 自残
/// 一般用在Debuff状态下
/// </summary>
/// <param name="damage"></param>
/// <param name="resultHp"></param>
/// <param name="effId"></param>
/// <param name="numEffId"></param>
public virtual void SelfDamage(float damage, float resultHp, int effId, int numEffId)
{
this.PlayAttackedEff(gameObject.transform.position, effId, EnumDefine.EffT.PublicEffect);
}
public enum eState
{
None,
Sleep,
Advent,
Idle,
Move,
MoveTo,
Turn,
CriticalStiff, //至命最后一击
Stiff,
Slide, //滑动
Down,
StunSlide,
Stun,
Die,
Max
}
}
在主要的函数中都有代码注释,读者可以参考,给出类的实现,是给读者设计时做一个参考使用的。
最后
以上就是烂漫镜子为你收集整理的Unity MMO游戏架构设计之角色设计二的全部内容,希望文章能够帮你解决Unity MMO游戏架构设计之角色设计二所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复