Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Addressable scene doesn't load on mobile, but does in editor.

Discussion in 'Addressables' started by MichaelTGD, Dec 17, 2019.

  1. MichaelTGD

    MichaelTGD

    Joined:
    Oct 24, 2019
    Posts:
    16
    I'm fairly new to Unity and C#, but I've been getting my head around it fairly well, until I came across Addressables. It seems like it should be simple, but I can never get it to work properly. I've come very close now, but I'm stuck, and can't figure out what I'm doing wrong at this point.

    And sorry for the long post, but I've been stuck for awhile on this, and I just can't figure out where my problem is, so I'm throwing it all out there.

    What I'm using:

    Unity 2019.3.0f1 & Addressables 1.4.0


    Here's what I'm trying to do:
    • I'm making an app for mobile devices, in which the user will select a scene (named after a city) from the main menu. The scenes will be stored remotely on a server, and downloaded and loaded when the user selects one. The scenes are selected by buttons, instantiated based on data from a CSV, which gives the name to label the button, and the addressable name for the scene.

    Here's HOW I'm doing it:

    • My game scene is set as addressable (as "ZmeerAddressable"). It's set into it's own addressable group with RemoteBuildPath and RemoteLoadPath. I build it with the default build script. When it's complete, I upload it from the ServerData folder to my remote server space. The files have full read permission.

    • At this point, I open the Main Menu scene and run it in the editor.Main Menu starts with a button, which when clicked grabs a CSV file, and makes the buttons. This works as intended. When I click the button labeled "Zoetmeer", it does load the correct "ZmeerAddressable" from the network (albeit with pink graphics and shader problems.)

    • Then I build the game, with only the Main Menu scene added to the build options (on a PC). The build succeeds, and I transfer it to my MacBook, open it in Xcode, build and install on my iPhone. The game launches, the csv file is read and buttons are made. But when I press the "Zoetermeer" button, nothing seems to happen.


    Here is the relevant debug log from Xcode at the moment the button is pressed to load the Addressable scene:


    Code (CSharp):
    1. Exception encountered in operation UnityEngine.ResourceManagement.ResourceManager+CompletedOperation`1[UnityEngine.ResourceManagement.ResourceProviders.SceneInstance], result='', status='Failed': Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=ZmeerAddressable\
    2.         \
    3.         UnityEngine.AddressableAssets.AddressablesImpl:LogException(AsyncOperationHandle, Exception)\
    4.         System.Action`2:Invoke(T1, T2)\
    5.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:set_OperationException(Exception)\
    6.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String)\
    7.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()\
    8.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Start(ResourceManager, AsyncOperationHandle, DelegateList`1)\
    9.         UnityEngine.ResourceManagement.ResourceManager:StartOperation(AsyncOperationBase`1, AsyncOperationHandle)\
    10.         UnityEngine.AddressableAssets.AddressablesImpl:LoadSceneAsync(Object, LoadSceneMode, Boolean, Int32)\
    11.         System.Func`2:Invoke(T)\
    12.         UnityEngine.ResourceManagement.ChainOperationTypelessDepedency`1:Execute()\
    13.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeExecute()\
    14.         System.Action`1:Invoke(T)\
    15.         DelegateList`1:Invoke(T)\
    16.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()\
    17.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String)\
    18.         UnityEngine.AddressableAssets.Initialization.<>c__DisplayClass13_0:<LoadContentCatalogInternal>b__0(AsyncOperationHandle`1)\
    19.         System.Action`1:Invoke(T)\
    20.         DelegateList`1:Invoke(T)\
    21.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()\
    22.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:Complete(TObject, Boolean, String)\
    23.         System.Action`1:Invoke(T)\
    24.         DelegateList`1:Invoke(T)\
    25.         UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1:InvokeCompletionEvent()\
    26.         UnityEngine.ResourceManagement.ResourceManager:ExecuteDeferredCallbacks()\
    27.         UnityEngine.ResourceManagement.ResourceManager:Update(Single)\
    28.         System.Action`1:Invoke(T)\
    29.          \
    30.         (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)\

    And then it just sits there. The app continues to respond to input, I can scroll the ScrollRect that the buttons are in, I can press the buttons more and the get the error again. But it never is able to load.

    I'm not sure why it calls it an "InvalidKeyException", when the name is correct, and it works in the editor. Am I not understanding what the "key" is that is required for
    Addressables.LoadSceneAsync( object key);
    ?

    And here is my script LevelLoader.cs in the Main Menu scene:

    Code (CSharp):
    1.  
    2.       using System.Collections;
    3.         using System.Collections.Generic;
    4.         using UnityEngine;
    5.         using UnityEngine.SceneManagement;
    6.         using UnityEngine.UI;
    7.         using UnityEngine.Networking;
    8.         using UnityEngine.AddressableAssets;
    9.        
    10.         public class LevelLoader : MonoBehaviour
    11.         {
    12.             [Header("Start Button")]
    13.             [SerializeField] GameObject startGameButton;
    14.        
    15.             //-- Obsolete?
    16.             [Header("Progress Bar UI")]
    17.             [SerializeField] Slider slider;
    18.             [SerializeField] TMPro.TextMeshProUGUI progressText;
    19.    
    20.         [Header("Game List items")]
    21.         [SerializeField] private string gameListURL;
    22.         [SerializeField] private GameObject gamesListParent;
    23.         [SerializeField] private GameInfo_obj sceneButtonParent;
    24.         [SerializeField] private Transform sceneButtonContentHolder;
    25.    
    26.         private List<GameInfo> gamesList = new List<GameInfo>();
    27.    
    28.        
    29.         private void OnEnable()
    30.         {
    31.             startGameButton.SetActive(true);
    32.             slider.gameObject.SetActive(false);
    33.             progressText.gameObject.SetActive(false);
    34.             gamesListParent.SetActive(false);
    35.    
    36.    
    37.    
    38.         }
    39.    
    40.    
    41.    
    42.    
    43.         #region GET GAME LIST
    44.         public void GetGameList() { StartCoroutine(GetGameListCoRo()); }
    45.    
    46.         private IEnumerator GetGameListCoRo()
    47.         {
    48.             //-- Hide/Activate UI
    49.             startGameButton.SetActive(false);
    50.             gamesListParent.SetActive(true);
    51.    
    52.             //-- Request GameList from network
    53.             UnityWebRequest request = UnityWebRequest.Get(gameListURL);
    54.             yield return request.SendWebRequest();
    55.    
    56.    
    57.             //-- Check UWR for errors
    58.             if (request.isNetworkError || request.isHttpError)
    59.             {
    60.                 Debug.LogError("Downloaded Data was empty. Problem with UnityWebRequest.");
    61.                 Debug.LogError(request.error);
    62.    
    63.             }
    64.             else
    65.             {
    66.                 Debug.Log("request.downloadHandler.text: " + request.downloadHandler.text);
    67.             }
    68.    
    69.      
    70.  
    71.            //-- Break up the List per line
    72.                 string[] tempGames = request.downloadHandler.text?.Split(new string[] {System.Environment.NewLine}, System.StringSplitOptions.RemoveEmptyEntries);
    73.        
    74.       Debug.Log("tempGames: " + tempGames[0]);
    75.        
    76.                 //-- Add games to the GameList
    77.                 foreach (var game in tempGames)
    78.             {
    79.                 string[] currentGame = game?.Split('|');
    80.                                Debug.Log("currentGame: " + currentGame[0]);
    81.  
    82.                 gamesList.Add(new GameInfo(currentGame[0], currentGame[1]));
    83.                                  Debug.Log(currentGame[0] + ", " + currentGame[1]);
    84.                
    85.             }
    86.             //-- Create button for each Game
    87.             foreach (var game in gamesList)
    88.             {          
    89.    
    90.                 GameObject buttonInstance = Instantiate(sceneButtonParent);
    91.                 buttonInstance.transform.SetParent(sceneButtonContentHolder);
    92.    
    93.                 //-- Set Button Text
    94.                 TMPro.TextMeshProUGUI sceneButtonText = buttonInstance.GetComponentInChildren<TMPro.TextMeshProUGUI>();
    95.                 sceneButtonText.text = game.GameName;
    96.    
    97.                 //-- Set OnClick
    98.                 LeanButton sceneButtonButton = buttonInstance.GetComponentInChildren<LeanButton>();
    99.                 sceneButtonButton.OnClick.AddListener(() => LoadLevelRemotely(game.GameAddressable));
    100.    
    101.    
    102.                 //-- Set Button Name
    103.                 buttonInstance.name = game.GameName;
    104.    
    105.                 //-- Activate Button
    106.                 buttonInstance.SetActive(true);
    107.             }
    108.    
    109.    
    110.    
    111.            
    112.         }
    113.    
    114.    
    115.    
    116.         #region Addressables - LOAD LEVEL - REMOTELY
    117.         public void LoadLevelRemotely(string sceneAddressable)
    118.         {
    119.             StartCoroutine(LoadLevelRemotelyCoRoutine(sceneAddressable));
    120.         }
    121.    
    122.         IEnumerator LoadLevelRemotelyCoRoutine(string sceneAddressable)
    123.         {
    124.             Addressables.LoadSceneAsync(sceneAddressable);
    125.    
    126.            
    127.    
    128.             startGameButton.SetActive(false);
    129.             gamesListParent.SetActive(false);
    130.             // slider.gameObject.SetActive(true);
    131.             // progressText.gameObject.SetActive(true);
    132.    
    133.    
    134.             yield return null;
    135.            
    136.    
    137.            
    138.         }
    139.    
    140.    
    141.         #endregion
    142.  
    143.  


    Thanks ahead of time for any help!

    ------------------------------------------------------

    A few more little tid bits just for whatever they might help:
    Before I build the addressable, I include a textUI and an empty gameobject with the labels "Remote Scene". After the file is uploaded to the server, but before I test or build the whole app, I change them to "local scene". It's something I started before I figured out about "Packed Play", and just keep doing it so I feel confident I know for sure while scene I've loaded.

    I've also set Build Remote catalog and Can Change Post Release on the addressable build. And I make sure everything is set to RemoteBuild/Load and that I'm always in Packed Play.

    (Also, sorry the code alignment got messed up. With all the copy and pasting, and trying to post in Answers, having that not work, and moving it over here... the indents got messed up and it looks a bit sloppy/ugly.)

    Thanks again!
     
    AskCarol likes this.
  2. AskCarol

    AskCarol

    Joined:
    Nov 12, 2019
    Posts:
    234
    Hey @MichaelTGD! Sorry to hear you are having issues. The team will take a look and get back to you as soon as possible.
     
  3. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    762
    Just a couple questions (sorry if I missed them in your original post): Are you performing a content build for your desired platform before doing your player build? If so are there any errors that get logged during the build of player content (not the player build)?
     
  4. RJSD3V

    RJSD3V

    Joined:
    Aug 30, 2019
    Posts:
    4
    Is there a solution for this? I have the same problem.
     
  5. MichaelTGD

    MichaelTGD

    Joined:
    Oct 24, 2019
    Posts:
    16
    Oh, sorry, I guess I missed this response. Addressables was (and I guess, still is) the one thing I could never figure out. I wasn't able to just sit around and wait a month for a reply, as it was stagnating production, so I found another way to handle the matter.

    Instead of trying to use Addressables to package and download scenes for each city/event a player can choose, I have the app grab a file/json from the backend server and build the scene based on the choice. It's actually a much cleaner, simpler method for my purpose, so I'm glad I found it, but I'm disappointed I wasn't able to understand this regardless.

    Sorry I'm not able to help further.
     
    dimmduh1 likes this.