1
\$\begingroup\$

I have a Unity project, where I recently changed the names of a few files in my Resources folder. This is relevant because I have code that looks like this:

        internal void LoadItems(string[] names)
        {
            var items = Resources.LoadAll<TileBase>("Tiles\\Items");
            var itemMap = items.ToDictionary(m => m.name.ToUpperInvariant());
            _items.Clear();
            _items.AddRange(names.Select(n => itemMap[n.ToUpperInvariant()]));
        }

The AddRange call is currently throwing an exception, because the incoming data is expecting the new names to be present, but itemMap for some reason still contains the old names. I've verified this in the debugger, and I've verified in Unity's file search that no file matching the old version of the name that's causing trouble here exists anywhere in the project anymore. And yet, when I run the project, (using the Attach To Unity And Run option from Visual Studio,) the old names still show up.

If I go into Build Settings and tell it to rebuild the project, this code works correctly... once. Subsequent runs cause it to fail, going back to the old names again, so it kind of feels like Unity is actively trolling me at this point.

The old data has to be cached somewhere, but I'm not sure where or how to fix it. Anyone know how I can resolve this?

\$\endgroup\$
  • \$\begingroup\$ When is LoadItems called, and how is the names argument populated? Are you sure looking up assets by name is an appropriate solution here? We may be able to suggest more robust solutions that aren't broken by a name change if we have a more complete picture of what you're trying to accomplish with this. \$\endgroup\$ – DMGregory May 18 '19 at 7:43
  • \$\begingroup\$ @DMGregory The names data is coming from the backend external server, that my code is supposed to remain in sync with, and this is called once, at startup. The idea is to pass a big list of all the items that may need to be drawn, by name, and turn it into an array, so that in the future the server can save hugely on bandwidth by sending indices instead of names. After looking at the documentation, I don't believe there's any simpler way to do this than searching through Resources; there are enough items that building the array by hand at design-time would be a huge waste of my time. \$\endgroup\$ – Mason Wheeler May 18 '19 at 12:12
1
\$\begingroup\$

Changing the file name does not automatically change the name property. That is, they are not inextricably linked. If you look inside the .asset or .prefab file for one of your assets (using Notepad, for example, assuming you are trying to load a prefab or ScriptableObject), you will see one or more “m_Name” entries. If any name matches the old file name, it may be that when you renamed the files, the name property did not get updated for some reason. If you try just making any change to the asset and re-saving the project it may solve the problem.

However, as DMGregory mentioned, there may be a better way than to access everything by file name. Perhaps simply a ScriptableObject like this:

[CreateAssetMenu]
public class TileBaseCollection : ScriptableObject {
  //To assign a name unrelated to the filename, so changing the filename doesn't affect anything:
  [Serializable]
  public struct TileBaseID {
    public string id;
    public TileBase tile;
  }
  public TileBaseID[] tiles;

  //or, if you have just a few tiles:
  public TileBase DesertTile;
  public TileBase GrassTile;
  //etc.
}

Note that if you create an instance of this, neither it nor the tiles referenced need to be in resources folders. Just declare a direct reference to the object in whatever MonoBehaviour you need to access the tiles from and assign the newly created object directly in the inspector.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Argh, that turned out to be exactly what the problem was. And I know I could do it this alternate way, but I have enough different tiles here (a few hundred of them) that trying to set that up would be a massive waste of time, which is why I chose this approach instead. \$\endgroup\$ – Mason Wheeler May 18 '19 at 12:29
  • \$\begingroup\$ @MasonWheeler note that it would be fairly easy to automate the process of setting it up with an editor script if you wanted to \$\endgroup\$ – Ed Marty May 18 '19 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.