实战:完整的击杀事件系统

我们来做一套完整的系统,让你彻底理解事件的用法。

步骤一:创建 Enemy.cs,定义敌人基类和事件

using System;

namespace MyGame
{
    class Enemy
    {
        public string name;
        private int hp;

        public int Hp
        {
            get { return hp; }
            set
            {
                if (value < 0) hp = 0;
                else hp = value;
            }
        }

        public int attackPower;

        // ★ 核心:定义一个事件。当敌人死亡时触发
        public event Action<Enemy> OnEnemyKilled;

        public Enemy(string enemyName, int enemyHp, int enemyAttack)
        {
            name = enemyName;
            Hp = enemyHp;
            attackPower = enemyAttack;
        }

        public void TakeDamage(int damage)
        {
            Hp = Hp - damage;
            Console.WriteLine(name + " 受到了" + damage + "点伤害!剩余HP:" + Hp);

            if (Hp <= 0)
            {
                Die();
            }
        }

        private void Die()
        {
            Console.WriteLine(name + " 被消灭了!");

            // ★ 触发事件!通知所有订阅者
            // 先检查事件是否为 null(有没有人订阅)
            if (OnEnemyKilled != null)
            {
                OnEnemyKilled(this);  // this 就是当前这个敌人对象
            }
        }

        public virtual void Attack()
        {
            Console.WriteLine(name + " 发动攻击,造成" + attackPower + "点伤害!");
        }
    }
}

注意

  • public event Action<Enemy> OnEnemyKilled;:定义了一个事件,它带一个 Enemy 参数,告诉订阅者“谁被杀了”。

  • if (OnEnemyKilled != null):必须检查!如果没人订阅,事件是 null,直接调用会报错。

  • OnEnemyKilled(this):触发事件,把当前敌人对象传出去。

步骤二:创建三个独立的系统,各自订阅事件

AchievementSystem.cs —— 成就系统

using System;
using System.Collections.Generic;

namespace MyGame
{
    class AchievementSystem
    {
        private int killCount = 0;
        private List<string> unlockedAchievements = new List<string>();

        // 这个方法签名必须和 Action<Enemy> 匹配:无返回值,一个 Enemy 参数
        public void OnEnemyKilled(Enemy enemy)
        {
            killCount++;
            Console.WriteLine("[成就系统] 累计击杀:" + killCount);

            if (killCount >= 5 && !unlockedAchievements.Contains("新手杀手"))
            {
                unlockedAchievements.Add("新手杀手");
                Console.WriteLine("🏆 解锁成就:新手杀手!");
            }

            if (killCount >= 10 && !unlockedAchievements.Contains("屠戮者"))
            {
                unlockedAchievements.Add("屠戮者");
                Console.WriteLine("🏆 解锁成就:屠戮者!");
            }
        }
    }
}

SoundSystem.cs —— 音效系统

using System;

namespace MyGame
{
    class SoundSystem
    {
        public void OnEnemyKilled(Enemy enemy)
        {
            // 根据敌人名字播放不同音效(这里用打印模拟)
            if (enemy.name.Contains("史莱姆"))
            {
                Console.WriteLine("[音效系统] 🔊 噗叽!");
            }
            else
            {
                Console.WriteLine("[音效系统] 🔊 啊——!");
            }
        }
    }
}

QuestSystem.cs —— 任务系统

using System;

namespace MyGame
{
    class QuestSystem
    {
        private int slimeKillCount = 0;
        private int requiredKills = 3;

        public void OnEnemyKilled(Enemy enemy)
        {
            if (enemy.name.Contains("史莱姆"))
            {
                slimeKillCount++;
                Console.WriteLine("[任务系统] 击杀史莱姆进度:" + slimeKillCount + "/" + requiredKills);

                if (slimeKillCount >= requiredKills)
                {
                    Console.WriteLine("[任务系统] ✅ 任务完成:讨伐史莱姆!");
                }
            }
        }
    }
}

步骤三:在 Main 里把它们串起来

Program.cs

using System;
using System.Collections.Generic;

namespace MyGame
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. 创建三个独立系统
            AchievementSystem achievement = new AchievementSystem();
            SoundSystem sound = new SoundSystem();
            QuestSystem quest = new QuestSystem();

            // 2. 生成一堆敌人
            List<Enemy> enemies = new List<Enemy>();
            for (int i = 1; i <= 12; i++)
            {
                Enemy slime = new Enemy("绿色史莱姆" + i, 20, 5);

                // ★ 核心:把各个系统的方法订阅到敌人死亡事件上
                slime.OnEnemyKilled += achievement.OnEnemyKilled;
                slime.OnEnemyKilled += sound.OnEnemyKilled;
                slime.OnEnemyKilled += quest.OnEnemyKilled;

                enemies.Add(slime);
            }

            Console.WriteLine("=== 开始战斗 ===\n");

            // 3. 依次击杀所有敌人
            foreach (Enemy enemy in enemies)
            {
                Console.WriteLine("--- 遭遇 " + enemy.name + " ---");
                // 攻击直到死亡
                while (enemy.Hp > 0)
                {
                    enemy.TakeDamage(10); // 每次打10点伤害
                }
                Console.WriteLine();
            }

            Console.WriteLine("=== 所有敌人已消灭 ===\n");
            Console.ReadKey();
        }
    }
}

📊 运行效果预览

  • Enemy 类完全不知道成就、音效、任务的存在。

  • 它只管在死亡时触发事件。

  • 各个系统独立存在,互不干扰。

  • 将来要加新系统(如统计面板),只需写一个新类并订阅事件,无需修改任何现有代码

这就是解耦,是制作大型游戏的核心架构思想。

明白了吗?

关注我,下一期更精彩。

更多推荐