samedi 6 juillet 2019

Creating a ScriptableObject asset in a custom folder from a calling script using Reflection

To make my life harder (/s), I am trying to automatically create ScriptableObjects if a field is null. I want to place the newly created ScriptableObjects in a custom folder in the same folder as the creating script.

For example, my "TreasureChestManager" has been newly created and placed on a GameObject. Using Reflection, I can see that it's field for OnTreasureChestFound is null. I haven't created the ScriptableObject OnTreasureChestFound yet, so I want to automatically create the asset, save to a folder called "Events" (that is a folder in the same folder as the TreasureChestManager.cs script).

Then I want to set the value for the OnTreasureChestFound to the newly created ScriptableObject of class type 'GameEvent`.

My issue is, I can't seem to get the correct file path of "Events" folder, that I want to store my GameEvent in.

I have tried different ways of getting the correct path. Some give me the root folder of the project, some fail. I have tried different combinations.

My fear is not creating the ScriptableObject in the correct manor that Unity has issues with it.

'GameEvent` is the Class name of the ScriptableObject. It lives in a different folder somewhere else in the project.

In the OnValidate() method of TreasureChestManager.cs I am doing the following:

FieldInfo[] fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);

            //This gets the names of the fields and the field name
            foreach (var field in fields)
            {

                if (field.FieldType.Name.Equals("GameEvent"))
                {
                    string fname = field.Name;
                    object temp = field.GetValue(this);


                    if (temp == null)
                    {

                        ////string path = AssetDatabase.GetAssetPath(gameObject) + "/Events/";
                        //string codeBase = Assembly.GetExecutingAssembly().CodeBase;
                        //UriBuilder uri = new UriBuilder(codeBase);
                        //string uripath = Uri.UnescapeDataString(uri.Path);
                        ////string path = Environment.CurrentDirectory;
                        //string path = Path.GetDirectoryName(uripath);

                        //string path = Path.GetDirectoryName(GetType().Name);

                        string path = AssetDatabase.GetAssetPath(GetInstanceID()) + "/Events/";
                        Debug.Log($"Path: {path}");

                        var gameEvent = GameEvent.CreateGameEventWithName(fname, path);
                        field.SetValue(this, gameEvent);
                    }
                }
            }

            EditorUtility.SetDirty(this);

Here is the ScriptableObject script GameEvent

 public class GameEvent : ScriptableObject
    {
        // other properties and methods

        public static GameEvent CreateGameEventWithName(string name, string path)
        {

            GameEvent asset = CreateInstance<GameEvent>();

            string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path  + name + ".asset");

            AssetDatabase.CreateAsset(asset, assetPathAndName);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

            return asset;
        }
}





Aucun commentaire:

Enregistrer un commentaire