103
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2501_CS_SE_FZU |
|---|---|
| 这个作业要求在哪里 | 团队作业——站立式会议+α冲刺 |
| 这个作业的目标 | α冲刺Day6 |
| 其他参考文献 | 《构建之法》、Google Style Guides |


| 成员角色 | 昨日至今日日站立会安排 | 存在的问题 / 遇到的困难 | 心得体会 | 今日至明日站立会安排 |
|---|---|---|---|---|
| 陈志豪(敌人模块) | 1. 完善敌人碰撞体管理逻辑,在攻击时临时忽略友方碰撞,解决混战卡顿;2. 拉大普通与精英敌人攻击间隔(普通 2.5 秒、精英 3.5 秒),强化强度差异;3. 测试敌人 “返回原点” 路径逻辑,修复因地形阻挡导致的卡滞问题。 | 精英敌人 “返回原点” 时,若中途遇到玩家,追击逻辑会覆盖返回逻辑,但重新触发返回时,路径计算会出现 “重复绕路”(如反复往返某一地形);多敌人混战中,部分敌人攻击后摇取消不及时,仍存在 0.1 秒左右的僵硬感,影响战斗流畅度。 | 敌人 AI 逻辑的 “状态切换优先级” 是确保行为流畅的关键。精英敌人绕路问题,源于未设置 “返回状态→追击状态→返回状态” 的路径重置机制,通过在重新触发返回时清空原路径点、重新计算最短路径,解决绕路问题;攻击后摇残留则是因为后摇取消逻辑未绑定 “攻击动作结束帧”,改为在攻击动画最后 1 帧强制取消后摇,僵硬感彻底消失。这让我意识到,AI 行为不仅要实现 “做什么”,更要明确 “状态切换时该如何衔接”,通过绑定动画帧、重置路径等细节,让敌人行为更自然,贴合玩家对 “智能敌人” 的预期。 | 1. 为敌人添加 “追击玩家时实时更新路径” 的逻辑,避免因玩家移动导致敌人追错方向;2. 优化精英敌人攻击后摇取消时机,绑定动画结束帧,彻底消除僵硬感;3. 测试不同地形(如窄道、台阶)下敌人的移动与攻击逻辑,确保无卡滞、无攻击落空问题。 |
| 胡定赟 (UI/UX 设计) | 1. 优化背包 UI“99+” 文字布局,调整锚点至图标右上角,解决边缘重叠;2. 修复技能栏 UI 窗口化切换时的图标位移,绑定画布中心锚点;3. 为血条 UI 添加 “受击时短暂闪烁红色” 效果,强化受击反馈。 | 血条闪烁效果在玩家连续受击时(如被 3 个敌人同时攻击),闪烁频率过高(每秒 3 次),导致视觉疲劳;背包 UI 在切换 “全部物品”“武器”“道具” 分类时,分类标签的选中状态(如红色下划线)会出现延迟显示(约 0.2 秒),影响操作反馈。 | UI 设计中,“反馈强度控制” 和 “状态响应速度” 直接影响玩家操作体验。血条高频闪烁问题,通过设置 “1 秒内最多闪烁 2 次” 的频率限制,既保留受击提示效果,又避免视觉疲劳;分类标签延迟显示,则是因为 UI 切换时添加了不必要的过渡动画(时长 0.2 秒),删除过渡动画后,选中状态可实时更新。现在做 UI 优化时,会同时考虑 “反馈有效性” 和 “感官舒适度”—— 比如受击反馈要让玩家清晰感知,但不能过度刺激;状态切换要及时响应,但不能因动画延迟影响操作判断,在 “提示清晰” 和 “体验舒适” 之间找到平衡。 | 1. 调整血条受击闪烁频率,设置 1 秒内最多闪烁 2 次,优化视觉体验;2. 修复背包 UI 分类标签的延迟显示问题,删除不必要的过渡动画,确保实时更新;3. 为技能冷却 UI 添加 “冷却进度条”(蓝色渐变填充),让玩家直观感知冷却剩余时间,替代单一的数字提示。 |
| 阮航宇 (地图与资源设计) | 1. 为指路箭头 UI 添加距离检测逻辑,玩家距离超 5 米自动隐藏,避免场景堆积;2. 完善恢复泉水多玩家适配,添加单玩家 3 秒触发冷却,防止恢复叠加;3. 在 Boss 区域外围添加 “战斗预警圈”(红色渐变光圈),提示玩家进入高强度战斗。 | 战斗预警圈在玩家快速穿过(如 Dash 冲刺)时,光圈触发延迟(约 0.3 秒),导致玩家已进入 Boss 区域,预警圈才显示,失去提示意义;恢复泉水的粒子特效在多玩家同时使用时,特效叠加导致画面出现轻微掉帧(从 60fps 降至 55fps),影响视觉流畅度。 | 地图交互物的 “触发及时性” 和 “资源轻量化” 是优化重点。预警圈延迟触发,源于触发检测用了 “每 0.3 秒检测一次距离” 的轮询逻辑,改为 “玩家进入预警圈碰撞体时立即触发” 的事件驱动逻辑后,可实时显示光圈;粒子特效掉帧,则是因为每个泉水特效实例未设置 “最大粒子数量”(默认无限制),通过将单泉水特效最大粒子数设为 50,叠加时总粒子数可控,帧率回升至 59fps。这让我明白,地图元素不仅要实现 “功能引导”,还要通过优化触发逻辑确保提示及时,通过控制资源消耗(如粒子数量、模型面数)保障运行流畅,尤其在多玩家、多交互物叠加场景下,“轻量化设计” 是避免性能问题的关键。 | 1. 优化战斗预警圈触发逻辑,改为碰撞体事件驱动,确保玩家进入时实时显示;2. 限制恢复泉水粒子特效的最大粒子数量(单泉水 50 个),解决多玩家使用时的掉帧问题;3. 在地图隐藏区域(如宝箱位置)添加 “微弱发光特效”(蓝色低亮度光点),引导玩家探索,同时避免特效过于醒目破坏场景氛围。 |
| 张天荣 (攻击模块) | 1. 优化雷元素连锁攻击层级过滤,明确仅检测 Enemy 层,避免误判友方;2. 为属性克制提示文字添加随机 Y 轴偏移(±10px),解决多文字重叠;3. 设计火元素燃烧效果 “伤害随时间递减” 机制(1 秒 5 点→2 秒 3 点→3 秒 2 点),提升策略性。 | 火元素燃烧效果在敌人死亡后仍会持续触发伤害判定(如敌人死亡后,燃烧伤害还会计算 2 次),导致无效伤害数值飘出,影响战斗反馈准确性;雷元素连锁攻击的连锁次数(默认 3 次)在面对密集敌人(如 5 个敌人扎堆)时,无法覆盖所有目标,攻击范围存在局限。 | 攻击效果的 “状态同步” 和 “范围适配” 是提升战斗体验的核心。火元素无效伤害问题,源于未在敌人死亡时立即清除燃烧状态,通过添加 “敌人死亡事件→清除燃烧状态” 的回调逻辑,解决无效判定;雷元素范围局限,则是因为连锁攻击的 “目标搜索半径”(默认 2 米)过小,扩大至 2.5 米后,可覆盖更多密集敌人。这让我意识到,攻击模块开发不能只关注 “伤害计算”,还要关联 “目标状态变化”(如敌人死亡、玩家闪避),确保伤害判定与目标状态同步;同时要根据 “战斗场景差异”(如单敌人、密集敌人)调整攻击参数(如范围、次数),让攻击效果在不同场景下都能发挥预期作用,提升玩法灵活性。 | 1. 为火元素燃烧效果添加 “敌人死亡时清除状态” 的逻辑,避免无效伤害判定;2. 扩大雷元素连锁攻击的目标搜索半径(从 2 米至 2.5 米),提升密集敌人场景下的覆盖范围;3. 为冰元素冻结效果添加 “冻结时长随技能等级提升” 的机制(1 级 2 秒→2 级 2.5 秒→3 级 3 秒),强化技能成长感,让玩家更有养成动力。 |
| 汪涛(测试与性能优化、玩家模块) | 1. 完善玩家 Dash 技能碰撞检测,开启 Continuous 模式,解决墙体穿透;2. 优化敌人尸体资源回收,添加 2 秒自动销毁 + 淡出动画;3. 执行全流程压力测试(20 + 敌人混战、多技能连发),记录性能数据。 | 压力测试中发现,玩家连续释放 10 次 Dash 技能后,角色移动速度会出现 “累积加速”(从默认 5m/s 增至 6.2m/s),导致后期移动失控;敌人尸体淡出动画在销毁时,偶发 “模型残留像素”(如尸体消失后,地面仍有 1 帧像素残留),属于渲染残留问题。 | 性能测试不仅要 “发现问题”,更要 “定位问题根源”。Dash 技能累积加速,源于每次冲刺后未重置 “临时速度加成”(每次冲刺会添加 0.3m/s 临时速度,未清除),通过在冲刺结束后 1 秒清除临时速度,解决失控问题;尸体渲染残留,则是因为销毁前未等待淡出动画完全结束(动画时长 0.5 秒,销毁时机设为 0.3 秒),延迟销毁时机至 0.5 秒后,残留像素消失。现在做性能测试时,会重点关注 “高频操作场景”(如连续技能、长时间混战)和 “资源销毁场景”,因为这类场景容易出现 “状态累积”“渲染残留” 等隐性问题,只有针对性测试,才能确保游戏在高负载下仍稳定运行。 | 1. 修复 Dash 技能连续释放后的累积加速问题,冲刺结束后 1 秒清除临时速度加成;2. 调整敌人尸体销毁时机,等待淡出动画(0.5 秒)完全结束后再销毁,解决渲染残留;3. 针对压力测试中帧率低于 50fps 的场景(如 20 + 敌人同时释放技能),优化技能特效的粒子渲染层级,降低非关键特效的渲染优先级,提升帧率。 |
| 莫馥玮(技能模块) | 1. 优化 DashStab 技能斜向冲刺,通过速度归一化确保各方向位移一致(均 2 米);2. 完善技能冷却弹窗状态同步,CD 结束后自动关闭弹窗;3. 为技能系统添加 “连招提示”(如 DashStab + 冰攻击触发 10% 伤害加成),引导玩家组合技能。 | 连招提示在玩家连续触发不同连招(如先触发 DashStab + 冰攻击,再触发冰攻击 + 火攻击)时,提示文字会出现 “覆盖显示”(新提示直接替换旧提示,无过渡),导致玩家错过前一个连招的加成信息;DashStab 技能在攻击到敌人后,偶尔会出现 “技能硬直未取消”(攻击命中后仍有 0.2 秒硬直),影响连招流畅度。 | 技能系统的 “信息传递完整性” 和 “操作连贯性” 是设计核心。连招提示覆盖问题,通过添加 “提示文字渐隐过渡”(旧提示 0.5 秒渐隐,新提示同时显示),让玩家有足够时间看清两次连招信息;技能硬直残留,则是因为 “命中取消硬直” 的逻辑未绑定 “攻击命中事件”,改为在检测到敌人命中时立即取消硬直,连招流畅度显著提升。这让我明白,技能设计不仅要 “好玩”,还要通过优化信息展示(如提示过渡)确保玩家获取完整反馈,通过优化操作衔接(如取消硬直)降低连招门槛,让玩家既能感受到策略性,又能体验到操作的爽快感,平衡 “策略深度” 和 “操作流畅度”。 | 1. 为连招提示文字添加渐隐过渡效果(0.5 秒渐隐),避免信息覆盖;2. 修复 DashStab 技能命中后的硬直残留,绑定攻击命中事件立即取消硬直;3. 为技能系统添加 “连招成就”(如连续触发 3 次不同连招解锁 “连招大师” 成就),增加玩法趣味性,激励玩家探索更多技能组合。 |
敌人模块
// 1. 敌人追击时实时更新路径,避免追错方向
private List<Vector2> currentPath = new List<Vector2>();
private float pathUpdateInterval = 0.5f; // 每0.5秒更新一次路径
private float lastPathUpdateTime;
private void Update()
{
if (IsChasingPlayer() && player != null)
{
// 定时更新路径
if (Time.time - lastPathUpdateTime >= pathUpdateInterval)
{
UpdateChasePath();
lastPathUpdateTime = Time.time;
}
// 按最新路径追击
FollowPath();
}
// 其他逻辑...
}
// 更新追击路径(简化版A*路径逻辑)
private void UpdateChasePath()
{
currentPath.Clear();
// 计算从敌人位置到玩家位置的简化路径(实际项目可集成A*算法)
Vector2 directionToPlayer = (player.position - transform.position).normalized;
// 每2米添加一个路径点,确保路径平滑
for (float i = 2f; i < Vector2.Distance(transform.position, player.position); i += 2f)
{
Vector2 pathPoint = (Vector2)transform.position + directionToPlayer * i;
currentPath.Add(pathPoint);
}
// 添加最终目标点(玩家位置)
currentPath.Add((Vector2)player.position);
}
// 跟随路径移动
private void FollowPath()
{
if (currentPath.Count == 0) return;
Vector2 targetPoint = currentPath[0];
// 移动到当前路径点
transform.position = Vector2.MoveTowards(transform.position, targetPoint, chaseSpeed * Time.deltaTime);
// 到达路径点后移除,前往下一个
if (Vector2.Distance(transform.position, targetPoint) < 0.1f)
{
currentPath.RemoveAt(0);
}
}
// 2. 精英敌人攻击后摇绑定动画结束帧,消除僵硬感
// 动画事件:攻击动画最后1帧调用此方法
public void OnAttackAnimationFinalFrame()
{
// 立即取消攻击后摇,恢复移动和攻击能力
attackRecoveryTimer = 0f;
isAttacking = false;
Debug.Log("攻击动画结束,立即取消后摇");
}
// 3. 地形适应性移动检测(窄道、台阶)
private void CheckTerrainAdaptation()
{
// 窄道检测:若两侧有墙,限制横向移动速度,避免卡墙
bool leftWall = Physics2D.OverlapCircle(wallCheckLeft.position, 0.1f, wallLayer);
bool rightWall = Physics2D.OverlapCircle(wallCheckRight.position, 0.1f, wallLayer);
if (leftWall && rightWall)
{
rb.velocity = new Vector2(0, rb.velocity.y); // 窄道中禁止横向移动
}
// 台阶检测:检测前方台阶,自动调整高度
RaycastHit2D stepHit = Physics2D.Raycast(wallCheckRight.position, new Vector2(0, -1), 0.5f, groundLayer);
if (stepHit.collider != null && IsChasingPlayer())
{
// 台阶高度≤0.3米时,自动上台阶
float stepHeight = transform.position.y - stepHit.point.y;
if (stepHeight > 0.1f && stepHeight <= 0.3f)
{
transform.position = new Vector2(transform.position.x, stepHit.point.y + 0.1f);
}
}
}
UI/UX 设计
// 1. 血条受击闪烁频率控制(1秒内最多2次)
private float lastBlinkTime = 0f;
private float blinkInterval = 0.5f; // 闪烁间隔≥0.5秒
public void OnPlayerTakeDamage()
{
// 控制闪烁频率
if (Time.time - lastBlinkTime >= blinkInterval)
{
StartCoroutine(BlinkHealthBar());
lastBlinkTime = Time.time;
}
}
private IEnumerator BlinkHealthBar()
{
Color originalColor = healthFillImage.color;
healthFillImage.color = Color.red;
yield return new WaitForSeconds(0.1f);
healthFillImage.color = GetHealthColor(currentHealth / maxHealth);
}
// 2. 背包UI分类标签实时更新(删除过渡动画)
public void SwitchItemCategory(ItemCategory category)
{
// 立即更新标签选中状态,无过渡动画
foreach (var tab in categoryTabs)
{
tab.Selected = (tab.Category == category);
// 直接设置选中样式,无延迟
tab.UnderlineImage.enabled = tab.Selected;
tab.Text.color = tab.Selected ? Color.red : Color.gray;
}
// 刷新物品列表
RefreshItemList(category);
}
// 3. 技能冷却UI添加进度条
public class SkillCooldownUI : MonoBehaviour
{
public Image cooldownFill; // 冷却进度条(蓝色渐变)
public TextMeshProUGUI cooldownText;
private Skill skill;
private void Update()
{
if (skill == null || !skill.IsOnCooldown)
{
cooldownFill.fillAmount = 0;
cooldownText.gameObject.SetActive(false);
return;
}
// 计算冷却进度
float cooldownPercent = (skill.RemainingCooldown / skill.CooldownDuration);
cooldownFill.fillAmount = cooldownPercent;
// 显示剩余时间(仅整数,减少视觉干扰)
cooldownText.text = Mathf.Round(skill.RemainingCooldown).ToString();
cooldownText.gameObject.SetActive(true);
}
public void BindSkill(Skill targetSkill)
{
skill = targetSkill;
}
}
// 1. 战斗预警圈碰撞体事件驱动触发
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
// 立即显示预警圈,无延迟
warningCircle.SetActive(true);
// 播放预警音效和文字提示
AudioSource.PlayClipAtPoint(warningSound, transform.position);
ShowWarningText("前方Boss区域!准备战斗!");
Debug.Log("玩家进入预警圈,实时触发提示");
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
warningCircle.SetActive(false);
}
}
// 2. 恢复泉水粒子特效数量限制
public class HealFountain : MonoBehaviour
{
[Header("粒子特效设置")]
public ParticleSystem healParticle;
public int maxParticleCount = 50; // 最大粒子数量
private void Start()
{
// 限制粒子数量
var emission = healParticle.emission;
var main = healParticle.main;
main.maxParticles = maxParticleCount;
// 限制每秒发射数量,避免瞬间叠加
emission.rateOverTime = new ParticleSystem.MinMaxCurve(10, 15);
}
// 多玩家触发冷却逻辑
private Dictionary<GameObject, float> playerCooldown = new Dictionary<GameObject, float>();
private void OnTriggerStay2D(Collider2D other)
{
if (other.CompareTag("Player") && Time.time - GetPlayerLastTriggerTime(other.gameObject) > 3f)
{
HealPlayer(other.GetComponent<PlayerController>());
playerCooldown[other.gameObject] = Time.time;
}
}
private float GetPlayerLastTriggerTime(GameObject player)
{
return playerCooldown.TryGetValue(player, out float time) ? time : 0;
}
}
// 3. 地图隐藏区域微弱发光特效
public class HiddenAreaGuide : MonoBehaviour
{
[Header("发光特效设置")]
public Light guideLight;
public float lightIntensity = 0.5f; // 低亮度,避免醒目
public float lightRange = 2f;
private void Start()
{
// 初始化微弱发光效果
guideLight.intensity = lightIntensity;
guideLight.range = lightRange;
guideLight.color = new Color(0.2f, 0.5f, 1f); // 淡蓝色,贴合隐藏探索氛围
}
// 玩家靠近时增强亮度,引导探索
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
guideLight.intensity = lightIntensity * 1.5f; // 轻微增强,提示玩家
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
guideLight.intensity = lightIntensity; // 恢复原亮度
}
}
}
地图模块
// 1. 战斗预警圈碰撞体事件驱动触发
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
// 立即显示预警圈,无延迟
warningCircle.SetActive(true);
// 播放预警音效和文字提示
AudioSource.PlayClipAtPoint(warningSound, transform.position);
ShowWarningText("前方Boss区域!准备战斗!");
Debug.Log("玩家进入预警圈,实时触发提示");
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
warningCircle.SetActive(false);
}
}
// 2. 恢复泉水粒子特效数量限制
public class HealFountain : MonoBehaviour
{
[Header("粒子特效设置")]
public ParticleSystem healParticle;
public int maxParticleCount = 50; // 最大粒子数量
private void Start()
{
// 限制粒子数量
var emission = healParticle.emission;
var main = healParticle.main;
main.maxParticles = maxParticleCount;
// 限制每秒发射数量,避免瞬间叠加
emission.rateOverTime = new ParticleSystem.MinMaxCurve(10, 15);
}
// 多玩家触发冷却逻辑
private Dictionary<GameObject, float> playerCooldown = new Dictionary<GameObject, float>();
private void OnTriggerStay2D(Collider2D other)
{
if (other.CompareTag("Player") && Time.time - GetPlayerLastTriggerTime(other.gameObject) > 3f)
{
HealPlayer(other.GetComponent<PlayerController>());
playerCooldown[other.gameObject] = Time.time;
}
}
private float GetPlayerLastTriggerTime(GameObject player)
{
return playerCooldown.TryGetValue(player, out float time) ? time : 0;
}
}
// 3. 地图隐藏区域微弱发光特效
public class HiddenAreaGuide : MonoBehaviour
{
[Header("发光特效设置")]
public Light guideLight;
public float lightIntensity = 0.5f; // 低亮度,避免醒目
public float lightRange = 2f;
private void Start()
{
// 初始化微弱发光效果
guideLight.intensity = lightIntensity;
guideLight.range = lightRange;
guideLight.color = new Color(0.2f, 0.5f, 1f); // 淡蓝色,贴合隐藏探索氛围
}
// 玩家靠近时增强亮度,引导探索
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
guideLight.intensity = lightIntensity * 1.5f; // 轻微增强,提示玩家
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
guideLight.intensity = lightIntensity; // 恢复原亮度
}
}
}
攻击模块
// 1. 火元素燃烧效果绑定敌人死亡事件,清除无效状态
public class BurnEffect : MonoBehaviour
{
private EnemyAI enemyAI;
private bool isBurning = false;
private void Start()
{
enemyAI = GetComponent<EnemyAI>();
// 绑定敌人死亡事件
if (enemyAI != null && enemyAI.GetComponent<Attribute>() != null)
{
enemyAI.GetComponent<Attribute>().OnDeath += OnEnemyDeath;
}
}
public void StartBurning(int[] damagePerSecond, float duration, GameObject source)
{
if (isBurning) return;
isBurning = true;
StartCoroutine(BurnCoroutine(damagePerSecond, duration, source));
}
private IEnumerator BurnCoroutine(int[] damagePerSecond, float duration, GameObject source)
{
float elapsed = 0f;
int damageIndex = 0;
while (elapsed < duration && isBurning)
{
// 每1秒造成一次伤害
yield return new WaitForSeconds(1f);
if (GetComponent<Attribute>() != null && GetComponent<Attribute>().IsAlive)
{
int damage = damageIndex < damagePerSecond.Length ? damagePerSecond[damageIndex] : 0;
GetComponent<Attribute>().TakeDamage(damage, source);
damageIndex++;
}
elapsed += 1f;
}
Destroy(this);
}
// 敌人死亡时立即停止燃烧
private void OnEnemyDeath()
{
isBurning = false;
Debug.Log("敌人死亡,清除燃烧状态");
}
private void OnDestroy()
{
// 取消事件绑定,避免内存泄漏
if (enemyAI != null && enemyAI.GetComponent<Attribute>() != null)
{
enemyAI.GetComponent<Attribute>().OnDeath -= OnEnemyDeath;
}
}
}
// 2. 雷元素连锁攻击扩大搜索半径
private void ApplyThunderEffect(GameObject target, AttackInfo attackInfo)
{
// 搜索半径从2米扩大至2.5米
float extendedChainRange = 2.5f;
Collider2D[] nearbyEnemies = Physics2D.OverlapCircleAll(
target.transform.position,
extendedChainRange,
enemyLayer
);
int chainDamage = Mathf.RoundToInt(attackInfo.baseDamage * 0.5f);
int chainedCount = 0;
foreach (Collider2D enemy in nearbyEnemies)
{
if (enemy.gameObject != target && enemy.gameObject != gameObject && chainedCount < 4) // 最多连锁4个目标
{
Attribute enemyAttr = enemy.GetComponent<Attribute>();
if (enemyAttr != null && enemyAttr.IsAlive)
{
enemyAttr.TakeDamage(chainDamage, gameObject);
Debug.Log($"雷元素连锁: {enemy.name} 受到{chainDamage}伤害,搜索半径{extendedChainRange}米");
chainedCount++;
}
}
}
}
// 3. 冰元素冻结时长随技能等级提升
public class FreezeEffect : MonoBehaviour
{
private float baseFreezeDuration = 2f;
private int skillLevel;
// 传入技能等级,计算冻结时长
public void StartFreeze(float duration, int level)
{
skillLevel = level;
// 等级加成:每级增加0.5秒冻结时长
float finalDuration = baseFreezeDuration + (skillLevel - 1) * 0.5f;
Debug.Log($"冰元素冻结:等级{skillLevel},时长{finalDuration}秒");
StartCoroutine(FreezeCoroutine(finalDuration));
}
private IEnumerator FreezeCoroutine(float duration)
{
Rigidbody2D rb = GetComponent<Rigidbody2D>();
if (rb != null)
{
rb.isKinematic = true;
rb.velocity = Vector2.zero;
}
yield return new WaitForSeconds(duration);
if (rb != null)
{
rb.isKinematic = false;
}
Destroy(this);
}
}
玩家模块
// 1. 修复Dash技能连续释放累积加速问题
public class PlayerController : MonoBehaviour
{
private float baseMoveSpeed = 5f;
private float tempSpeedBonus = 0f; // 临时速度加成
private float speedBonusDuration = 1f; // 加成持续1秒
private float lastDashTime = 0f;
public void PerformDash()
{
if (!CanDash()) return;
// 冲刺逻辑...
rb.velocity = new Vector2(dashDirection.x * dashSpeed, dashDirection.y * dashSpeed);
// 添加临时速度加成(0.3m/s)
tempSpeedBonus = 0.3f;
lastDashTime = Time.time;
}
private void FixedUpdate()
{
// 清除过期的临时速度加成
if (tempSpeedBonus > 0 && Time.time - lastDashTime >= speedBonusDuration)
{
tempSpeedBonus = 0f;
Debug.Log("临时速度加成清除,恢复基础速度");
}
// 计算最终移动速度(基础速度+临时加成)
float finalMoveSpeed = baseMoveSpeed + tempSpeedBonus;
// 应用速度...
rb.velocity = new Vector2(inputX * finalMoveSpeed, rb.velocity.y);
}
}
// 2. 敌人尸体淡出动画完全结束后销毁,解决渲染残留
public class EnemyCorpse : MonoBehaviour
{
public float fadeDuration = 0.5f; // 淡出动画时长
private SpriteRenderer spriteRenderer;
private void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
StartCoroutine(FadeAndDestroy());
}
private IEnumerator FadeAndDestroy()
{
Color originalColor = spriteRenderer.color;
float elapsed = 0f;
// 淡出动画(0.5秒从不透明到透明)
while (elapsed < fadeDuration)
{
elapsed += Time.deltaTime;
float alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration);
spriteRenderer.color = new Color(originalColor.r, originalColor.g, originalColor.b, alpha);
yield return null;
}
// 动画完全结束后再销毁,避免渲染残留
Destroy(gameObject);
Debug.Log("尸体淡出动画结束,销毁对象");
}
}
// 3. 技能特效渲染层级优化,提升高负载帧率
public class EffectRenderOptimizer : MonoBehaviour
{
[Header("渲染优先级设置")]
public int criticalEffectSortingOrder = 100; // 关键特效(如伤害数字)优先级高
public int normalEffectSortingOrder = 50; // 普通特效(如粒子)优先级中
public int trivialEffectSortingOrder = 10; // 次要特效(如地面痕迹)优先级低
// 初始化时设置渲染层级
public void SetEffectPriority(EffectType type)
{
SpriteRenderer renderer = GetComponent<SpriteRenderer>();
ParticleSystemRenderer particleRenderer = GetComponent<ParticleSystemRenderer>();
switch (type)
{
case EffectType.DamageText: // 伤害数字(关键)
if (renderer != null) renderer.sortingOrder = criticalEffectSortingOrder;
break;
case EffectType.SkillParticle: // 技能粒子(普通)
if (particleRenderer != null) particleRenderer.sortingOrder = normalEffectSortingOrder;
break;
case EffectType.GroundMark: // 地面痕迹(次要)
if (renderer != null) renderer.sortingOrder = trivialEffectSortingOrder;
// 关闭次要特效的阴影,减少渲染消耗
if (renderer != null) renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
break;
}
}
public enum EffectType
{
DamageText,
SkillParticle,
GroundMark
}
}
技能模块
// 1. 连招提示文字渐隐过渡,避免信息覆盖
public class ComboHintUI : MonoBehaviour
{
public TextMeshProUGUI hintText;
public float fadeDuration = 0.5f; // 渐隐时长
private Queue<HintData> hintQueue = new Queue<HintData>();
private bool isFading = false;
// 显示连招提示(加入队列,依次显示)
public void ShowComboHint(string text)
{
hintQueue.Enqueue(new HintData(text, Time.time));
if (!isFading)
{
StartCoroutine(ProcessHintQueue());
}
}
// 处理提示队列,旧提示渐隐时显示新提示
private IEnumerator ProcessHintQueue()
{
while (hintQueue.Count > 0)
{
isFading = true;
HintData currentHint = hintQueue.Dequeue();
hintText.text = currentHint.Text;
hintText.alpha = 1f;
// 等待0.8秒(让玩家看清)后开始渐隐
yield return new WaitForSeconds(0.8f);
// 渐隐过程
float elapsed = 0f;
while (elapsed < fadeDuration)
{
elapsed += Time.deltaTime;
hintText.alpha = Mathf.Lerp(1f, 0f, elapsed / fadeDuration);
yield return null;
}
hintText.alpha = 0f;
isFading = false;
}
}
private struct HintData
{
public string Text;
public float CreateTime;
public HintData(string text, float time)
{
Text = text;
CreateTime = time;
}
}
}
// 2. DashStab技能命中后立即取消硬直
public class DashStabSkill : MonoBehaviour
{
private bool hasHitEnemy = false;
private float hitHardness = 0.2f; // 原硬直时长
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy") && !hasHitEnemy)
{
hasHitEnemy = true;
// 命中敌人,立即取消硬直
CancelSkillHardness();
// 处理伤害逻辑...
DealDamage(other.GetComponent<Attribute>());
}
}
// 取消技能硬直
private void CancelSkillHardness()
{
PlayerController player = GetComponentInParent<PlayerController>();
if (player != null)
{
// 调用玩家控制器的取消硬直方法(需在PlayerController中实现)
player.CancelHardness();
Debug.Log("DashStab命中敌人,立即取消硬直");
}
}
// 技能结束后重置状态
private void OnSkillEnd()
{
hasHitEnemy = false;
}
}
// 3. 技能连招成就系统
public class ComboAchievementSystem : MonoBehaviour
{
[Header("成就配置")]
public Achievement comboMasterAchievement; // 连招大师:连续3次不同连招
private List<string> recentCombos = new List<string>();
private float comboMemoryDuration = 5f; // 连招记忆时长(5秒内的连招计入统计)
// 记录触发的连招
public void OnComboTriggered(string comboId)
{
// 移除超时的连招记录
recentCombos.RemoveAll(c => Time.time - c.Split('|')[1].ToFloat() > comboMemoryDuration);
// 添加新连招(格式:连招ID|触发时间)
recentCombos.Add($"{comboId}|{Time.time}");
// 去重,统计不同连招数量
HashSet<string> uniqueCombos = new HashSet<string>(recentCombos.Select(c => c.Split('|')[0]));
// 解锁"连招大师"成就
if (uniqueCombos.Count >= 3 && !comboMasterAchievement.IsUnlocked)
{
UnlockAchievement(comboMasterAchievement);
}
}
// 解锁成就
private void UnlockAchievement(Achievement achievement)
{
achievement.IsUnlocked = true;
// 显示成就解锁弹窗
AchievementPopupUI.Show(achievement.Icon, achievement.Name, achievement.Description);
Debug.Log($"成就解锁:{achievement.Name}");
}
// 成就数据结构
[System.Serializable]
public class Achievement
{
public string Name;
public string Description;
public Sprite Icon;
public bool IsUnlocked = false;
}
}