feat(gameplay): 提升单位检测范围并添加法师属性

- 将所有单位的检测范围从默认值提升至100
- 为法师预制体添加护盾、等级等新属性
- 为法师添加暴击、吸血、伤害减免等战斗属性
- 更换法师弹丸预设并调整相关参数
- 添加锚点交战Z线控制功能
- 更新玩家数据中配备的召唤师技能
- 移除多余的纹理配置文件
```
This commit is contained in:
huadexuan committed 2026-10-07 23:59:17 +08:00
1 parent 6089308f66
commit 23c559d9f7
243 files changed
+150612 -1459

No files matched your search

@@ -44,10 +44,12 @@ public class DefenseWaveLevelController : MonoBehaviour
public float spawnY = 0.16f;
public float waveCompleteDelay = 3f;
[Header("UI 绑定")]
public Text waveTextUI; // 绑定 TowerDefenseCanvas/TopBar/WaveText
public Text killCountTextUI; // 绑定 TowerDefenseCanvas/TopBar/KillCountText
private LevelWaveFile level;
private readonly List<GameObject> activeEnemies = new List<GameObject>();
private Slider progressSlider;
private Text progressText;
private int currentWaveIndex = -1;
private int totalEnemies;
private int defeatedEnemies;
@@ -55,7 +57,8 @@ public class DefenseWaveLevelController : MonoBehaviour
private void Start()
{
if (!LoadLevel()) return;
CreateProgressBar();
EnsureUIReferences();
UpdateProgress(0, level.waves.Length, "准备中");
if (autoStart) StartCoroutine(RunLevel());
}
@@ -105,6 +108,12 @@ public class DefenseWaveLevelController : MonoBehaviour
// 每波结束后,让英雄回到初始位置
ResetHeroPositionsAfterWave();
// 每 2 波结束(第 2、4、6、8...波)触发 3 选 1 战术增益弹窗
if ((currentWaveIndex + 1) % 2 == 0)
{
BuffSelectionController.Instance.ShowBuffSelection();
}
yield return new WaitForSeconds(Mathf.Max(0f, waveCompleteDelay));
}
@@ -177,6 +186,16 @@ public class DefenseWaveLevelController : MonoBehaviour
{
activeEnemies.RemoveAt(i);
defeatedEnemies++;
// 击杀金币奖励 (基础 15 金币 * 战术增益倍率)
if (GoldManager.Instance != null)
{
float killMult = BuffSelectionController.KillGoldMultiplier;
int goldAmount = Mathf.RoundToInt(15f * killMult);
GoldManager.Instance.AddGold(goldAmount);
}
UpdateProgress(currentWaveIndex + 1, level.waves.Length);
}
}
@@ -207,7 +226,9 @@ public class DefenseWaveLevelController : MonoBehaviour
}
if (unit == null) return;
unit.InitializeFromPlayerData(data.GetMaxHealth(1), data.GetAttackPower(1), data.GetMoveSpeed(1));
// 小怪等级根据波次索引动态计算(前几波 Lv.1,随着波次推进适度成长,如 1~3 波 Lv.1,4~6 波 Lv.2,7~10 波 Lv.3)
int enemyLevel = Mathf.Clamp((currentWaveIndex / 3) + 1, 1, 10);
unit.InitializeFromPlayerData(data.GetMaxHealth(enemyLevel), data.GetAttackPower(enemyLevel), data.GetMoveSpeed(enemyLevel), enemyLevel);
}
private int TotalCount(WaveEntry wave)
@@ -228,60 +249,42 @@ public class DefenseWaveLevelController : MonoBehaviour
return entry.prefab;
}
private void CreateProgressBar()
private void EnsureUIReferences()
{
var canvasObject = new GameObject("WaveProgressHUD", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
var canvas = canvasObject.GetComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 500;
if (waveTextUI != null && killCountTextUI != null) return;
var root = canvasObject.GetComponent<RectTransform>();
var panel = new GameObject("WaveProgressPanel", typeof(RectTransform), typeof(Image));
panel.transform.SetParent(root, false);
var panelRect = panel.GetComponent<RectTransform>();
panelRect.anchorMin = new Vector2(0.5f, 1f);
panelRect.anchorMax = new Vector2(0.5f, 1f);
panelRect.pivot = new Vector2(0.5f, 1f);
panelRect.anchoredPosition = new Vector2(0f, -20f);
panelRect.sizeDelta = new Vector2(420f, 64f);
panel.GetComponent<Image>().color = new Color(0f, 0f, 0f, 0.45f);
var canvasObject = GameObject.Find("TowerDefenseCanvas");
if (canvasObject == null) return;
var sliderObject = new GameObject("WaveProgress", typeof(RectTransform), typeof(Slider));
sliderObject.transform.SetParent(panel.transform, false);
var sliderRect = sliderObject.GetComponent<RectTransform>();
sliderRect.anchorMin = new Vector2(0.5f, 0f);
sliderRect.anchorMax = new Vector2(0.5f, 0f);
sliderRect.pivot = new Vector2(0.5f, 0f);
sliderRect.anchoredPosition = new Vector2(0f, 10f);
sliderRect.sizeDelta = new Vector2(360f, 16f);
progressSlider = sliderObject.GetComponent<Slider>();
progressSlider.minValue = 0f;
progressSlider.maxValue = 1f;
progressSlider.value = 0f;
progressSlider.interactable = false;
var topBar = canvasObject.transform.Find("TopBar");
if (topBar == null) return;
var textObject = new GameObject("WaveProgressText", typeof(RectTransform), typeof(Text));
textObject.transform.SetParent(panel.transform, false);
var textRect = textObject.GetComponent<RectTransform>();
textRect.anchorMin = new Vector2(0.5f, 1f);
textRect.anchorMax = new Vector2(0.5f, 1f);
textRect.pivot = new Vector2(0.5f, 1f);
textRect.anchoredPosition = new Vector2(0f, -8f);
textRect.sizeDelta = new Vector2(390f, 28f);
progressText = textObject.GetComponent<Text>();
progressText.alignment = TextAnchor.MiddleCenter;
progressText.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
progressText.fontSize = 18;
progressText.color = Color.white;
if (waveTextUI == null)
{
var waveObj = topBar.Find("WaveText");
if (waveObj != null) waveTextUI = waveObj.GetComponent<Text>();
}
if (killCountTextUI == null)
{
var killObj = topBar.Find("KillCountText");
if (killObj != null) killCountTextUI = killObj.GetComponent<Text>();
}
}
private void UpdateProgress(int waveNumber, int waveCount, string text)
private void UpdateProgress(int waveNumber, int waveCount, string statusHint = "")
{
if (progressSlider != null)
EnsureUIReferences();
int currentDisplayWave = Mathf.Clamp(waveNumber > 0 ? waveNumber : 1, 1, waveCount);
if (waveTextUI != null)
{
float defeatedRatio = totalEnemies > 0 ? (float)defeatedEnemies / totalEnemies : 0f;
progressSlider.value = Mathf.Clamp01((waveNumber - 1 + defeatedRatio) / Mathf.Max(1, waveCount));
waveTextUI.text = $"波次 {currentDisplayWave}/{waveCount}";
}
if (killCountTextUI != null)
{
killCountTextUI.text = $"击杀 {defeatedEnemies}/{totalEnemies}";
}
if (progressText != null) progressText.text = text;
}
}