ddl战士———α冲刺Day6

ddl战士 2025-11-04 21:49:24
这个作业属于哪个课程2501_CS_SE_FZU
这个作业要求在哪里团队作业——站立式会议+α冲刺
这个作业的目标α冲刺Day6
其他参考文献《构建之法》、Google Style Guides

1. 站立式会议照片

img

2. 项目燃尽图

img

3. 成员工作总结

成员角色昨日至今日日站立会安排存在的问题 / 遇到的困难心得体会今日至明日站立会安排
陈志豪(敌人模块)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 次不同连招解锁 “连招大师” 成就),增加玩法趣味性,激励玩家探索更多技能组合。

4.成果证明

敌人模块

// 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;
    }
}
...全文
73 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

103

社区成员

发帖
与我相关
我的任务
社区描述
2501_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_LQF
  • 木村修
  • 心态773
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧