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


| 成员角色 | 昨日至今日日站立会安排 | 存在的问题 / 遇到的困难 | 心得体会 | 今日至明日站立会安排 |
|---|---|---|---|---|
| 陈志豪(敌人模块) | 1. 开发敌人 “攻击前摇 / 后摇” 逻辑,为普通敌人设置 0.5s 前摇、精英敌人 0.8s 前摇;2. 测试敌人 AI 追击范围,初步调整追击距离参数;3. 联调敌人死亡与玩家拾取系统,验证尸体资源清理逻辑。 | 精英敌人攻击后摇过长,导致玩家可连续攻击无反击空间,战斗难度失衡;敌人追击范围调整后,仍存在 “追击到地图边缘后无法返回原区域” 的问题。 | 这次做敌人攻击节奏和追击逻辑,深刻体会到 “数值平衡直接影响战斗体验”。精英敌人原本 0.8s 前摇搭配 1s 后摇,玩家能轻松绕后输出,完全没压迫感,后来把后摇缩短到 0.6s 才找回精英怪的强度。另外追击范围边界处理没做好,敌人跑出巡逻区就 “迷路”,添加 “超出范围 10 秒后返回原点” 的逻辑才解决,这让我明白 AI 行为不仅要考虑 “追”,还要规划 “归” 的路径。 | 1. 优化精英敌人攻击后摇时长,从 0.8s 调整至 0.6s,平衡战斗难度;2. 为敌人添加 “超出巡逻范围 10 秒自动返回原点” 的逻辑,解决追击迷路问题;3. 测试多敌人混战场景下的 AI 行为,避免敌人互相阻挡导致攻击卡顿。 |
| 胡定赟 (UI/UX 设计) | 1. 完成死亡 UI 开发,添加死亡提示文字、3 秒重生倒计时与返回主菜单按钮;2. 优化背包 UI 在 720p 分辨率下的显示,调整为 3 列 4 行布局;3. 为技能栏 UI 添加 U/I/O/L 键按键提示图标。 | 死亡 UI 重生倒计时结束后,偶发 “重生按钮仍可点击” 的 bug,导致重复触发重生逻辑;技能栏按键提示图标在 2K 高分辨率下显示模糊,图标像素不足。 | UI 开发中 “状态同步” 和 “资源适配” 是两大关键。死亡 UI 倒计时结束后,没及时禁用重生按钮,玩家点击就会重复触发重生,加了 “倒计时结束置灰按钮” 的逻辑才修复。高分辨率下图标模糊则是因为用了低像素素材,重新导出 2 倍尺寸的图标后显示才清晰。现在做 UI 时,我会先梳理所有交互状态的切换逻辑,再准备多分辨率适配的资源,避免后期返工。 | 1. 修复死亡 UI 重生按钮状态 bug,添加 “倒计时结束禁用按钮” 逻辑;2. 重新制作 2K 分辨率适配的技能栏按键提示图标,提升显示清晰度;3. 为背包 UI 添加 “物品数量超过 99 时显示省略号(如 99+)” 的功能,优化信息展示。 |
| 阮航宇 (地图与资源设计) | 1. 开发恢复泉水交互逻辑,实现每 2 秒恢复 10% 生命值 / MP 的功能;2. 补全地图边缘岩石、火把等装饰元素;3. 测试地图全区域碰撞,排查地形缝隙卡角色问题。 | 恢复泉水粒子特效与恢复数值飘字不同步,特效播放时数值未及时显示;地图部分角落装饰元素与碰撞体重叠,导致玩家靠近时视觉穿透。 | 地图交互物开发让我明白 “多元素协同要统一时序”。恢复泉水原本是先播特效再显示数值,玩家看到特效却没数值反馈,还以为没生效,调整为 “特效与数值同时触发” 后体验更直观。装饰元素与碰撞体重叠则是因为摆放时没对齐碰撞体边界,逐一对齐位置后解决。现在做地图时,会把交互物的特效、数值、逻辑放在同一时序里,同时检查视觉元素与碰撞体的位置匹配度。 | 1. 同步恢复泉水粒子特效与数值飘字触发时序,确保两者同时显示;2. 调整地图角落装饰元素位置,避免与碰撞体重叠导致视觉穿透;3. 在地图关键路径添加 “指路箭头” UI 提示,引导玩家探索方向。 |
| 张天荣 (攻击模块) | 1. 集成火 / 冰元素攻击效果与攻击判定联动,实现点燃、冻结敌人逻辑;2. 修复攻击盒近距离判定盲区,添加 0.2f 半径的 SphereCast 球形检测;3. 测试不同攻击角度下的判定准确性,调整攻击盒朝向跟随角色面朝方向翻转。 | 冰元素冻结敌人时,偶尔出现 “冻结时间结束后敌人无法移动” 的 bug;SphereCast 球形检测与原攻击盒判定范围重叠,导致部分攻击重复计算伤害。 | 元素攻击开发中 “状态重置” 和 “判定范围隔离” 很重要。冰元素冻结结束后,没重置敌人的移动状态,导致敌人卡住,加了 “冻结结束恢复移动组件” 的逻辑才修复。攻击判定重复计算则是因为没区分两种检测的触发条件,添加 “优先触发原攻击盒,未命中再触发 SphereCast” 的逻辑后解决。现在做攻击系统时,我会关注异常状态结束后的重置逻辑,同时规划不同判定方式的优先级,避免冲突。 | 1. 修复冰元素冻结敌人后的移动状态 bug,添加 “冻结结束恢复移动” 逻辑;2. 优化攻击判定优先级,设置 “原攻击盒未命中时再触发 SphereCast 检测”,避免重复计算伤害;3. 为元素攻击添加 “属性克制提示”(如 “火克冰” 弹出文字),提升玩法策略性。 |
| 汪涛(测试与性能优化、玩家模块) | 1. 优化玩家重生与死亡动画衔接,绑定 1.5s 死亡动画时长与重生倒计时;2. 执行玩家 - 敌人 - 攻击 - 技能全流程测试,记录技能释放后攻击无响应等问题;3. 调整玩家空中移动加速度,从 10f 降至 8f,减少滑步感。 | 全流程测试中发现 “技能释放后 0.3 秒内无法触发攻击” 的延迟问题;玩家空中移动加速度调整后,下落时仍存在轻微飘动感。 | 全流程测试能暴露模块联动的隐藏问题。技能释放后攻击延迟,是因为技能逻辑里加了 0.3 秒的输入锁定,忘记移除,取消锁定后恢复正常。空中飘动感则是因为没调整下落重力参数,把重力从 20f 提升至 25f 后解决。现在我不仅会测试单个模块功能,还会重点跑全流程场景,同时关注参数调整对关联体验的影响,比如改加速度要同步检查重力是否匹配。 | 1. 修复技能释放后攻击延迟问题,取消技能逻辑中的 0.3 秒输入锁定;2. 调整玩家下落重力参数,从 20f 提升至 25f,解决空中飘动感;3. 优化玩家受击无敌帧判定,避免无敌期间仍被敌人攻击命中。 |
| 莫馥玮(技能模块) | 1. 完成近战技能 DashStab 开发,实现向前冲刺 2 米 + 沿途攻击判定;2. 修复技能 MP 消耗计算异常,添加等级系数(MP 消耗 = 基础消耗 ×(1+0.1× 技能等级));3. 为技能释放添加 MP 不足弹窗提示与音效。 | DashStab 技能冲刺过程中,偶尔会穿透敌人碰撞体,导致攻击判定失效;技能等级系数计算时,未处理基础消耗为 0 的异常情况,出现 MP 消耗为 0 的 bug。 | 技能开发中 “边界情况处理” 不能忽视。DashStab 穿透敌人是因为冲刺时没启用碰撞检测,加了 “冲刺期间开启连续碰撞检测” 的逻辑后解决。MP 消耗为 0 则是因为没判断基础消耗是否为 0,添加 “基础消耗为 0 时默认按 1 点计算” 的兜底逻辑才修复。现在做技能时,会提前梳理所有可能的边界情况,比如参数异常、碰撞失效等,逐一添加处理逻辑。 | 1. 修复 DashStab 技能冲刺穿透敌人问题,添加 “冲刺期间连续碰撞检测” 逻辑;2. 完善技能 MP 消耗计算兜底逻辑,基础消耗为 0 时默认按 1 点计算;3. 为技能释放添加 “冷却中弹窗提示”,告知玩家剩余冷却时间。 |
玩家模块
private void OnDeathAnimationEnd()
{
// 绑定死亡动画时长与重生倒计时,避免卡顿
Invoke(nameof(TriggerRespawn), 1.5f);
}
private void TriggerRespawn()
{
transform.position = spawnPoint.position;
currentHealth = maxHealth;
// 修复空中飘动感,调整下落重力
rb.gravityScale = 25f;
Debug.Log("玩家重生,重力参数已更新");
}
// 优化受击无敌帧判定
private void OnTakeDamage()
{
if (isInvincible) return;
currentHealth -= damageTaken;
isInvincible = true;
Invoke(nameof(EndInvincibility), 1f); // 1秒无敌帧
}
private void EndInvincibility()
{
isInvincible = false;
}
敌人模块
// 优化精英敌人攻击后摇,平衡战斗难度
private void SetEnemyAttackTiming()
{
if (enemyType == EnemyType.Elite)
{
attackWindup = 0.8f;
attackRecovery = 0.6f; // 缩短后摇时长
}
else
{
attackWindup = 0.5f;
attackRecovery = 0.4f;
}
}
// 解决敌人追击迷路问题,添加自动返回逻辑
private void Update()
{
if (IsChasingPlayer() && Vector2.Distance(transform.position, patrolOrigin) > chaseRange)
{
chaseTimer += Time.deltaTime;
if (chaseTimer >= 10f)
{
StopChasing();
ReturnToPatrolOrigin();
chaseTimer = 0f;
}
}
}
攻击模块
// 优化元素攻击与判定联动,修复冻结后移动bug
private void ApplyElementEffect(Enemy enemy, ElementType type)
{
switch (type)
{
case ElementType.Fire:
enemy.ApplyBurn(3f, 5f); // 燃烧3秒,每秒5点伤害
break;
case ElementType.Ice:
enemy.ApplyFreeze(2f); // 冻结2秒
enemy.OnFreezeEnd += ResetEnemyMovement; // 绑定冻结结束回调
break;
}
}
// 冻结结束恢复敌人移动
private void ResetEnemyMovement(Enemy enemy)
{
enemy.EnableMovement();
enemy.OnFreezeEnd -= ResetEnemyMovement; // 移除回调避免重复触发
}
// 优化攻击判定优先级,避免重复计算
private void CheckAttackHit()
{
// 优先检测原攻击盒
if (Physics2D.OverlapBox(attackBox.position, attackBox.size, 0f, enemyLayer))
{
DealDamage();
}
// 原攻击盒未命中时,检测SphereCast
else
{
if (Physics2D.SphereCast(transform.position, 0.2f, attackDirection, out RaycastHit2D hit, 0.5f, enemyLayer))
{
DealDamage(hit.collider.GetComponent<Enemy>());
}
}
}
技能模块
// 修复DashStab技能冲刺穿透敌人问题
private void PerformDashStab()
{
isDashing = true;
rb.velocity = new Vector2(dashDirection.x * dashSpeed, 0f);
Physics2D.IgnoreLayerCollision(playerLayer, enemyLayer, false); // 开启碰撞检测
StartCoroutine(EndDash());
}
private IEnumerator EndDash()
{
yield return new WaitForSeconds(0.3f);
isDashing = false;
rb.velocity = Vector2.zero;
}
// 完善MP消耗计算兜底逻辑
private int CalculateMPCost()
{
int baseCost = skillData.baseMPCost;
// 基础消耗为0时默认按1点计算
if (baseCost <= 0) baseCost = 1;
return Mathf.RoundToInt(baseCost * (1 + 0.1f * skillLevel));
}
// 添加技能冷却中提示
private void OnSkillCastFailed(CastFailReason reason)
{
if (reason == CastFailReason.OnCooldown)
{
float remainingCD = skillCD - (Time.time - lastCastTime);
ShowPopup($"技能冷却中,剩余{Mathf.Round(remainingCD)}秒");
}
}
UI/UX 设计
// 修复死亡UI重生按钮状态bug
private void UpdateDeathUI()
{
countdownTimer -= Time.deltaTime;
countdownText.text = $"{Mathf.Ceil(countdownTimer)}秒后自动重生";
if (countdownTimer <= 0)
{
TriggerRespawn();
respawnButton.interactable = false; // 禁用按钮
respawnButton.image.color = Color.gray; // 置灰按钮
}
}
// 为背包UI添加物品数量省略号显示
private void UpdateItemCountText(Item item)
{
if (item.count > 99)
{
itemCountText.text = "99+";
}
else
{
itemCountText.text = item.count.ToString();
}
}
// 重新制作高分辨率技能按键图标
private void LoadSkillIcon(SkillType type)
{
string iconPath = $"Icons/Skill/{type}_2x"; // 加载2倍尺寸图标
Texture2D iconTexture = Resources.Load<Texture2D>(iconPath);
if (iconTexture != null)
{
skillIcon.sprite = Sprite.Create(iconTexture, new Rect(0, 0, iconTexture.width, iconTexture.height), new Vector2(0.5f, 0.5f));
}
}
地图模块
