You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Addressables加载Sprite返回None问题求助

问题:Addressables加载Sprite到Weather Struct后图标始终为Null

我尝试通过代码将Sprite加载到自定义的Weather struct中,但运行项目时weatherList中所有条目均报错“Failed to load weather icon for XXX”。已确认Addressables Group配置正确(修改图标名称会触发键错误),但weatherList中的Weather Icon始终显示为None(Sprite)。

WeatherManager代码实现

public class WeatherManager : MonoBehaviour
{
    #region Variables

    private List<Weather> weatherList = new List<Weather>();

    #endregion

    ...

    public void Start()
    {
        InitialiseWeatherList();
    }

    ...

    private void InitialiseWeatherList()
    {
        if(weatherList.Count == 0)
        {
            weatherList.Add(new Weather(WeatherType.Cloudy, "Cloudy", "Weather_Cloudy"));
            weatherList.Add(new Weather(WeatherType.PartlyCloudy, "Partly Cloudy", "Weather_PartlyCloudy"));
            weatherList.Add(new Weather(WeatherType.Rainy, "Rainy", "Weather_Rainy"));
            weatherList.Add(new Weather(WeatherType.Snowing, "Snowing", "Weather_Snowing"));
            weatherList.Add(new Weather(WeatherType.Sunny, "Sunny", "Weather_Sunny"));
            weatherList.Add(new Weather(WeatherType.Thunderstorm, "Thunderstorm", "Weather_Thunderstorm"));
            
            StartCoroutine(LoadWeatherIcons());
        }
    }

    private IEnumerator LoadWeatherIcons()
    {
        foreach(Weather weather in weatherList)
        {
            yield return weather.LoadWeatherIcon();
            weather.SetWeatherIcon(weather.GetWeatherIcon());
        }

        foreach (Weather weather in weatherList)
        {
            if(weather.GetWeatherIcon() == null)
            {
                Debug.LogError($"Failed to load weather icon for {weather.GetWeatherName()}");
            }
        }
    }
}

Weather Struct定义

public struct Weather
{
    private WeatherType weatherType;
    private AssetReference weatherIconReference;
    private Sprite weatherIcon;
    private string weatherName;
    private string weatherIconName;

    public Weather(WeatherType weatherType, string weatherName, string weatherIconName)
    {
        this.weatherType = weatherType;
        this.weatherIconReference = null;
        this.weatherIcon = null;
        this.weatherName = weatherName;
        this.weatherIconName = weatherIconName;
    }

    public WeatherType GetWeatherType() { return weatherType; }

    public Sprite GetWeatherIcon() { return weatherIcon; }

    public string GetWeatherName() { return weatherName; }

    public string GetWeatherIconName() { return weatherIconName; }

    public void SetWeatherIcon(Sprite weatherIcon)
    {
        if(this.weatherIcon == null)
        {
            this.weatherIcon = weatherIcon;
        }
        else
        {
            Debug.LogError("Could not reassign weather icon.");
        }
    }

    public IEnumerator LoadWeatherIcon()
    {
        AsyncOperationHandle<Sprite> loadOperation = Addressables.LoadAssetAsync<Sprite>(weatherIconName);
        yield return loadOperation;

        if(loadOperation.Status == AsyncOperationStatus.Succeeded)
        {
            weatherIcon = loadOperation.Result;
        }
        else
        {
            Debug.LogError($"Failed to load weather icon for {weatherName}");
        }
    }
}

核心问题

Weather是值类型(struct),在LoadWeatherIcons的foreach循环中,Weather weather in weatherList会创建原结构体的副本。调用LoadWeatherIcon()和SetWeatherIcon()时,所有修改都只作用于这个副本,而非列表中的原结构体实例,导致原列表里的weatherIcon始终为null。

解决方案

方案1:将Weather从struct改为class(推荐)

将Weather改为引用类型(class),这样foreach循环中操作的是原实例的引用,修改会直接同步到列表中的元素:

public class Weather // 替换struct为class
{
    private WeatherType weatherType;
    private AssetReference weatherIconReference;
    private Sprite weatherIcon;
    private string weatherName;
    private string weatherIconName;

    public Weather(WeatherType weatherType, string weatherName, string weatherIconName)
    {
        this.weatherType = weatherType;
        this.weatherIconReference = null;
        this.weatherIcon = null;
        this.weatherName = weatherName;
        this.weatherIconName = weatherIconName;
    }

    // 其余方法保持不变...
}

同时可以去掉LoadWeatherIcons中多余的weather.SetWeatherIcon(weather.GetWeatherIcon())行,因为LoadWeatherIcon()已经直接给实例的weatherIcon赋值了。

方案2:保持struct,通过索引修改原元素

如果必须使用struct,遍历列表时通过索引访问元素,修改后重新赋值回列表:

private IEnumerator LoadWeatherIcons()
{
    for (int i = 0; i < weatherList.Count; i++)
    {
        Weather weather = weatherList[i];
        yield return weather.LoadWeatherIcon();
        // 将修改后的副本重新赋值回列表
        weatherList[i] = weather;
    }

    foreach (Weather weather in weatherList)
    {
        if(weather.GetWeatherIcon() == null)
        {
            Debug.LogError($"Failed to load weather icon for {weather.GetWeatherName()}");
        }
    }
}

同样可以去掉多余的SetWeatherIcon调用,避免无效操作。


内容的提问来源于stack exchange,提问作者JamieRhys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:17:26