diff --git a/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs b/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
index 5661a263a8..4938674568 100644
--- a/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
+++ b/Assets/PerfectWorld/Scripts/Addressable/AddressableManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
@@ -43,32 +44,131 @@ namespace BrewMonster.Scripts
}
///
- /// Load a text asset asynchronously. The address should look like this: "elements.data"
+ /// Load a text asset asynchronously.
+ /// NOTE: The key must match the Addressables "Address" (or another valid key like a label/GUID).
///
///
///
///
public async Task LoadTextAssetAsync(string assetPath)
{
- if (_loadedAssets.ContainsKey(assetPath))
+ if (_loadedTextAssets.ContainsKey(assetPath))
{
return _loadedTextAssets[assetPath].Result;
}
try
{
- var handle = Addressables.LoadAssetAsync(assetPath);
- await handle.Task;
- _loadedTextAssets[assetPath] = handle;
- return handle.Result;
+ // First, try the key exactly as provided. If it doesn't exist in the catalog,
+ // fall back to common project conventions (e.g. full Asset path).
+ foreach (var key in GetCandidateKeys(assetPath))
+ {
+ var locationsHandle = Addressables.LoadResourceLocationsAsync(key, typeof(TextAsset));
+ await locationsHandle.Task;
+
+ if (locationsHandle.Status != AsyncOperationStatus.Succeeded || locationsHandle.Result == null || locationsHandle.Result.Count == 0)
+ {
+ Addressables.Release(locationsHandle);
+ continue;
+ }
+
+ Addressables.Release(locationsHandle);
+
+ var handle = Addressables.LoadAssetAsync(key);
+ await handle.Task;
+
+ if (handle.Status == AsyncOperationStatus.Succeeded && handle.Result != null)
+ {
+ _loadedTextAssets[assetPath] = handle;
+ return handle.Result;
+ }
+
+ // If load failed, release and try next candidate.
+ if (handle.IsValid())
+ {
+ Addressables.Release(handle);
+ }
+ }
+
+ BMLogger.LogError($"AddressableManager: No Location found for TextAsset key='{assetPath}'. " +
+ $"Tried: {string.Join(", ", GetCandidateKeys(assetPath).Select(k => $"'{k}'"))}");
+ LogSimilarKeys(assetPath);
+ return null;
}
catch (Exception e)
{
- BMLogger.LogError(e.StackTrace);
+ BMLogger.LogError($"AddressableManager: Failed to load TextAsset '{assetPath}': {e}");
return null;
}
}
+ private static IEnumerable GetCandidateKeys(string assetPath)
+ {
+ if (string.IsNullOrWhiteSpace(assetPath))
+ {
+ yield break;
+ }
+
+ // Exact key (what caller asked for)
+ yield return assetPath;
+
+ // Common fallback used by this repo's Addressables settings: full asset path address.
+ // Example in `Assets/AddressableAssetsData/AssetGroups/configuration.asset`:
+ // m_Address: Assets/Addressable/elements.txt
+ if (!assetPath.Contains("/") && !assetPath.Contains("\\"))
+ {
+ yield return $"Assets/Addressable/{assetPath}";
+ }
+ }
+
+ private static void LogSimilarKeys(string needle)
+ {
+ // Helpful diagnostics in dev builds: show a few keys containing the substring.
+ try
+ {
+ var lower = needle?.ToLowerInvariant();
+ if (string.IsNullOrEmpty(lower))
+ {
+ return;
+ }
+
+ const int max = 20;
+ var matches = new List(max);
+
+ foreach (var locator in Addressables.ResourceLocators)
+ {
+ foreach (var keyObj in locator.Keys)
+ {
+ if (keyObj is not string keyStr)
+ {
+ continue;
+ }
+
+ if (!keyStr.ToLowerInvariant().Contains(lower))
+ {
+ continue;
+ }
+
+ matches.Add(keyStr);
+ if (matches.Count >= max)
+ {
+ goto Done;
+ }
+ }
+ }
+
+ Done:
+ if (matches.Count > 0)
+ {
+ BMLogger.LogWarning($"AddressableManager: Similar Addressables keys for '{needle}': {string.Join(", ", matches)}");
+ }
+ }
+ catch
+ {
+ // ignore diagnostics failures
+ }
+ }
+
///
/// Load an asset asynchronously. The address should look like this: "models/npcs/npc/魅灵首领/魅灵首领/魅灵首领.prefab"
///
diff --git a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
index 5e7e12c927..085a7974ea 100644
--- a/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
+++ b/Assets/PerfectWorld/Scripts/Common/DataProcess/elementdataman.cs
@@ -321,7 +321,15 @@ namespace ModelRenderer.Scripts.GameData
// if (!File.Exists(pathname)) return -1;
- var dataFile = await AddressableManager.Instance.LoadTextAssetAsync("elements.data");
+ // Addressables key must match the configured "Address". This repo currently uses full asset paths
+ // (see `Assets/AddressableAssetsData/AssetGroups/configuration.asset`).
+ // `AddressableManager.LoadTextAssetAsync` also has fallbacks, so "elements.txt" will work too.
+ var dataFile = await AddressableManager.Instance.LoadTextAssetAsync("Assets/Addressable/elements.txt");
+ if (dataFile == null)
+ {
+ BMLogger.LogError("ElementDataMan: Failed to load Addressable TextAsset for elements data.");
+ return -1;
+ }
using (var file = new MemoryStream(dataFile.bytes))
{