如何优化基于Unity与Fishnet的多人射击游戏击中血量更新代码?
问题:Fishnet框架下多人射击游戏血量更新的代码优化与正确性验证
我用Unity做多人游戏开发,采用Fishnet作为网络框架,学习过程中遇到不少问题,官方文档和教程没提供有效帮助。折腾一周后,我实现了子弹击中玩家后更新HUD血量显示的功能,但感觉代码冗余,想确认当前代码是否正确,以及有没有更优的实现方式。
现有代码
Bullet.cs(子弹逻辑)
private void OnTriggerEnter(Collider other) { if (other.TryGetComponent<PlayerController>(out PlayerController playerController)) { playerController.TakeDamage(playerController); } Server_DestroyBullet(); } [ServerRpc(RequireOwnership = false)] public void Server_DestroyBullet() { InstanceFinder.ServerManager.Despawn(gameObject); DestroyInstance(); } [ObserversRpc] public void DestroyInstance() { Destroy(gameObject); }
PlayerController.cs(玩家逻辑片段)
[ServerRpc(RequireOwnership = false)] public void TakeDamage(PlayerController script) { script.healthPoints--; UpdateLifeDisplay(script.Owner, script.healthPoints.ToString()); } [TargetRpc] void UpdateLifeDisplay(NetworkConnection conn, string value) { HUDController.lifeText.text = value; }
代码问题分析
- 冗余参数传递:
TakeDamage方法里传入PlayerController script完全没必要,当前实例本身就是目标玩家,传参属于多余操作,还可能引发逻辑错误。 - 高耦合的静态引用:直接用
HUDController.lifeText这种全局静态引用,会让代码耦合度极高,后续维护或扩展HUD功能时容易出问题。 - 多余的子弹销毁逻辑:Fishnet的
Despawn方法会自动同步到所有客户端完成对象销毁,额外调用DestroyInstance这个ObserversRpc属于重复操作。 - 手动同步效率低:用
TargetRpc手动同步血量到客户端,不如利用Fishnet自带的SyncVar特性更简洁可靠。
优化方案
优化后的Bullet.cs
private void OnTriggerEnter(Collider other) { if (other.TryGetComponent<PlayerController>(out PlayerController playerController)) { // 直接调用TakeDamage,无需传参 playerController.TakeDamage(); } Server_DestroyBullet(); } [ServerRpc(RequireOwnership = false)] public void Server_DestroyBullet() { // Fishnet Despawn会自动同步销毁到所有客户端,无需额外ObserversRpc InstanceFinder.ServerManager.Despawn(gameObject); }
优化后的PlayerController.cs
// 替换静态引用,每个玩家持有自己的HUD实例 [SerializeField] private HUDController _ownHud; // 用SyncVar自动同步血量,hook函数在血量变化时触发UI更新 [SyncVar(hook = nameof(OnHealthUpdated))] private int _healthPoints = 100; // 假设初始血量为100 [ServerRpc(RequireOwnership = false)] public void TakeDamage() { // 直接操作当前实例的血量,无需额外传参 _healthPoints--; } // SyncVar变化时的回调,自动同步到客户端并更新UI private void OnHealthUpdated(int oldHealth, int newHealth) { _ownHud.lifeText.text = newHealth.ToString(); }
优化说明
- 利用SyncVar简化同步:SyncVar是Fishnet专门用于同步服务器变量到客户端的特性,配合hook函数能自动在变量变化时触发UI更新,省去手动编写TargetRpc的冗余代码。
- 移除不必要的代码:删掉多余的参数传递、重复的销毁逻辑,让代码更简洁。
- 降低耦合度:用每个玩家自己的HUD实例替代全局静态引用,代码扩展性和可维护性更强。
- 贴合框架设计:遵循Fishnet的原生特性设计代码,减少自定义网络逻辑的出错概率。
内容的提问来源于stack exchange,提问作者Conrado Saud
相关产品推荐
相关产品推荐

