```
feat(player): 添加玩家阵型保存功能 新增savedFormation字段用于存储玩家的阵型配置, 包括角色ID列表和对应的格子索引位置信息。 ```
This commit is contained in:
1 parent
e127da5416
commit
1abd0de32f
16 files changed
+432
-2930
No files matched your search
@@ -1,17 +1,53 @@
|
||||
{
|
||||
"playerId": "local_player",
|
||||
"unlockedCharacters": [
|
||||
{ "characterId": "human_soldier", "level": 1, "starLevel": 0 },
|
||||
{ "characterId": "archer", "level": 1, "starLevel": 0 },
|
||||
{ "characterId": "shield_guard", "level": 1, "starLevel": 0 },
|
||||
{ "characterId": "mage", "level": 1, "starLevel": 0 },
|
||||
{ "characterId": "elite_soldier", "level": 1, "starLevel": 0 }
|
||||
],
|
||||
"currentDeck": [
|
||||
"human_soldier",
|
||||
"archer",
|
||||
"shield_guard",
|
||||
"mage",
|
||||
"elite_soldier"
|
||||
]
|
||||
}
|
||||
"playerId": "local_player",
|
||||
"unlockedCharacters": [
|
||||
{
|
||||
"characterId": "human_soldier",
|
||||
"level": 1,
|
||||
"starLevel": 0
|
||||
},
|
||||
{
|
||||
"characterId": "archer",
|
||||
"level": 1,
|
||||
"starLevel": 0
|
||||
},
|
||||
{
|
||||
"characterId": "shield_guard",
|
||||
"level": 1,
|
||||
"starLevel": 0
|
||||
},
|
||||
{
|
||||
"characterId": "mage",
|
||||
"level": 1,
|
||||
"starLevel": 0
|
||||
},
|
||||
{
|
||||
"characterId": "elite_soldier",
|
||||
"level": 1,
|
||||
"starLevel": 0
|
||||
}
|
||||
],
|
||||
"currentDeck": [
|
||||
"human_soldier",
|
||||
"archer",
|
||||
"shield_guard",
|
||||
"mage",
|
||||
"elite_soldier"
|
||||
],
|
||||
"savedFormation": {
|
||||
"characterIds": [
|
||||
"archer",
|
||||
"mage",
|
||||
"human_soldier",
|
||||
"elite_soldier",
|
||||
"shield_guard"
|
||||
],
|
||||
"cellIndices": [
|
||||
1,
|
||||
4,
|
||||
14,
|
||||
15,
|
||||
27
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
+73
-2742
File diff suppressed because it is too large.
Load diff
@@ -1,137 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// 自动绑定友方英雄到UI卡片(Play Mode自动运行)
|
||||
/// </summary>
|
||||
public class AutoBindHeroes : MonoBehaviour
|
||||
{
|
||||
[Header("UI引用")]
|
||||
[Tooltip("英雄卡片面板的父物体")]
|
||||
public Transform heroCardsPanel;
|
||||
|
||||
[Header("英雄头像资源")]
|
||||
public Sprite soldierIcon;
|
||||
public Sprite archerIcon;
|
||||
public Sprite shieldIcon;
|
||||
public Sprite mageIcon;
|
||||
public Sprite eliteSoldierIcon;
|
||||
|
||||
private bool hasBindOnce = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// 延迟1秒等待所有英雄生成
|
||||
Invoke(nameof(BindHeroesToCards), 1f);
|
||||
}
|
||||
|
||||
void BindHeroesToCards()
|
||||
{
|
||||
if (hasBindOnce)
|
||||
{
|
||||
Debug.LogWarning("英雄已经绑定过了,跳过重复绑定");
|
||||
return;
|
||||
}
|
||||
|
||||
if (heroCardsPanel == null)
|
||||
{
|
||||
Debug.LogError("AutoBindHeroes: heroCardsPanel 未赋值!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 查找所有友方英雄(teamId=0)
|
||||
var allUnits = FindObjectsOfType<UnitBase>();
|
||||
var heroes = new List<UnitBase>();
|
||||
|
||||
foreach (var unit in allUnits)
|
||||
{
|
||||
var team = unit.GetComponent<UnitTeam>();
|
||||
if (team != null && team.teamId == 0)
|
||||
{
|
||||
heroes.Add(unit);
|
||||
}
|
||||
}
|
||||
|
||||
if (heroes.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("AutoBindHeroes: 未找到友方英雄(teamId=0)");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"AutoBindHeroes: 找到 {heroes.Count} 个友方英雄");
|
||||
|
||||
// 2. 设置所有英雄为可复活
|
||||
foreach (var hero in heroes)
|
||||
{
|
||||
var health = hero.GetComponent<WorldHealthBar>();
|
||||
if (health != null)
|
||||
{
|
||||
health.canRevive = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 绑定到UI卡片(最多5个)
|
||||
int bindCount = Mathf.Min(heroes.Count, 5);
|
||||
for (int i = 0; i < bindCount; i++)
|
||||
{
|
||||
var hero = heroes[i];
|
||||
var cardObj = heroCardsPanel.Find($"HeroCard{i + 1}");
|
||||
|
||||
if (cardObj == null)
|
||||
{
|
||||
Debug.LogWarning($"AutoBindHeroes: 未找到 HeroCard{i + 1}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var heroCardUI = cardObj.GetComponent<HeroCardUI>();
|
||||
if (heroCardUI == null)
|
||||
{
|
||||
Debug.LogWarning($"AutoBindHeroes: HeroCard{i + 1} 缺少 HeroCardUI 组件");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据英雄名字匹配头像
|
||||
Sprite icon = GetHeroIcon(hero.name);
|
||||
if (icon == null)
|
||||
{
|
||||
Debug.LogWarning($"AutoBindHeroes: {hero.name} 没有匹配的头像,使用默认图标");
|
||||
}
|
||||
|
||||
// 绑定英雄
|
||||
heroCardUI.SetHero(hero, icon, hero.transform.position);
|
||||
Debug.Log($"✅ HeroCard{i + 1} 已绑定: {hero.name}");
|
||||
}
|
||||
|
||||
hasBindOnce = true;
|
||||
Debug.Log($"<color=green>✅ 英雄自动绑定完成!共绑定 {bindCount} 个英雄</color>");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据英雄名字获取对应头像
|
||||
/// </summary>
|
||||
Sprite GetHeroIcon(string heroName)
|
||||
{
|
||||
if (heroName.Contains("人类士兵") || heroName.Contains("士兵"))
|
||||
{
|
||||
return soldierIcon;
|
||||
}
|
||||
else if (heroName.Contains("弓箭手") || heroName.Contains("弓箭"))
|
||||
{
|
||||
return archerIcon;
|
||||
}
|
||||
else if (heroName.Contains("盾卫"))
|
||||
{
|
||||
return shieldIcon;
|
||||
}
|
||||
else if (heroName.Contains("法师"))
|
||||
{
|
||||
return mageIcon;
|
||||
}
|
||||
else if (heroName.Contains("精锐"))
|
||||
{
|
||||
return eliteSoldierIcon;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: BntLsXv+VCiekq1pfBLqrcgPxyOKiyT9GMwu39MKq/rePWiFpCWwjlw=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -25,7 +25,19 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
|
||||
private void SpawnHeroes()
|
||||
{
|
||||
// 1. 玩家编排过的阵型
|
||||
// 1. 优先从 PlayerData.json 读取保存的阵型
|
||||
if (PlayerDataManager.Instance != null)
|
||||
{
|
||||
SavedFormationData formationData = PlayerDataManager.Instance.LoadFormation();
|
||||
if (formationData != null && formationData.characterIds != null && formationData.characterIds.Length > 0)
|
||||
{
|
||||
Debug.Log($"从 PlayerData.json 加载阵型,共 {formationData.characterIds.Length} 个英雄");
|
||||
SpawnFromSavedFormation(formationData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 回退到 FormationData(场景间临时传递的数据)
|
||||
if (FormationData.HasCustomFormation
|
||||
&& FormationData.HeroPrefabs != null
|
||||
&& FormationData.HeroPrefabs.Length > 0)
|
||||
@@ -42,10 +54,54 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 没有编排数据:默认阵型
|
||||
// 3. 没有任何编排数据:使用默认阵型
|
||||
SpawnDefaultFormation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从保存的阵型数据生成英雄
|
||||
/// </summary>
|
||||
private void SpawnFromSavedFormation(SavedFormationData formationData)
|
||||
{
|
||||
for (int i = 0; i < formationData.characterIds.Length; i++)
|
||||
{
|
||||
string characterId = formationData.characterIds[i];
|
||||
int cell = i < formationData.cellIndices.Length ? formationData.cellIndices[i] : -1;
|
||||
|
||||
if (string.IsNullOrEmpty(characterId) || !DeployGrid.IsValidIndex(cell))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据 characterId 找到对应的 Prefab
|
||||
GameObject prefab = FindPrefabByCharacterId(characterId);
|
||||
if (prefab != null)
|
||||
{
|
||||
Spawn(prefab, cell);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"未找到 characterId={characterId} 对应的 Prefab");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据 characterId 查找对应的 Prefab
|
||||
/// </summary>
|
||||
private GameObject FindPrefabByCharacterId(string characterId)
|
||||
{
|
||||
var allData = Resources.LoadAll<CharacterData>("Data");
|
||||
foreach (var data in allData)
|
||||
{
|
||||
if (data.characterId == characterId)
|
||||
{
|
||||
return data.unitPrefab;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SpawnDefaultFormation()
|
||||
{
|
||||
if (roster == null || roster.heroes == null) return;
|
||||
@@ -89,7 +145,7 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int spawnedHeroCount = 0; // 记录已生成英雄数量
|
||||
private int spawnedHeroCount = 0; // 记录已生成英雄数量(改为实例变量)
|
||||
|
||||
private void Spawn(GameObject prefab, int cell)
|
||||
{
|
||||
@@ -141,25 +197,49 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
|
||||
private void BindHeroToCard(GameObject heroUnit, CharacterData characterData, Vector3 spawnPos)
|
||||
{
|
||||
if (spawnedHeroCount >= 5) return; // 最多5个英雄
|
||||
if (spawnedHeroCount >= 5)
|
||||
{
|
||||
Debug.LogWarning($"已达到最大英雄数量5,跳过绑定 {heroUnit.name}");
|
||||
return; // 最多5个英雄
|
||||
}
|
||||
|
||||
// 查找对应的卡片
|
||||
Canvas canvas = FindObjectOfType<Canvas>();
|
||||
if (canvas == null) return;
|
||||
// 查找 TowerDefenseCanvas
|
||||
GameObject canvasObj = GameObject.Find("TowerDefenseCanvas");
|
||||
if (canvasObj == null)
|
||||
{
|
||||
Debug.LogError("BindHeroToCard: 未找到 TowerDefenseCanvas");
|
||||
return;
|
||||
}
|
||||
|
||||
Transform heroPanel = canvas.transform.Find("BottomUI/HeroCardsPanel");
|
||||
if (heroPanel == null) return;
|
||||
Transform heroPanel = canvasObj.transform.Find("BottomUI/HeroCardsPanel");
|
||||
if (heroPanel == null)
|
||||
{
|
||||
Debug.LogError("BindHeroToCard: 未找到 BottomUI/HeroCardsPanel");
|
||||
return;
|
||||
}
|
||||
|
||||
string cardName = $"HeroCard{spawnedHeroCount + 1}";
|
||||
Transform cardObj = heroPanel.Find(cardName);
|
||||
if (cardObj == null) return;
|
||||
if (cardObj == null)
|
||||
{
|
||||
Debug.LogError($"BindHeroToCard: 未找到 {cardName}");
|
||||
return;
|
||||
}
|
||||
|
||||
HeroCardUI heroCardUI = cardObj.GetComponent<HeroCardUI>();
|
||||
if (heroCardUI == null) return;
|
||||
if (heroCardUI == null)
|
||||
{
|
||||
Debug.LogError($"BindHeroToCard: {cardName} 缺少 HeroCardUI 组件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取英雄单位组件
|
||||
UnitBase unitBase = heroUnit.GetComponent<UnitBase>();
|
||||
if (unitBase == null) return;
|
||||
if (unitBase == null)
|
||||
{
|
||||
Debug.LogError($"BindHeroToCard: {heroUnit.name} 缺少 UnitBase 组件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载对应的头像
|
||||
UnityEngine.Sprite icon = characterData != null ? characterData.cardIcon : null;
|
||||
@@ -169,7 +249,7 @@ public class BattleFormationSpawner : MonoBehaviour
|
||||
|
||||
spawnedHeroCount++;
|
||||
|
||||
Debug.Log($"英雄 {heroUnit.name} 已绑定到 {cardName}");
|
||||
Debug.Log($"✅ {cardName} 已绑定英雄: {heroUnit.name}(第 {spawnedHeroCount} 个)");
|
||||
}
|
||||
|
||||
private CharacterData FindCharacterDataForPrefab(GameObject prefab)
|
||||
|
||||
@@ -56,6 +56,12 @@ public class CastleSpawnManager : MonoBehaviour
|
||||
float atk = playerData.GetAttackPower(data);
|
||||
float spd = playerData.GetMoveSpeed(data);
|
||||
unitBase.InitializeFromPlayerData(hp, atk, spd);
|
||||
|
||||
// 如果是敌人(teamId != 0),增大寻敌距离
|
||||
if (teamId != 0)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"城堡出兵: {data.characterName} teamId={teamId} pos={spawnPoint.position}");
|
||||
|
||||
@@ -114,6 +114,14 @@ public class DefenseWaveLevelController : MonoBehaviour
|
||||
: (spawned % 2 == 0 ? -3f : 3f);
|
||||
var enemy = Instantiate(prefab, new Vector3(x, spawnY, spawnZ), Quaternion.identity);
|
||||
enemy.tag = "Enemy";
|
||||
|
||||
// 增大敌人的寻敌距离
|
||||
UnitBase unitBase = enemy.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
|
||||
ApplyCharacterData(enemy, wave.enemyIds[typeIndex]);
|
||||
activeEnemies.Add(enemy);
|
||||
spawned++;
|
||||
|
||||
@@ -8,11 +8,11 @@ public static class DeployGrid
|
||||
{
|
||||
public const int Cols = 6;
|
||||
public const int Rows = 5;
|
||||
public const float ColStep = 2.8f;
|
||||
public const float RowStep = 3.0f;
|
||||
public const float BackZ = 2.5f; // 最靠后一排的中心 Z(让部署区落在底部卡片栏上方)
|
||||
public const float ColStep = 2.4f; // 列间距改为2.4,让网格更紧凑,避免最边缘格子太靠外
|
||||
public const float RowStep = 2.8f; // 行间距保持2.8
|
||||
public const float BackZ = -15.0f; // 最靠后一排的中心 Z(调整到靠近摄像机的底部区域)
|
||||
public const float CellWidth = 2.5f;
|
||||
public const float CellDepth = 2.7f;
|
||||
public const float CellDepth = 2.5f; // 格子深度改为2.5,与宽度相同,形成正方形
|
||||
public const float CellHeight = 0.03f;
|
||||
public const float GridY = 0.12f; // 格位可视块的中心高度
|
||||
public const float UnitY = 0.16f; // 单位落点高度(与 NavMesh 高度一致)
|
||||
|
||||
@@ -236,6 +236,12 @@ public class EnemyCastleAI : MonoBehaviour
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.InitializeFromPlayerData(data.GetMaxHealth(1), data.GetAttackPower(1), data.GetMoveSpeed(1));
|
||||
|
||||
// 如果是敌人(teamId != 0),增大寻敌距离
|
||||
if (spawnTeamId != 0)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -310,17 +310,67 @@ public class FormationManager : MonoBehaviour
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ===== 进入战斗 =====
|
||||
// ===== 保存阵型 =====
|
||||
|
||||
public void StartBattle()
|
||||
{
|
||||
FillUnplacedWithDefault();
|
||||
SaveFormation();
|
||||
SaveFormationToJson();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(battleSceneName))
|
||||
private void SaveFormationToJson()
|
||||
{
|
||||
int count = HeroCount;
|
||||
var characterIds = new string[count];
|
||||
var cells = new int[count];
|
||||
|
||||
// 初始化数组
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
SceneManager.LoadScene(battleSceneName);
|
||||
HeroEntry entry = GetHero(i);
|
||||
characterIds[i] = entry != null ? GetCharacterId(entry.prefab) : "";
|
||||
cells[i] = -1;
|
||||
}
|
||||
|
||||
// 填充已放置的格位
|
||||
foreach (var pair in placed)
|
||||
{
|
||||
int heroIndex = pair.Value.heroIndex;
|
||||
if (heroIndex >= 0 && heroIndex < count)
|
||||
{
|
||||
cells[heroIndex] = pair.Key;
|
||||
}
|
||||
}
|
||||
|
||||
// 保存到 PlayerData.json
|
||||
if (PlayerDataManager.Instance != null)
|
||||
{
|
||||
PlayerDataManager.Instance.SaveFormation(characterIds, cells);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("PlayerDataManager.Instance 未找到,无法保存阵型");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据 Prefab 获取 characterId
|
||||
/// </summary>
|
||||
private string GetCharacterId(GameObject prefab)
|
||||
{
|
||||
if (prefab == null) return "";
|
||||
|
||||
// 查找对应的 CharacterData
|
||||
var allData = Resources.LoadAll<CharacterData>("Data");
|
||||
foreach (var data in allData)
|
||||
{
|
||||
if (data.unitPrefab == prefab)
|
||||
{
|
||||
return data.characterId;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private void SaveFormation()
|
||||
|
||||
@@ -195,16 +195,43 @@ public class HeroCardUI : MonoBehaviour
|
||||
var navAgent = heroUnit.GetComponent<UnityEngine.AI.NavMeshAgent>();
|
||||
if (navAgent != null)
|
||||
{
|
||||
navAgent.enabled = true; // 确保启用
|
||||
if (!navAgent.isOnNavMesh)
|
||||
{
|
||||
navAgent.enabled = false;
|
||||
navAgent.enabled = true;
|
||||
}
|
||||
navAgent.ResetPath(); // 清空旧路径
|
||||
}
|
||||
|
||||
// 重置 UnitBase 状态(关键修复:清空目标让单位重新寻敌)
|
||||
UnitBase unitBase = heroUnit.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.enabled = true; // 确保脚本启用
|
||||
unitBase.target = null; // 清空目标
|
||||
unitBase.ResetAnchorPosition(); // 重置锚点位置到复活位置(修复一直尝试返回旧锚点的问题)
|
||||
}
|
||||
|
||||
// 重置 Animator
|
||||
Animator animator = heroUnit.GetComponent<Animator>();
|
||||
if (animator != null)
|
||||
{
|
||||
animator.enabled = true;
|
||||
animator.Rebind(); // 重置动画状态
|
||||
animator.Update(0f);
|
||||
}
|
||||
|
||||
// 使用WorldHealthBar的Revive方法(会重置isDead并恢复生命)
|
||||
heroHealthBar.Revive(heroHealthBar.maxHealth);
|
||||
|
||||
// 重新显示血条(修复复活后没有血条的问题)
|
||||
Transform barTransform = heroHealthBar.transform.Find("WorldHealthBar");
|
||||
if (barTransform != null)
|
||||
{
|
||||
barTransform.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// 重置UI状态
|
||||
isDead = false;
|
||||
if (deathPanel != null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
[System.Serializable]
|
||||
public class PlayerOwnedCharacterJson
|
||||
@@ -9,12 +10,20 @@ public class PlayerOwnedCharacterJson
|
||||
public int starLevel = 0;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SavedFormationData
|
||||
{
|
||||
public string[] characterIds = new string[0];
|
||||
public int[] cellIndices = new int[0];
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class PlayerSaveJson
|
||||
{
|
||||
public string playerId = "local_player";
|
||||
public PlayerOwnedCharacterJson[] unlockedCharacters = new PlayerOwnedCharacterJson[0];
|
||||
public string[] currentDeck = new string[0];
|
||||
public SavedFormationData savedFormation = new SavedFormationData();
|
||||
}
|
||||
|
||||
public class PlayerDataManager : MonoBehaviour
|
||||
@@ -103,4 +112,65 @@ public class PlayerDataManager : MonoBehaviour
|
||||
var character = GetCharacterData(characterId);
|
||||
if (character != null) character.level++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存阵型到 PlayerData.json
|
||||
/// </summary>
|
||||
public void SaveFormation(string[] characterIds, int[] cellIndices)
|
||||
{
|
||||
string path = Application.dataPath + "/Resources/PlayerData.json";
|
||||
|
||||
try
|
||||
{
|
||||
// 读取现有数据
|
||||
string json = File.ReadAllText(path);
|
||||
var saveData = JsonUtility.FromJson<PlayerSaveJson>(json);
|
||||
|
||||
// 更新阵型数据
|
||||
saveData.savedFormation = new SavedFormationData
|
||||
{
|
||||
characterIds = characterIds,
|
||||
cellIndices = cellIndices
|
||||
};
|
||||
|
||||
// 写回文件
|
||||
string updatedJson = JsonUtility.ToJson(saveData, true);
|
||||
File.WriteAllText(path, updatedJson);
|
||||
|
||||
Debug.Log($"<color=green>✅ 阵型已保存到 PlayerData.json</color>");
|
||||
Debug.Log($"保存了 {characterIds.Length} 个英雄的阵型数据");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"保存阵型失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 PlayerData.json 加载阵型
|
||||
/// </summary>
|
||||
public SavedFormationData LoadFormation()
|
||||
{
|
||||
TextAsset json = localPlayerJson != null
|
||||
? localPlayerJson
|
||||
: Resources.Load<TextAsset>("PlayerData");
|
||||
|
||||
if (json != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var save = JsonUtility.FromJson<PlayerSaveJson>(json.text);
|
||||
if (save != null && save.savedFormation != null)
|
||||
{
|
||||
return save.savedFormation;
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError("加载阵型失败:" + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return new SavedFormationData();
|
||||
}
|
||||
}
|
||||
@@ -276,6 +276,7 @@ public class UnitBase : MonoBehaviour
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度(修复攻击后动画变慢的问题)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,11 +402,24 @@ public class UnitBase : MonoBehaviour
|
||||
return Vector3.Distance(current, anchor) <= anchorArrivalDistance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置锚点位置到当前位置(用于复活等场景)
|
||||
/// </summary>
|
||||
public void ResetAnchorPosition()
|
||||
{
|
||||
anchorPosition = transform.position;
|
||||
anchorInitialized = true;
|
||||
}
|
||||
|
||||
private void ReturnToAnchor()
|
||||
{
|
||||
if (navAgent == null || !anchorInitialized)
|
||||
{
|
||||
if (!summonerMode) animator.SetInteger("speed", 0);
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -416,7 +430,11 @@ public class UnitBase : MonoBehaviour
|
||||
|
||||
if (!navAgent.isOnNavMesh)
|
||||
{
|
||||
if (!summonerMode) animator.SetInteger("speed", 0);
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -426,7 +444,11 @@ public class UnitBase : MonoBehaviour
|
||||
navAgent.ResetPath();
|
||||
transform.position = new Vector3(anchorPosition.x, transform.position.y, anchorPosition.z);
|
||||
navAgent.nextPosition = transform.position;
|
||||
if (!summonerMode) animator.SetInteger("speed", 0);
|
||||
if (!summonerMode)
|
||||
{
|
||||
animator.SetInteger("speed", 0);
|
||||
animator.speed = 1f; // 重置动画播放速度
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -437,6 +459,7 @@ public class UnitBase : MonoBehaviour
|
||||
nextPathUpdateTime = Time.time + PathUpdateInterval;
|
||||
}
|
||||
animator.SetInteger("speed", navAgent.velocity.sqrMagnitude > 0.01f ? 1 : 0);
|
||||
animator.speed = 1f; // 确保移动时动画速度正常
|
||||
}
|
||||
|
||||
//目标决策:只寻找 detectionRange 内的敌方战斗单位;范围内没有敌人时原地待机或回到锚点。
|
||||
|
||||
@@ -85,6 +85,14 @@ public class WaveSpawner : MonoBehaviour
|
||||
Vector3 spawnPos = transform.position + wave.spawnPositions[i];
|
||||
GameObject enemy = Instantiate(wave.enemyPrefabs[i], spawnPos, Quaternion.identity);
|
||||
enemy.tag = "Enemy";
|
||||
|
||||
// 增大敌人的寻敌距离
|
||||
UnitBase unitBase = enemy.GetComponent<UnitBase>();
|
||||
if (unitBase != null)
|
||||
{
|
||||
unitBase.detectionRange = 100f; // 从默认30增加到100
|
||||
}
|
||||
|
||||
activeEnemies.Add(enemy);
|
||||
|
||||
Debug.Log($"生成敌人:{enemy.name} 位置={spawnPos}");
|
||||
|
||||
Reference in new issue
Block a user