Would that decrease performance?

Hello everyone.

In my game, I want each character in screen (let’s say about 100 characters at maximum) to have its own icon and 3d model as well as many other properties. Each character is an instance of the “character” class, and stores all its data in its properties.

I’ve stored on an xml database all the character “types” that go into the game (e.g. “Soldier” type, with its health points, level, an inventory, a 2d picture’s name…) and I read it to get all the data for that single character.

So, to start a game, I’m planning to use a foreach loop for every character on scene, which would be assigning all the needed values from the database (setting their HP, level…). Most of those properties are integers or strings, so I don’t think that would hurt performance much. But I also need to assign their 3d models (prefabs) and 2dTextures (the icons) in the database.

I’m thinking on having this done by using the Resources.Load() method (or one similar to this one) for each character’s model and icon. So I’ll get an string like “icon01” from the database, and then load it from the project folder using Resources.Load() would that hurt the performance much? I’m trying to keep this as optimal as possible, but I don’t see any other viable way to do it.

Thank you very much.

Instead of defining the data in a XML file, you could create a scriptable object which defines an NPC type, and then just attach that as a member property for each NPC in game.

It will mean you need to do a bit of editor scripting to create your particular scriptable object, but it’s not especially hard.

i.e.:

   [MenuItem("Assets/Create/Darkwurm/Level Map")]
   static void ContextCreateLevelMapAsset()
   {  // get filename
      string filename;
      int ndx = 1;
      
      // what file?
      do
      {
         filename = "/LevelMap" + ndx + ".asset";
         ++ndx;
      }
      while(System.IO.File.Exists(Application.dataPath + filename));
      
      // create the tree at the specified path
      CreateLevelMapAtPath("Assets" + filename, true);
   }   

   static DWLevelMap CreateLevelMapAtPath(string filename, bool focus)
   {  // create the asset
      DWLevelMap level_map = ScriptableObject.CreateInstance<DWLevelMap>();
      Assert.IsNotNull(level_map);
      AssetDatabase.CreateAsset(level_map, filename);
      AssetDatabase.SaveAssets();
      EditorUtility.FocusProjectWindow();
      EditorUtility.SetDirty(level_map); // okay, it's broadly empty but what the hell!
      if(focus) Selection.activeObject = level_map;
      return level_map;
   }

The above is some code to create a new DWLevelMap asset of ours. Apologies - it doesn’t create the item at the location you right clicked in your project (if anyone knows how to do this???).

This is not to say that other methods aren’t valid btw - I just went through the pain of using some other resource and finding it much easier to create a bunch of ScriptableObjects that I can use to define some game data. As it happens this DWLevelMap is a ScriptableObject that describes a map and is used only by the editor to build the map. So you don’t have to limit their use to in-game data - they can be used to describe structures you wish to edit.

We also use ScriptableObjects to store details of our Behaviour Trees, race and class information, items and much more.

I don’t know about performance, but it’s much easier to do it this way as Unity will know about your scriptable objects and in turn any prefabs they may be referencing and load all the resources necessary as you startup. Also, as you’re referencing a scriptable object, you will probably load less data instead of duplicating the data across your 100 mobs - it should be more memory efficient.

Don’t use foreach loop … it put downs un necessary garbages in memory