前言
原文链接: https://www.yuque.com/finctive/game-dev/obsever-ugui
本文参考自:
- Unity3d College - Observer Pattern - Game Programming Patterns in Unity & C#(视频教程)
- 游戏设计模式-观察者模式 (译文)
- Game Programming Patterns - Observer (英语原文)
在阅读完本文后,请查看上述链接内容。
本文使用的示例工程:FINCTIVE/lost-in-the-wilderness-nightmare(荒野迷踪:噩梦)欢迎Star!
由于水平有限,文章内容可能有误,欢迎探讨、交流、或直接批评。
┗|`O′|┛
本文作者: FINCTIVE
联系邮箱: finctive@qq.com
转载请标明原文链接以及作者名字,谢谢。
应用场景
想象你在游戏项目中实现了一个角色控制器,这个控制器相对复杂,以至于你想新开一个空场景来单独测试这个控制器脚本。
很不幸,你发现在新场景中,角色游戏对象缺乏相关UI的引用,导致程序无法测试。
public Slider hpSlider; // 举个例子,角色HP的血条
void GetDamage()
{
// ...处理受伤代码...
// 更新相应UI
hpSlider.value = newValue; // 在新场景中导致空引用
}
解决方案
使用C#委托和事件来建立hp更新和UI更新的联系。
在管理玩家属性的脚本中(本例中是PlayerInfo.cs)
public event Action<int> OnPlayerHpChange;
public int hp
{
get => _hp;
set
{
_hp = value;
if (OnPlayerHpChange != null)
OnPlayerHpChange(_hp);
}
}
在控制UI更新行为的脚本中(本例是PlayerHpUI.cs)
void Start()
{
// 通过全局变量获取player示例中的playerInfo对象(与上一个代码示例对应)
PlayerController.player.playerInfo.OnPlayerHpChange += _OnPlayerHpChange;
}
private void _OnPlayerHpChange(int hp)
{
hpSlider.value = (float)hp / 100f;
}
在本例中Player控制器部分代码与UI更新代码分离开了,实际工程项目中会出现更复杂的情况;本文例子是“一对一”的情况,实际工程中有可能会出现“一对多”甚至“多对多”的情况。
更经典的应用场景是游戏成就系统:游戏成就千奇百怪,把判定游戏成就的代码耦合到其他游戏系统中不是一个明智的做法。
作者:FINCTIVE(finctive@qq.com)
欢迎转载,请附上原文链接以及作者名字,谢谢!