Hi!

I am encountering a really strange issue and I truly cannot comprehend what is causing it.

I recently added a save system to my game and I took this opportunity to also make the menus (main menu, pause menu, etc.). For all of those menus I added a panel with a placeholder texture in them.

Once my save/load system was functionnal I wanted to make my menus prettier and change the textures in the panel.

Here is the issue:

When I change the texture, it sometimes break the load system. It depends on the texture and on the panel. Some texture break the game if they are put in the panel of the load menu but not in the panel of the main menu, etc. The error message is always the same.

I made this video showing the bug. You can see that in the beginning, I can launch the game and load the last save (via the "continue" button). But when I change the texture, the game launches but the continue button refuses to work.

Here is the full error message;

E 0:00:02:0743 Dictionary.cs:644 @ TValue Godot.Collections.Dictionary2.get_Item(TKey): System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
<Erreur C#> System.Collections.Generic.KeyNotFoundException
<Source C#> /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs:644 @ TValue Godot.Collections.Dictionary
2.get_Item(TKey)
<Pile des appels>Dictionary.cs:644 @ TValue Godot.Collections.Dictionary`2.get_Item(TKey)
save_load_manager.cs:195 @ void save_load_manager.TrueLoad(string, string)
main_menu.cs:84 @ void main_menu._on_continue_button_down()
main_menu_ScriptMethods.generated.cs:104 @ bool main_menu.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name&, Godot.NativeInterop.NativeVariantPtrArgs, Godot.NativeInterop.godot_variant&)
CSharpInstanceBridge.cs:24 @ Godot.NativeInterop.godot_bool Godot.Bridge.CSharpInstanceBridge.Call(nint, Godot.NativeInterop.godot_string_name, Godot.NativeInterop.godot_variant**, int, Godot.NativeInterop.godot_variant_call_error, Godot.NativeInterop.godot_variant*)

It does not seem to be linked to the file size or the file extension.

Any help would be really appreciated, thank you very much! 🙂

  • xyz replied to this.
  • Aristobulus Those are not node names. They are just stringified node references. Saving/loading this makes no sense whatsoever.

    Aristobulus Well the error message is quite clear. You're trying to fetch a non existent key from the dictionary. Let's see the actual code.

      xyz

      Thank you for your reply. I do agree the message is clear.

      Here is the method that doesn't work when the texture is changed:

          public void TrueLoad(string profile, string name)
          {
              MusicManager.CallingTheChildrenBack();
      
              var GameData = LoadGame(profile, name);
      
              GD.Print(profile, name);
      
              ProfileName = GameData["ProfileName"];
      
              Node NODES = GetNode<Node>("/root/PROCEAN/MAP/NODES");
      
              Godot.Collections.Array<Godot.Node> IslandNodes = NODES.GetChildren();
      
              GetTree().CallGroup("Music Detectors", "Standby"); // This line avoid an error message due to a bad interaction between the music detectors area and the music streamers
      
              foreach (var node in IslandNodes)
              {
                  MapManager.LoadMap(GameData[$"{node}Path"], GameData[$"{node}IslandDirectory"], GameData[$"{node}Rotation"]);
              }
      
              Vector2 PlayerPos = new Vector2(GameData["PlayerPositionX"].ToFloat(), GameData["PlayerPositionY"].ToFloat());
              Vector2 BezierPos = new Vector2(GameData["BezierPosX"].ToFloat(), GameData["BezierPosY"].ToFloat());
              GameManager.SpawnPlayer(PlayerPos, GameData["CurrentBoat"], BezierPos, GameData["Speed"]);
      
              GetTree().CallGroup("QuitHarborButtons", "QuittingHarborOnReload");
      
      
              if (GameData["InAnInterface"] == "True")
              {
                  PlayerProperties.InAnInterface = true;
              }
              else { PlayerProperties.InAnInterface = false; }
      
              if (GameData["InADock"] == "True")
              {
                  PlayerProperties.InADock = true;
              }
              else { PlayerProperties.InADock = false; }
      
              if (GameData["DockCamera"] == "True")
              {
                  PlayerProperties.DockCamera = true;
              }
              else { PlayerProperties.DockCamera = false; }
          }
      }

      To be specific, it can't access GameData. Wich tells me it wasn't load properly via my function LoadGame().

      Here is that function:

      public Dictionary<string, string> LoadGame(string profile, string name)
      {
          if (FileAccess.Open($"user://Saves/{profile}/{name}/{name}.json", FileAccess.ModeFlags.Read) != null)
          {
      
              FileAccess file = FileAccess.Open($"user://Saves/{profile}/{name}/{name}.json", FileAccess.ModeFlags.Read);
      
              string content = file.GetAsText();
      
              return JsonConvert.DeserializeObject<Dictionary<string, string>>(content);
      
          }
          return null;
      }

      I don't understand how changing the texture in a panel can affect those lines of code...

      • xyz replied to this.

        xyz

        It seems to be this one:

                MapManager.LoadMap(GameData[$"{node}Path"], GameData[$"{node}IslandDirectory"], GameData[$"{node}Rotation"]);
        • xyz replied to this.

          xyz

          It is calling this function:

          
           public void LoadMap(string path, string id,string degrees)
           {
               var BagOfIslands = this;
          
               //Finding the Island node to reload
               islandnode_dataholder IslandNode = GetNode< islandnode_dataholder >(path);
          
               //Cleaning the previous islands
               IslandNode.GetChild(1).QueueFree();
          
               //Where the scene (=Island) is added as a child node
               Island = (Node2D)GD.Load<PackedScene>(id).Instantiate();
               Node IslandRobotMarker = IslandNode.GetChild(0);
               IslandRobotMarker.AddSibling(Island);
          
               //Where the node characteristics are altered
               float rotation = degrees.ToFloat();
               Island.RotationDegrees = rotation;
          
               //Store the island ID for reload
               IslandNode.IslandDirectory = id;
               
           }

          Aristobulus Well print the GameData object to see if it contains all the keys you expect it to contain.

            xyz Printing the GameData returns what's expected. It is the complete and exact data from the Json file.

            xyz

            I found something! Changing the texture changes the name of the node that is called! And it doesn't correspond to the node saved in the Json file. This is why it breaks. Thank you!

            But I don't understand why the name of the node changes.

            Instead of calling one of those :
            <Node2D#34141635808>
            <Node2D#34175190235>
            <Node2D#34208744701>

            It calls:
            Node2D#34108081376>

            I will immediatly check if it is always the same.

            EDIT:

            Depending on the texture I chose for the panel, it sometimes changes the ID of the node. Sometimes not. And the ID change seems to depend on and be specific to the texture chosen.

            • xyz replied to this.

              Aristobulus Those are not node names. They are just stringified node references. Saving/loading this makes no sense whatsoever.

                xyz Oh ok! So they will inevitabely change over time?

                That seems to be easy to fix. I will just save the nodes actual names.

                You already helped me months ago for another problem on this project. So thank you very much for your assistance.

                EDIT:

                The problem is solved! What a relief.

                Aristobulus changed the title to [SOLVED] Issue with dictionnaries breaking when changing texture in panels .