Custom Editor that uses CSV for GameObject Creation and Property Assignment

Hello! Thank you for taking the time to read this. :slight_smile:

I am currently working on a custom Unity editor tool that will allow me to press a button at the the top of the Unity window and create GameObjects. I’m in need of this tool because each time I create a GameObject I have to attach a script and then manually fill in all the fields and attach the related GameObjects, mp3 files, etc.

Currently I have the tool setup so when I press Generate Monsters at the top, Unity will take an excel spread sheet, generate new game objects and attach my script to those GameObjects. I am now in the process of attempting to figure out how to make it fill out/attach the rest of my data related to that script (automatically) once this script has been attached. I am currently using a CSV file to create the objects.

Are there any tools that currently do this? I have looked around on the Asset Store, YouTube, and the forums and can’t seem to find what I’m looking for. I’m still relatively new to Unity and am willing to continue my own script, but I’ve been spinning my wheels in the mud for a while now.

I have attached a screenshot of my Unity Inspector (so you can kind of see what I’m talking about) and my Excel CSV (this is just a quick example).

For the type of game that I’m creating I really need to create objects in this way. (I know there are other ways to do monster spawns and things)

Any feedback to assist me in this matter is greatly appreciated - thank you for your time. Have a blessed day.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using UnityEngine.Networking;


public class MonsterMaker : MonoBehaviour
{
    private static string monsterStatsCSV = "Editor/CSVs/monsterStats.csv";
    public GameObject monsterNames;
    private string m_Directory = string.Empty;
    public MonsterAttributes monAtt;

    [MenuItem("Utilities/Create Monsters")]
    public static void GenerateMonsterNames()
    {
        string[] allLines = File.ReadAllLines(Application.dataPath + monsterStatsCSV);
        foreach (string s in allLines)
        {
            string[] splitData = s.Split(',');
            GameObject monsterNames = new GameObject("monsterNames");
            monsterNames.gameObject.name = splitData[0];
            monsterNames.AddComponent<MonsterAttributes>();
        }
        AssetDatabase.SaveAssets();
    }
}


Any reason you’re not just using ScriptableObjects (and collections of them) to do this??

CSV is great if you’re exporting to somewhere else (like localization) but if it’s just for in-engine use, all you have really done is greatly increased the friction surface in your software when it comes to interoperating with that data.

1 Like

So my small remote team creates these tables for me and then I click the button to generate them in the game so that I can further modify them if needed. Unity only reads from the CSV once (during creation) and then it is no longer needed. I plan to not only use this for monsters, but other objects that I need to generate that are intricate and repetitive as well. I suppose I could do them as scriptable objects, but I was really wanting to keep them as traditional GameObjects as they are easily manipulated in the editor. I’m not sure where the addional friction would come as they are only being created once.

With ScriptableObjects you use the actual object. The data is there, you use it, you’re done.

With a CSV you have to read it in, turn it into some kind of object just to get to the point where you can use it.

That’s the friction.

That said, it’s not insurmountable and it sounds like you have your reasons.

When do you contemplate this “import” happening from CSV? The above code will only run in editor, NEVER in the game. Are you aware of that?

You are correct, it never happens in game; it’s only meant to be used as an editor tool in Unity. So whenever it’s time for me to setup a specific level/scene/environment, I set up my environment in Unity and then I want to create objects within Unity’s Hierarchy. I basically press generate and then they appear in the Inspector for me to manipulate. I’m using it currently for monsters, but it will in the future be used for all sorts of other GameObjects. I’ll attach a picture for reference. This tools is more meant for scene setup so that I can manipulate and modify from there.

Okay, so it’s basically CSV-driven procedural generation which you then save as an asset (such as scene or prefab) and then potentially update later.

As far as “pre-made tools,” the shape and structure of what you contemplate is going to be pretty tightly-bound to your game concept and game setup in general.

That is correct.

I’m fine if there isn’t a premade tool, I just felt like I can’t be the only one that needs to automate GameObject assembly - figured there would be something out there.

Any suggestions for my path forward? I’ve tried to see if I could find other snippets of code and integrate them into my solution, to no avail. I’m currently trying to get the script to reiterate through the GameObjects once the script is attached to fill out the information/data/attributes from that script. I thought my first step would be having the script set the Enchanted bool so that I wouldn’t have to go through and click that bool on or off for each object.

Edit: Also thank you for taking the time to chat with me about this, I really appreciate it.

Um… there’s the Unity editor. Our entire team works in it.

Engineers write code.

Artists create artwork.

Technical artists import and configure that artwork into Prefabs.

Animators animate the content.

Designers use the prefabs and ScriptableObjects to create content.

QA people run the content (on devices) and when they have bugs, they go into the editor and try to reproduce it so that they can report the bug effectively.

There’s plenty of room for custom tooling and custom objects and custom stuff all along there, with each person able to ask the other person “Hey I want to do X, can you make me something to do this?”

But we would NEVER reach outside of Unity unless we had to send that data to someone not on the team, such as localization.

I meant no disrespect with my comment, my apologies if it came across as disrespectful. I just meant that the Asset Store is full of useful tools and I was surprised I didn’t see something for what I was trying to do (I didn’t figure my need was that special if that makes sense). It’s alright if there’s nothing out there, if I end up making this tool work, I’ll release it on the Asset Store for free.

What you want is to make your file a txt, because you can natively feed txt file in the editor, and I’ve written a fair share of parsers which run natively, like you would normally work on a texture in PS, and upon saving, it would seamlessly update itself on its own when you get back to Unity.

In my editor I expose a variable expecting a TextAsset, to which you then dragndrop your txt file. I then created a FileSystemWatcher. Here’s an example

public TextAsset _apexFile;
FileSystemWatcher _watcher;
bool _dirty = false;
void createFileWatcher(string folderPath) {
  _watcher = new FileSystemWatcher(folderPath);
  _watcher.NotifyFilter = NotifyFilters.LastWrite;
  _watcher.Filter = "*.txt";
  _watcher.EnableRaisingEvents = true;
  _watcher.Changed += fileChanged;
}
void fileChanged(object source, FileSystemEventArgs e) {
  _dirty = true;
  AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
  var file = AssetDatabase.GetAssetPath(_apexFile);
  AssetDatabase.ImportAsset(file);
  refresh();
}
void Update() => refresh();

void refresh() {
  if(!_dirty) return;

  // I just reuse existing methods to reset all states
  OnDisable();
  OnEnable();

  // here my parser gulps the source as a string
  _console.Load(_apexFile.text);

  float startTime = Time.realtimeSinceStartup;

  // then I proceed treating the source as a batch file, in my case
  // you do you
  _console.ExecAll();

  Debug.Log($"{(Time.realtimeSinceStartup - startTime):F6} s");

  _dirty = false;
}

This is a simple MonoBehaviour mind you, not a UnityEditor.Editor.
It has [ExecuteInEditMode] attribute which helps me achieve a very rapid coding style with my tools and utilities.
Obviously it’s not suitable for deployment, so either guard it with #if UNITY_EDITOR clauses
or place it into Editor folder

Other related stuff

void OnEnable() {
  if(_apexFile == null) return;
  _active = true;

  _console = // I create my console object
  // yadda yadda

  createFileWatcher(getFileFolder(_apexFile));
  _dirty = true;
}

string getFileFolder(TextAsset file) {
  string ltrim(string path) => path.Substring(path.IndexOf("/"));
  string rtrim(string path) => path.Substring(0, path.LastIndexOf("/") + 1);
  return Application.dataPath + ltrim(rtrim(AssetDatabase.GetAssetPath(file)));
}

void OnDisable() {
  if(_console != null) _console.Dispose(); // whatever
  // here I purge all lingering states for my objects

  destroyFileWatcher();
  _active = false;
}

void destroyFileWatcher() {
  if(_watcher != null) {
    _watcher.Changed -= fileChanged;
    _watcher.Dispose();
  }
}

You obviously need to use the string you’ve gotten in this fashion by coding a proper parser.
In this particular case I read the lines one by one and split them into a chain of commands.
You can use TextReader or something similar.

Note: This is only a rough sketch. If it’s over your head, that’s ok, check out the links and move slowly. Maybe you can do something simpler for your case.

Thank you for response, I’ll mull this over and see if I can get it to work for my use-case. Thank you for taking the time to post this.

This works so well, that you can literally work in your file (in front of Unity), save it, ALT+TAB and immediately see the digested results.

I’ve made a Houdini-like application that lets you produce procedural 3D meshes from a txt file with a series of commands. Pretty powerful stuff that I’m yet to flesh out to full potential.

So I understand where you’re coming from with what you’re doing. Sometimes we really do need a working pipeline that extends beyond Unity editor.

Yes, if I get anything fleshed out beyond what I have, I’ll be sure to post everything and let you know. You’re more than welcome to use anything I come up; I really appreciate your response.