编队系统重置 选角页面基本完成 等待存入playerprefs

This commit is contained in:
FloatGaming
2025-12-07 12:04:21 +08:00
parent 941b294fce
commit c0a822b958
134 changed files with 14796 additions and 198 deletions
@@ -2,6 +2,7 @@ using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections.Generic;
using System.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif
@@ -18,8 +19,17 @@ public class teamUIController : MonoBehaviour
[Tooltip("IDs for the 5 ally slots (top to bottom). These are used by PopulateAllySOsFromIds to resolve SOs into currentAllySOs.")]
public List<int> allySlotIds = new List<int> { 0, 0, 0, 0, 0 };
// --- 新增:敌人队列槽 ID 列表(按出场顺序) ---
[Header("Runtime enemy configuration")]
[Tooltip("IDs for enemies to appear in sequence. All enemies share a single GameObject and will be initialized from these SOs in order.")]
public List<int> enemySlotIds = new List<int>();
// --- 新增:解析后的当前五个 SO 引用(按顺序) ---
private TeamCharacterDataInfo[] currentAllySOs = new TeamCharacterDataInfo[5];
// 新增:解析后的当前敌人 SO 列表(按出场顺序)
private EnemyData_SO[] currentEnemySOs = new EnemyData_SO[0];
// 新增:仅包含已解析到的、有效的敌人 SO(不包含 id==0 或未找到的项)
private EnemyData_SO[] recognizedEnemySOs = new EnemyData_SO[0];
// previous active flags for detecting external changes
private bool[] prevAllyActive = new bool[5];
@@ -33,6 +43,13 @@ public class teamUIController : MonoBehaviour
[Tooltip("Runtime: Resources subfolder path (no 'Resources/' prefix). Example: so/ally")]
public string runtimeResourcesFolderPath = "so/ally";
// 新增:敌人 SO 路径(Editor / Runtime
[Tooltip("Editor-only: project path or absolute disk path to the folder that contains enemy SOs. Example: Assets/Resources/so/enemies")]
public string editorEnemySOFolderPath = "Assets/Resources/so/enemies";
[Tooltip("Runtime: Resources subfolder path (no 'Resources/' prefix) for enemy SOs. Example: so/enemies")]
public string runtimeEnemyResourcesFolderPath = "so/enemies";
// Optional per-ally object to toggle together with isAllyX_active. If null falls back to objectFather_allyXX.
[Header("Ally runtime objects (optional)")]
public GameObject ally01_object;
@@ -263,7 +280,7 @@ public class teamUIController : MonoBehaviour
if (runtimeDiscovered.Count == 0)
{
var arrAll = Resources.LoadAll("");
if (arrAll != null && arrAll.Length > 0)
if (arrAll != null && arr.Length > 0)
{
runtimeDiscovered.AddRange(arrAll);
Debug.LogWarning($"[teamUIController] (Runtime) Resources.LoadAll returned 0 in '{resourcesPath}', fell back to loading all ScriptableObjects ({arrAll.Length})");
@@ -276,7 +293,7 @@ public class teamUIController : MonoBehaviour
{
Debug.LogWarning($"[teamUIController] (Runtime) Resources.LoadAll failed for '{resourcesPath}': {ex.Message}");
var arrAll = Resources.LoadAll("");
if (arrAll != null && arrAll.Length > 0)
if (arrAll != null && arr.Length > 0)
runtimeDiscovered.AddRange(arrAll);
}
}
@@ -446,27 +463,152 @@ public class teamUIController : MonoBehaviour
#endif
}
// Resolve various forms of selectedProjectFolderPath into a Resources.Load relative path (no 'Resources/' prefix, no extension)
private string ResolveResourcesRelativePath(string selectedPath)
// Populate enemy SOs from enemySlotIds using editor/runtime paths similar to allies
public void PopulateEnemySOsFromIds()
{
if (string.IsNullOrEmpty(selectedPath)) return string.Empty;
string p = selectedPath.Replace("\\", "/");
// If user provided a path starting with "Assets/Resources/", strip to get relative
int idx = p.IndexOf("Assets/Resources/");
if (idx >= 0)
if (enemySlotIds == null || enemySlotIds.Count == 0)
{
return p.Substring(idx + "Assets/Resources/".Length).Trim('/');
currentEnemySOs = new EnemyData_SO[0];
// update recognized list and UI
FilterRecognizedEnemies();
UpdateEnemyListText();
return;
}
// If user provided an absolute path that contains Application.dataPath and Resources
string appData = Application.dataPath.Replace("\\", "/");
idx = p.IndexOf(appData + "/Resources/");
if (idx >= 0)
#if UNITY_EDITOR
string folderToUse = !string.IsNullOrEmpty(editorEnemySOFolderPath) ? editorEnemySOFolderPath : selectedProjectFolderPath;
string projectRelative = null;
if (!string.IsNullOrEmpty(folderToUse))
{
return p.Substring((appData + "/Resources/").Length).Trim('/');
string projectPath = folderToUse.Replace("\\", "/");
if (projectPath.StartsWith(Application.dataPath)) projectRelative = "Assets" + projectPath.Substring(Application.dataPath.Length);
else if (projectPath.StartsWith("Assets/")) projectRelative = projectPath;
else Debug.LogWarning("editorEnemySOFolderPath should be inside project Assets for editor search. Falling back to project-wide search.");
}
// If user already provided a Resources relative path (like "so/ally"), return it trimmed
if (p.StartsWith("Resources/")) p = p.Substring("Resources/".Length);
return p.Trim('/');
List<EnemyData_SO> results = new List<EnemyData_SO>();
List<Object> discovered = new List<Object>();
if (!string.IsNullOrEmpty(projectRelative))
{
string[] guids = AssetDatabase.FindAssets("t:EnemyData_SO", new[] { projectRelative });
foreach (var g in guids)
{
var path = AssetDatabase.GUIDToAssetPath(g);
var so = AssetDatabase.LoadAssetAtPath<EnemyData_SO>(path);
if (so != null) discovered.Add(so);
}
}
else
{
string[] guids = AssetDatabase.FindAssets("t:EnemyData_SO");
foreach (var g in guids)
{
var path = AssetDatabase.GUIDToAssetPath(g);
var so = AssetDatabase.LoadAssetAtPath<EnemyData_SO>(path);
if (so != null) discovered.Add(so);
}
}
// For each id in enemySlotIds try to resolve an EnemyData_SO; if id==0 or not found push null (skip)
foreach (var id in enemySlotIds)
{
if (id == 0) { results.Add(null); continue; }
EnemyData_SO found = null;
for (int j = 0; j < discovered.Count; j++)
{
var obj = discovered[j] as EnemyData_SO;
if (obj == null) continue;
string path = AssetDatabase.GetAssetPath(obj);
if (!string.IsNullOrEmpty(path) && path.Contains(id.ToString())) { found = obj; break; }
if (obj.enemyID == id) { found = obj; break; }
}
results.Add(found);
}
currentEnemySOs = results.ToArray();
#else
string resourcesPath = ResolveResourcesRelativePath(!string.IsNullOrEmpty(runtimeEnemyResourcesFolderPath) ? runtimeEnemyResourcesFolderPath : selectedProjectFolderPath);
List<Object> runtimeDiscovered = new List<Object>();
if (!string.IsNullOrEmpty(resourcesPath))
{
resourcesPath = resourcesPath.Trim('/');
try
{
var arr = Resources.LoadAll(resourcesPath);
if (arr != null && arr.Length > 0) runtimeDiscovered.AddRange(arr);
if (runtimeDiscovered.Count == 0)
{
var arrAll = Resources.LoadAll("");
if (arrAll != null && arrAll.Length > 0) runtimeDiscovered.AddRange(arrAll);
}
}
catch { var arrAll = Resources.LoadAll(""); if (arrAll != null && arrAll.Length > 0) runtimeDiscovered.AddRange(arrAll); }
}
else
{
var arr = Resources.LoadAll(""); if (arr != null && arr.Length > 0) runtimeDiscovered.AddRange(arr);
}
List<EnemyData_SO> results = new List<EnemyData_SO>();
foreach (var id in enemySlotIds)
{
if (id == 0) { results.Add(null); continue; }
EnemyData_SO found = null;
foreach (var o in runtimeDiscovered)
{
if (o == null) continue;
if (o is EnemyData_SO e)
{
if (!string.IsNullOrEmpty(e.name) && e.name.Contains(id.ToString())) { found = e; break; }
if (e.enemyID == id) { found = e; break; }
}
}
// final attempt: Resources.Load by path
if (found == null && !string.IsNullOrEmpty(resourcesPath))
{
try
{
var byId = Resources.Load<EnemyData_SO>($"{resourcesPath}/{id}");
if (byId != null) found = byId;
}
catch { }
}
results.Add(found);
}
currentEnemySOs = results.ToArray();
#endif
// build recognized list and update UI
FilterRecognizedEnemies();
UpdateEnemyListText();
}
// Build recognizedEnemySOs from currentEnemySOs by filtering out null entries (id==0 or unresolved)
private void FilterRecognizedEnemies()
{
var list = new List<EnemyData_SO>();
if (currentEnemySOs != null)
{
foreach (var so in currentEnemySOs)
{
if (so != null)
{
list.Add(so);
}
}
}
recognizedEnemySOs = list.ToArray();
// update enemyCounterMax to reflect actual number of recognized enemies
enemyCounterMax = recognizedEnemySOs != null ? recognizedEnemySOs.Length : 0;
// clamp current index
if (enemyCurrentCount < 0) enemyCurrentCount = 0;
if (enemyCurrentCount > enemyCounterMax) enemyCurrentCount = enemyCounterMax;
}
// 返回解析到的敌人 SO 列表(副本)
public EnemyData_SO[] GetCurrentEnemySOs()
{
return (EnemyData_SO[])currentEnemySOs.Clone();
}
// Debug helper to print key fields of a TeamCharacterDataInfo
@@ -502,6 +644,13 @@ public class teamUIController : MonoBehaviour
[Tooltip("当前总分")]
public TextMeshProUGUI currentTotalScore;
// new: runtime enemy instance and UI sync fields
private EnemyCombatant enemyCombatantInstance;
private Coroutine enemyFadeHealthCoroutine;
private Coroutine enemyFadeManaCoroutine;
private int prevEnemyHP = -1;
private int prevEnemyMana = -1;
[Header("Combo判定最低要求")]
public ComboJudgeType comboJudgeType = ComboJudgeType.Perfect;
@@ -696,16 +845,32 @@ public class teamUIController : MonoBehaviour
public Image currentEnemy_healthImage;
[Tooltip("虚血条")]
public Image currentEnemy_fadehealthImage;
[Tooltip("法力条")]
public Image currentEnemy_manaImage;
[Tooltip("虚法力条")]
public Image currentEnemy_fademanaImage;
[Tooltip("共计血条")]
public Image allEnemy_totalHealthImage;
[Tooltip("共计虚血条")]
public Image allEnemy_totalFadehealthImage;
[Tooltip("名字文本")]
public TextMeshProUGUI currentEnemy_nameText;
[Tooltip("当前生命值/最大生命值")]
public Text currentEnemy_nameText;
[Tooltip("类型文本")]
public Text currentEnemy_typeText;
[Tooltip("当前敌人生命值/最大生命值")]
public TextMeshProUGUI currentEnemy_healthRate;
[Tooltip("所有敌人生命值/最大生命值总计")]
public TextMeshProUGUI totalEnemy_healthRate;
[Tooltip("当前敌人法力值/最大法力值")]
public TextMeshProUGUI currentEnemy_manaRate;
[Tooltip("当前分数/轨道分数上限")]
public TextMeshProUGUI currentEnemy_current_scoreText; // rate : now score / max score
[Tooltip("角色唯一识别码")]
[Tooltip("敌人唯一识别码")]
[SerializeField] private int enemy_id;
[Tooltip("受击闪红")]
public Image currentEnemy_hurtRedImage;
[Tooltip("敌人排队")]
public TextMeshProUGUI enemyList_rateText;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
@@ -721,6 +886,17 @@ public class teamUIController : MonoBehaviour
// Ensure score text references are resolved so ScoreManager and AllyCombatant can write to them
ResolveScoreTextReferences();
// Initialize enemies list and spawn first enemy if any
PopulateEnemySOsFromIds();
// set enemyCounterMax based on recognized (resolved non-null) enemies so zeros/unresolved don't count
enemyCounterMax = recognizedEnemySOs != null ? recognizedEnemySOs.Length : 0;
enemyCurrentCount = 0;
InitializeEnemyInstance();
if (recognizedEnemySOs != null && recognizedEnemySOs.Length > 0)
{
SpawnNextEnemy();
}
}
// Update is called once per frame
@@ -736,6 +912,23 @@ public class teamUIController : MonoBehaviour
prevAllyActive[i] = current[i];
}
}
// Sync enemy UI with EnemyCombatant values
if (enemyCombatantInstance != null)
{
int hp = enemyCombatantInstance.currentHP;
int mana = enemyCombatantInstance.currentMana;
if (prevEnemyHP != hp)
{
UpdateEnemyHealthVisuals(prevEnemyHP, hp, true);
prevEnemyHP = hp;
}
if (prevEnemyMana != mana)
{
UpdateEnemyManaVisuals(prevEnemyMana, mana, true);
prevEnemyMana = mana;
}
}
}
private void FixedUpdate()
@@ -890,4 +1083,298 @@ public class teamUIController : MonoBehaviour
case 4: if (teammate05_characterImage != null) teammate05_characterImage.sprite = sprite; break;
}
}
// ------------------- Enemy spawn & UI sync helpers -------------------
private void InitializeEnemyInstance()
{
// Try to find an existing enemy object in scene
enemyCombatantInstance = FindFirstObjectByType<EnemyCombatant>();
if (enemyCombatantInstance == null)
{
var go = new GameObject("thisEnemy");
enemyCombatantInstance = go.AddComponent<EnemyCombatant>();
}
// attach listeners
if (enemyCombatantInstance != null)
{
enemyCombatantInstance.OnEnemyDied -= OnEnemyDiedHandler;
enemyCombatantInstance.OnEnemyRevived -= OnEnemyRevivedHandler;
enemyCombatantInstance.OnEnemyDied += OnEnemyDiedHandler;
enemyCombatantInstance.OnEnemyRevived += OnEnemyRevivedHandler;
// initialize previous tracked values
prevEnemyHP = enemyCombatantInstance.currentHP;
prevEnemyMana = enemyCombatantInstance.currentMana;
}
}
private void SpawnNextEnemy()
{
// handle case: no configured/recognized enemies -> show empty state but keep UI visible
if (recognizedEnemySOs == null || recognizedEnemySOs.Length == 0)
{
if (objectFather_enemy != null) objectFather_enemy.SetActive(true);
if (currentEnemy_nameText != null) currentEnemy_nameText.text = "(No Enemy)";
if (currentEnemy_characterImage != null) currentEnemy_characterImage.sprite = null;
if (currentEnemy_healthImage != null) currentEnemy_healthImage.fillAmount = 0f;
if (currentEnemy_fadehealthImage != null) currentEnemy_fadehealthImage.fillAmount = 0f;
if (currentEnemy_healthRate != null) currentEnemy_healthRate.text = "0/0";
if (currentEnemy_manaImage != null) currentEnemy_manaImage.fillAmount = 0f;
if (currentEnemy_fademanaImage != null) currentEnemy_fademanaImage.fillAmount = 0f;
if (enemyCounter != null) enemyCounter.text = "0/0";
if (currentEnemy_typeText != null) currentEnemy_typeText.text = "(普通)";
UpdateEnemyListText();
return;
}
if (enemyCurrentCount < 0) enemyCurrentCount = 0;
if (enemyCurrentCount >= recognizedEnemySOs.Length)
{
// All enemies processed: show empty/finished state but keep UI visible
if (objectFather_enemy != null) objectFather_enemy.SetActive(true);
if (currentEnemy_nameText != null) currentEnemy_nameText.text = "(All Defeated)";
if (currentEnemy_characterImage != null) currentEnemy_characterImage.sprite = null;
if (currentEnemy_healthImage != null) currentEnemy_healthImage.fillAmount = 0f;
if (currentEnemy_fadehealthImage != null) currentEnemy_fadehealthImage.fillAmount = 0f;
if (currentEnemy_healthRate != null) currentEnemy_healthRate.text = "0/0";
if (currentEnemy_manaImage != null) currentEnemy_manaImage.fillAmount = 0f;
if (currentEnemy_fademanaImage != null) currentEnemy_fademanaImage.fillAmount = 0f;
if (enemyCounter != null) enemyCounter.text = "0/" + enemyCounterMax.ToString();
if (currentEnemy_typeText != null) currentEnemy_typeText.text = "(普通)";
UpdateEnemyListText();
return;
}
var so = recognizedEnemySOs[enemyCurrentCount];
if (so == null)
{
Debug.LogWarning($"[teamUIController] SpawnNextEnemy: SO is null at index {enemyCurrentCount}");
// skip null slots (treated as empty) and advance
enemyCurrentCount++;
SpawnNextEnemy();
return;
}
InitializeEnemyInstance();
enemyCombatantInstance.InitializeFromSO(so);
// set UI visuals (name / sprites)
if (currentEnemy_nameText != null) currentEnemy_nameText.text = so.enemyName ?? so.name;
if (currentEnemy_characterImage != null)
{
var sprite = so.enemy_Profile != null ? so.enemy_Profile : so.enemy_Image;
if (sprite != null) currentEnemy_characterImage.sprite = sprite;
else currentEnemy_characterImage.sprite = null;
}
// set type text: show for Simple/Elite/Boss/Legend
if (currentEnemy_typeText != null)
{
switch (so.enemyType)
{
case EnemyData_SO.EnemyType.Elite:
currentEnemy_typeText.text = "(精英)";
break;
case EnemyData_SO.EnemyType.Boss:
currentEnemy_typeText.text = "(首领)";
break;
case EnemyData_SO.EnemyType.Legend:
currentEnemy_typeText.text = "(史诗)";
break;
default:
currentEnemy_typeText.text = "(普通)";
break;
}
}
// ensure UI parent is visible
if (objectFather_enemy != null) objectFather_enemy.SetActive(true);
// reset previous values so Update picks up initial state
prevEnemyHP = enemyCombatantInstance.currentHP;
prevEnemyMana = enemyCombatantInstance.currentMana;
UpdateEnemyUIImmediate();
// update enemy counter text
if (enemyCounter != null)
{
enemyCounter.text = $"{Mathf.Clamp(enemyCurrentCount+1,1,999)}/{enemyCounterMax}";
}
// refresh the enemy list display
UpdateEnemyListText();
}
// Build a readable representation of the enemy queue and write to enemyList_rateText
private void UpdateEnemyListText()
{
if (enemyList_rateText == null) return;
int total = recognizedEnemySOs != null ? recognizedEnemySOs.Length : 0;
int displayIndex = 0;
if (total == 0)
displayIndex = 0;
else
displayIndex = Mathf.Clamp(enemyCurrentCount + 1, 1, total);
// show as "current/total" (e.g. 1/3). When no enemies, show 0/0
enemyList_rateText.text = total == 0 ? "0/0" : $"{displayIndex}/{total}";
}
private void OnEnemyDiedHandler(EnemyCombatant e)
{
// advance to next enemy after death
enemyCurrentCount++;
SpawnNextEnemy();
}
private void OnEnemyRevivedHandler(EnemyCombatant e)
{
// refresh UI
UpdateEnemyUIImmediate();
}
private void UpdateEnemyUIImmediate()
{
if (enemyCombatantInstance == null) return;
// health
if (currentEnemy_healthImage != null)
currentEnemy_healthImage.fillAmount = enemyCombatantInstance.maxHP > 0 ? (float)enemyCombatantInstance.currentHP / enemyCombatantInstance.maxHP : 0f;
if (currentEnemy_fadehealthImage != null)
currentEnemy_fadehealthImage.fillAmount = currentEnemy_healthImage != null ? currentEnemy_healthImage.fillAmount : (enemyCombatantInstance.maxHP > 0 ? (float)enemyCombatantInstance.currentHP / enemyCombatantInstance.maxHP : 0f);
if (currentEnemy_healthRate != null)
currentEnemy_healthRate.text = $"{enemyCombatantInstance.currentHP}/{enemyCombatantInstance.maxHP}";
// mana visuals (new)
if (currentEnemy_manaImage != null)
currentEnemy_manaImage.fillAmount = enemyCombatantInstance.maxMana > 0 ? (float)enemyCombatantInstance.currentMana / enemyCombatantInstance.maxMana : 0f;
if (currentEnemy_fademanaImage != null)
currentEnemy_fademanaImage.fillAmount = currentEnemy_manaImage != null ? currentEnemy_manaImage.fillAmount : (enemyCombatantInstance.maxMana > 0 ? (float)enemyCombatantInstance.currentMana / enemyCombatantInstance.maxMana : 0f);
if (currentEnemy_manaRate != null)
currentEnemy_manaRate.text = enemyCombatantInstance.maxMana > 0 ? $"{enemyCombatantInstance.currentMana}/{enemyCombatantInstance.maxMana}" : "0/0";
if (allEnemy_totalHealthImage != null)
{
// optional: aggregate total health across remaining enemies
int totalCur = 0, totalMax = 0;
if (currentEnemySOs != null)
{
for (int i = enemyCurrentCount; i < currentEnemySOs.Length; i++)
{
var so = currentEnemySOs[i];
if (so == null) continue;
totalMax += Mathf.Max(1, so.enemy_maxHP);
// use max for not-yet-spawned enemies
if (i == enemyCurrentCount) totalCur += enemyCombatantInstance.currentHP; else totalCur += so.enemy_maxHP;
}
}
if (totalMax > 0)
{
allEnemy_totalHealthImage.fillAmount = (float)totalCur / totalMax;
if (totalEnemy_healthRate != null) totalEnemy_healthRate.text = $"{totalCur}/{totalMax}";
}
}
}
private void UpdateEnemyHealthVisuals(int oldHP, int newHP, bool animateFade)
{
if (enemyCombatantInstance == null) return;
if (currentEnemy_healthImage != null)
{
float newFill = enemyCombatantInstance.maxHP > 0 ? (float)newHP / enemyCombatantInstance.maxHP : 0f;
currentEnemy_healthImage.fillAmount = Mathf.MoveTowards(currentEnemy_healthImage.fillAmount, newFill, 1f);
}
if (currentEnemy_healthRate != null)
currentEnemy_healthRate.text = $"{newHP}/{enemyCombatantInstance.maxHP}";
if (enemyFadeHealthCoroutine != null) StopCoroutine(enemyFadeHealthCoroutine);
if (currentEnemy_fadehealthImage != null)
{
float target = currentEnemy_healthImage != null ? currentEnemy_healthImage.fillAmount : (enemyCombatantInstance.maxHP > 0 ? (float)newHP / enemyCombatantInstance.maxHP : 0f);
if (animateFade && Application.isPlaying)
enemyFadeHealthCoroutine = StartCoroutine(EnemyFadeHealthCoroutine(target));
else
currentEnemy_fadehealthImage.fillAmount = target;
}
// hurt flash if hp decreased
if (oldHP >= 0 && newHP < oldHP && currentEnemy_hurtRedImage != null && Application.isPlaying)
{
StopCoroutine("EnemyHurtFlash");
StartCoroutine(EnemyHurtFlash());
}
}
private void UpdateEnemyManaVisuals(int oldMana, int newMana, bool animateFade)
{
if (enemyCombatantInstance == null) return;
if (currentEnemy_manaRate != null)
currentEnemy_manaRate.text = enemyCombatantInstance.maxMana > 0 ? $"{newMana}/{enemyCombatantInstance.maxMana}" : "0/0";
if (enemyFadeManaCoroutine != null) StopCoroutine(enemyFadeManaCoroutine);
if (currentEnemy_fademanaImage != null)
{
float target = currentEnemy_manaImage != null ? currentEnemy_manaImage.fillAmount : (enemyCombatantInstance.maxMana > 0 ? (float)newMana / enemyCombatantInstance.maxMana : 0f);
if (animateFade && Application.isPlaying)
enemyFadeManaCoroutine = StartCoroutine(EnemyFadeManaCoroutine(target));
else if (currentEnemy_fademanaImage != null)
currentEnemy_fademanaImage.fillAmount = target;
}
// update main mana bar immediately
if (currentEnemy_manaImage != null)
{
currentEnemy_manaImage.fillAmount = enemyCombatantInstance.maxMana > 0 ? (float)newMana / enemyCombatantInstance.maxMana : 0f;
}
}
private IEnumerator EnemyFadeHealthCoroutine(float targetFill)
{
if (currentEnemy_fadehealthImage == null) yield break;
float start = currentEnemy_fadehealthImage.fillAmount;
float duration = 0.6f;
float t = 0f;
while (t < duration)
{
t += Time.deltaTime;
currentEnemy_fadehealthImage.fillAmount = Mathf.Lerp(start, targetFill, t / duration);
yield return null;
}
currentEnemy_fadehealthImage.fillAmount = targetFill;
}
private IEnumerator EnemyFadeManaCoroutine(float targetFill)
{
if (currentEnemy_fademanaImage == null) yield break;
float start = currentEnemy_fademanaImage.fillAmount;
float duration = 0.4f;
float t = 0f;
while (t < duration)
{
t += Time.deltaTime;
currentEnemy_fademanaImage.fillAmount = Mathf.Lerp(start, targetFill, t / duration);
yield return null;
}
currentEnemy_fademanaImage.fillAmount = targetFill;
}
private IEnumerator EnemyHurtFlash()
{
if (currentEnemy_hurtRedImage == null) yield break;
Color c = currentEnemy_hurtRedImage.color;
c.a = 1f;
currentEnemy_hurtRedImage.color = c;
yield return new WaitForSeconds(0.2f);
float dur = 0.4f;
float t = 0f;
while (t < dur)
{
t += Time.deltaTime;
c.a = Mathf.Lerp(1f, 0f, t / dur);
currentEnemy_hurtRedImage.color = c;
yield return null;
}
c.a = 0f;
currentEnemy_hurtRedImage.color = c;
}
}