Unity引擎2D游戏开发,血量更新逻辑的实现
思路
能够发现Fill Amount
就是控制血量条长度的控件,它是一个百分比值,则可以通过当前血量除以最大血量得到当前血量的百分比。那么,也就能控制血量条的长度了。
编写基本的更新逻辑
创建C#文件
将C#文件挂载到Player State Bar
上
在C#文件中调用UI组件前,需要调用UI组件库
using UnityEngine.UI;
在PlayerStateBar C#文件中,创建三个全局变量,分别代表绿色血条、红色血条和精力条
// 绿色血条
public Image healthImage;
// 红色血条
public Image healthDelayImage;
// 精力条
public Image powerImage;
在Hierarchy
中拖动Image到各自的位置
在PlayerStateBar中创建OnHealthChange()方法,用于处理血量变更时执行的代码
/// <summary>
/// 接受Health的变更百分比
/// </summary>
/// <param name="percentage">百分比:current / Max</param>
public void OnHealthChange(float percentage)
{
healthImage.fillAmount = percentage;
}
创建关于血量的ScriptableObject事件
这时候就需要从Player的Character中传递血量数据到此处,那么怎么样才能安全的完整的跨物体甚至跨场景来传递数值呢?
这时候需要利用ScriptableObject
进行传递,它是一个持久化存储在项目中的资产文件类型,例如
后缀名为.Asset
在Scripts下创建ScriptableObject
文件夹,并创建CharacterEventSO
。因为是利用ScriptableObject来创建事件,因此以EventSO结尾
打开CharacterEventSO C#文件,继承ScriptableObject
public class CharacterEventSO : ScriptableObject
{
}
在上面写上描述用以生成ScriptableObject资产文件
[CreateAssetMenu(fileName = "Event/CharacterEventSO")]
public class CharacterEventSO : ScriptableObject
{
}
这样就能在Project窗口中添加此资产文件
创建一个UnityAction的全局变量,用于传递Character数据
// 只传递Character数据
public UnityAction<Character> OnEventRised;
创建RaiseEvent()事件启动方法
/// <summary>
/// 启动事件
/// </summary>
/// <param name="character">谁想启动这个事件,就把自己的Character传递进去</param>
public void RaiseEvent(Character character)
{
OnEventRised?.Invoke(character);
}
在Assets中创建Events文件夹,在内部创建SriptableObject事件
接下来,在Character代码脚本当中,只要血量发生变化就调用EventSO,把当前血量传递过去
用Unity Event进行广播,则在Character C#脚本中,添加如下全局变量
public UnityEvent<Character> OnHealthChange;
然后在Player的Character中,将上述的ScriptableObject Event拖入,并选择RaiseEvent()方法。从而,当人物血量有了变化,即可广播出去。
接下来,Player State Bar来监听,因为要使血条栏变少
监听ScriptableObject事件
在Hierarchy中,创建一个GameObject,用于监听所有关于UI的事件
在Scripts下,创建一个UIManager
的C#脚本
绑定到UI Manager
下
C#代码中,创建一个CharacterEventSO
的全局变量
public class UIManager : MonoBehaviour
{
[Header("事件监听")]
public CharacterEventSO healthEvent;
}
在UI Manager中,绑定Character Event SO
的Event文件
此时,就能够成功监听Character Event SO的Event文件,利用了Character Event SO的Event文件进行中间件传递了一些数据
继续编写血条更新逻辑
在UIManager C#脚本中,创建OnEnable()
方法和OnDisable()
方法。并在内部添加OnHealthEvent事件进行监听
private void OnEnable()
{
healthEvent.OnEventRised += OnHealthEvent;
}
private void OnDisable()
{
healthEvent.OnEventRised -= OnHealthEvent;
}
OnEnable()即启动事件方法,OnDisable()为关闭事件方法,两者均为固定方法
由于需要对血条栏进行控制,所以添加状态栏的全局变量
public PlayerStateBar playerStateBar;
然后创建OnHealthEvent()
方法,在内部对血条进行计算,并赋予给playerStateBar的OnHealthChange()
方法
private void OnHealthEvent(Character character)
{
var percentage = character.currentHealth / character.maxHealth;
playerStateBar.OnHealthChange(percentage);
}
打开Hierarchy,选中UI Manager,将对应的组件拖入
打开Character,虽然创建了OnHealthChange变量,但是并没有对其进行调用。那么就需要在受伤时和初始化时进行调用
public void TakeDamage(Attack attacker)
{
if (invulnerable)
{
return;
}
if (currentHealth - attacker.damage > 0)
{
currentHealth -= attacker.damage;
TriggerInvulnerable();
// 执行受伤
OnTakeDamage?.Invoke(attacker.transform);
} else
{
currentHealth = 0;
// 触发死亡
onDie?.Invoke();
}
// 进行血条的扣除
OnHealthChange?.Invoke(this);
}
private void Start()
{
currentHealth = maxHealth;
OnHealthChange?.Invoke(this);
}
红色血条的扣除
打开PlayerStateBar脚本,由于healthDelayImage要跟随healthImage变化,所以在Update()中进行
判断红色血条是否大于绿色血条的值,如果大于,则扣除时间的修正进行变化
private void Update()
{
if (healthDelayImage.fillAmount > healthImage.fillAmount)
{
healthDelayImage.fillAmount -= Time.deltaTime;
}
}