Unity3D自學筆記——架構應用(十)角色屬性
阿新 • • 發佈:2019-01-22
角色屬性
效果圖
類圖
Attribute
提供公共的引數,每個引數都有兩個值
Atk, 基礎值,就是白屬性
AtkMax, 計算後的值,就是附魔,升級,強化,鑲嵌,充人民幣後的值
public abstract class Attribute
{
private Attribute m_Parent;
public int Hp { get; set; }
public int Mp { get; set; }
public int Atk { get; set; }
public int Def { get; set; }
public int Spd { get; set; }
public int Hit { get; set; }
public double CriticalRate { get; set; }
public double AtkSpd { get; set; }
public double AtkRange { get; set; }
public double MoveSpd { get; set; }
public int HpMax { get; set; }
public int MpMax { get; set; }
public int AtkMax { get; set; }
public int DefMax { get; set; }
public int SpdMax { get; set; }
public int HitMax { get; set; }
public double CriticalRateMax { get; set; }
public double AtkSpdMax { get; set; }
public double AtkRangeMax { get; set; }
public double MoveSpdMax { get ; set; }
public abstract void Calculate();
protected void SetParent(AttributeNode child)
{
child.m_Parent = this.m_Parent;
}
public Attribute GetParent()
{
return this.m_Parent;
}
}
AttributNode
繼承Attribute,遞迴實現Caculate,然後實現新增節點和刪除節點
就是給白屬性不斷的加各種效果
public class AttributeNode : Attribute
{
private List<Attribute> m_NodeList = new List<Attribute>();
public override void Calculate()
{
this.HpMax = this.Hp;
this.MpMax = this.Mp;
this.AtkMax = this.Atk;
this.DefMax = this.Def;
this.SpdMax = this.Spd;
this.HitMax = this.Hit;
this.CriticalRateMax = this.CriticalRate;
this.AtkSpdMax = this.AtkSpd;
this.AtkRangeMax = this.AtkRange;
this.MoveSpdMax = this.MoveSpd;
foreach (AttributeNode node in m_NodeList)
{
if (node.NodeCount() > 0)
{
node.Calculate();
}
this.HpMax += node.HpMax;
this.MpMax += node.MpMax;
this.AtkMax += node.AtkMax;
this.DefMax += node.DefMax;
this.SpdMax += node.SpdMax;
this.HitMax += node.HitMax;
this.CriticalRateMax += node.CriticalRateMax;
this.AtkSpdMax += node.AtkSpdMax;
this.MoveSpdMax += node.MoveSpdMax;
}
}
public int NodeCount()
{
return m_NodeList.Count;
}
public void AddNode(AttributeNode node)
{
m_NodeList.Add(node);
}
public void RemoveNode(AttributeNode node)
{
m_NodeList.Remove(node);
}
}
AttributeRoot
最頂級節點,就是角色屬性
最開始沒有Root類的,但是在處理當前血量時卡了很久
按照設計Hp應該是英雄的基礎屬性(1級的屬性),它不能變,不然一執行Caculate就跟開掛樣,不斷增加,所以還需要一個CurrentHp 來等於 MaxHp。又不想在PlayerInfo裡面又單獨定義一套屬性,所以就提取了Root類,畢竟主角光環,它特殊。可以看到大多方法是和Node一樣的,只是多了一個Caculate(bool),作為初始化是將HpCur = HpMax用。不用Root繼承Node的原因是,減小類之間的耦合關係,怕到後期變化過大導致不易修改。
public class AttributeRoot : Attribute
{
public int HpCur { get; set; }
public int MpCur { get; set; }
public int AtkCur { get; set; }
public int DefCur { get; set; }
public int SpdCur { get; set; }
public int HitCur { get; set; }
public double CriticalRateCur { get; set; }
public double AtkSpdCur { get; set; }
public double AtkRangeCur { get; set; }
public double MoveSpdCur { get; set; }
private List<Attribute> m_NodeList = new List<Attribute>();
public override void Calculate()
{
this.HpMax = this.Hp;
this.MpMax = this.Mp;
this.AtkMax = this.Atk;
this.DefMax = this.Def;
this.SpdMax = this.Spd;
this.HitMax = this.Hit;
this.CriticalRateMax = this.CriticalRate;
this.AtkSpdMax = this.AtkSpd;
this.AtkRangeMax = this.AtkRange;
this.MoveSpdMax = this.MoveSpd;
foreach (AttributeNode node in m_NodeList)
{
if (node.NodeCount() > 0)
{
node.Calculate();
}
this.HpMax += node.HpMax;
this.MpMax += node.MpMax;
this.AtkMax += node.AtkMax;
this.DefMax += node.DefMax;
this.SpdMax += node.SpdMax;
this.HitMax += node.HitMax;
this.CriticalRateMax += node.CriticalRateMax;
this.AtkSpdMax += node.AtkSpdMax;
this.MoveSpdMax += node.MoveSpdMax;
}
}
public void Calculate(bool isInit)
{
Calculate();
if (isInit)
{
this.HpCur = this.HpMax;
this.MpCur = this.MpMax;
this.AtkCur = this.AtkMax;
this.DefCur = this.DefMax;
this.SpdCur = this.SpdMax;
this.HitCur = this.HitMax;
this.CriticalRateCur = this.CriticalRateMax;
this.AtkSpdCur = this.AtkSpdMax;
this.MoveSpdCur = this.MoveSpdMax;
}
}
public int NodeCount()
{
return m_NodeList.Count;
}
public void AddNode(AttributeNode node)
{
m_NodeList.Add(node);
}
public void RemoveNode(AttributeNode node)
{
m_NodeList.Remove(node);
}
}
PlayerStatus
掛在角色上的
目前實現了當角色在場景中建立成功後,呼叫Load事件進行初始化。這裡把Lv和Exp單獨抽出來,是沒有考慮裝備或者其他技能對LV和經驗的變化。而且經驗是變化最快的,沒殺一個怪就變了,一變就Caculate也太耗效能了。
public class PlayerStatus : MonoBehaviour {
private UserEntity m_User;
public double m_MultipleExp = 1.18;
public int m_StartExp = 40;
public string PlayerName { get; set; }
public int Lv { get; set; }
public int LvMax { get; set; }
public double Exp { get; set; }
public double ExpMax { get; set;}
public double HpRegenTime { get; set; }
public double MpRegenTime { get; set; }
public AttributeNode statusGrowth = new AttributeNode();
public AttributeNode statusEquip = new AttributeNode();
public AttributeNode statusBuff = new AttributeNode();
public AttributeRoot status = new AttributeRoot();
void Start()
{
}
private void InitAllStatus()
{
InitStatusGrowth();
InitStatus();
}
private void InitStatusGrowth()
{
this.statusGrowth.Hp = this.Lv * this.m_User.Hero.HpGrowth;
this.statusGrowth.Mp = this.Lv * this.m_User.Hero.MpGrowth;
this.statusGrowth.Atk = this.Lv * this.m_User.Hero.AtkGrowth;
this.statusGrowth.Def = this.Lv * this.m_User.Hero.DefGrowth;
this.statusGrowth.Spd = this.Lv * this.m_User.Hero.SpdGrowth;
this.statusGrowth.Hit = this.Lv * this.m_User.Hero.HitGrowth;
this.statusGrowth.CriticalRate = this.Lv * this.m_User.Hero.CriticalRateGrowth;
this.statusGrowth.AtkSpd = this.Lv * this.m_User.Hero.AtkSpdGrowth;
this.statusGrowth.AtkRange = this.Lv * this.m_User.Hero.AtkRangeGrowth;
this.statusGrowth.MoveSpd = this.Lv * this.m_User.Hero.MoveSpdGrowth;
this.statusGrowth.Calculate();
}
private void InitStatus()
{
this.status.Hp = this.m_User.Hero.Hp;
this.status.Mp = this.m_User.Hero.Mp;
this.status.Atk = this.m_User.Hero.Atk;
this.status.Def = this.m_User.Hero.Def;
this.status.Spd = this.m_User.Hero.Spd;
this.status.Hit = this.m_User.Hero.Hit;
this.status.CriticalRate = this.m_User.Hero.CriticalRate;
this.status.AtkSpd = this.m_User.Hero.AtkSpd;
this.status.AtkRange = this.m_User.Hero.AtkRange;
this.status.MoveSpd = this.m_User.Hero.MoveSpd;
this.status.AddNode(this.statusGrowth);
this.status.AddNode(this.statusEquip);
this.status.AddNode(this.statusBuff);
this.status.Calculate(true);
}
public void Load(UserEntity user)
{
this.m_User = user;
this.Lv = this.m_User.Lv;
this.PlayerName = this.m_User.Name;
this.Exp = this.m_User.Exp;
this.ExpMax = m_StartExp * m_MultipleExp * this.Lv;
this.LvMax = this.m_User.Hero.MaxLv;
this.HpRegenTime = this.m_User.HpRegenTime;
this.MpRegenTime = this.m_User.MpRegenTime;
InitAllStatus();
}
}
UIPlayerInfo
角色屬性綁值
public class UIPlayerInfo : UIScene {
private Image m_ImgHead;
private Text m_TxtLv;
private Text m_TxtName;
private Text m_TxtHp;
private Text m_TxtMp;
private Slider m_SldHp;
private Slider m_SldMp;
private Slider m_SldExp;
private PlayerStatus m_PlayerStatus;
protected override void Start()
{
base.Start();
InitWidget();
}
private void InitWidget()
{
this.m_ImgHead = UIHelper.FindChild<Image>(transform, "imgHead");
this.m_TxtLv = UIHelper.FindChild<Text>(transform, "txtLv");
this.m_TxtName = UIHelper.FindChild<Text>(transform, "txtName");
this.m_SldHp = UIHelper.FindChild<Slider>(transform, "sldHp");
this.m_SldMp = UIHelper.FindChild<Slider>(transform, "sldMp");
this.m_SldExp = UIHelper.FindChild<Slider>(transform, "sldExp");
this.m_TxtHp = UIHelper.FindChild<Text>(transform, "sldHp/Text");
this.m_TxtMp = UIHelper.FindChild<Text>(transform, "sldMp/Text");
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
//TODO: this.m_ImgHead
this.m_PlayerStatus = player.GetComponent<PlayerStatus>();
this.m_TxtName.text = this.m_PlayerStatus.PlayerName;
this.m_TxtLv.text = this.m_PlayerStatus.Lv.ToString();
this.m_TxtHp.text = string.Format("{0}/{1}", this.m_PlayerStatus.status.HpCur, this.m_PlayerStatus.status.HpMax);
this.m_TxtMp.text = string.Format("{0}/{1}", this.m_PlayerStatus.status.MpCur, this.m_PlayerStatus.status.MpMax);
this.m_SldHp.value = this.m_PlayerStatus.status.HpCur / this.m_PlayerStatus.status.HpMax;
this.m_SldExp.value = this.m_PlayerStatus.status.MpCur / this.m_PlayerStatus.status.MpMax;
this.m_SldExp.value = (float)(this.m_PlayerStatus.Exp / this.m_PlayerStatus.ExpMax);
}
}
}