TShit.cs和Star.cs
TShit.cs和Star.cs代码一样(便便塔)是一个继承自
TShitTowerPersonalProperty的塔脚本。从代码量上看,它非常简洁,只重写了Start()和Update()方法,没有添加任何新的字段或逻辑。
这么简单的脚本有什么用?
实际上,它代表了绝大多数普通塔的标准模板——攻击行为完全由
父类TowerPersonalProperty提供,子类只需根据自身特点微调初始化或攻击节奏即可。
而便便塔的特殊效果(减速 debuff)实际上是在子弹脚本(TshitBullect)中实现的,而不是在塔脚本中。
核心作用
| 作用 | 说明 |
|---|---|
| 标识塔的类型 | 通过类名TShit区分不同塔(如便便塔、水晶塔、风车塔等),便于对象池加载、子弹关联等。 |
| 调用父类初始化 | 在Start()中调用base.Start(),执行父类的通用初始化(设置升级/出售价格、获取动画组件、初始化攻击计时器等)。 |
| 提供攻击节奏 | 在Update()中实现计时攻击逻辑(CD 管理),与父类的攻击方法Attack()配合。 |
| 预留扩展点 | 如果未来便便塔需要特殊行为(如攻击时额外播放屎特效),可以在子类中重写相应方法,而不影响其他塔。 |
注意:这个脚本并没有重写
Attack()方法,因此攻击时实际执行的是
父类TowerPersonalProperty.Attack()—— 生成普通的子弹预制体。而便便子弹的 debuff 效果是由子弹脚本TshitBullect通过读取towerLevel自行计算的,与塔脚本无关
生命周期函数
protected override void Start() 重写方法
protected override:重写父类的虚方法。
base.Start():调用父类的Start,完成通用初始化:
获取
GameController单例。计算升级价格(
price * 1.5f)和出售价格(price / 2)。查找
tower子物体上的Animator组件。初始化攻击计时器
timeVal = attackCD(让塔可以立刻攻击)。便便塔没有额外的初始化工作,所以只调用基类即可。
protected override void Update() 重写方法
protected override void Update () { if (GameController.Instance.isPause || GameController.Instance.gameOver) { return; } if (targetTrans==null) { return; } if (timeVal>=attackCD/GameController.Instance.gameSpeed) { timeVal = 0; Attack(); } else { timeVal += Time.deltaTime; } }
游戏状态检查:若游戏暂停或结束,直接返回,不进行任何攻击判定。
目标有效性检查:若当前锁定目标为空(
targetTrans == null),返回。攻击CD控制:
计算当前攻击阈值:
attackCD / GameController.Instance.gameSpeed(游戏速度越快,阈值越小,攻击频率越高)。若计时器达到阈值,则:
重置计时器
timeVal = 0。调用父类的
Attack()方法发射子弹。否则累加
timeVal += Time.deltaTime。
为什么这个脚本这么简单?
这体现了面向对象设计中的模板方法模式:
父类
TowerPersonalProperty提供了塔的通用框架:升级、出售、攻击 CD 管理(在父类 Update 中)、旋转、子弹生成等。子类可以根据需要选择性重写部分行为:
如果塔的行为与父类完全一致,那么子类只需一个空的
Start和Update(甚至可以不重写 Update,直接继承父类的),但这里重写了 Update 去掉了旋转。如果塔的行为特殊(如水晶塔的持续激光),则重写更多方法。
TShit代表了一类最普通的塔:周期发射子弹,子弹自身携带特殊效果(减速)。塔本身不需要任何特殊逻辑,因此子类代码极少。
与便便子弹(TshitBullect)的协作
便便塔发射的子弹预制体是
TshitBullect(在父类Attack()中通过资源路径加载)。子弹在
Start()中根据towerLevel计算 debuff 强度和持续时间。子弹命中怪物后,发送
DecreaseSpeed消息,施加减速效果。所以便便塔的“特殊性”完全体现在子弹上,而非塔本身。这是一个职责分离的好例子:塔只管发射,子弹管特殊效果。
