Create the same asset using AssetDatabase.CreateAsset(asset, path), the current scene is missing

PlayerData .cs

using UnityEngine;
public class PlayerData : ScriptableObject {
    public string id;
}

Player.cs

using UnityEngine;
public class Player : MonoBehaviour {
    public PlayerData data;
}

TestCreateAsset .cs Placed in the Editor folder

using UnityEditor;
using UnityEngine;
public class TestCreateAsset : Editor {
    [MenuItem("Tools/TestCreateAsset")]
    private static void Test() {
        PlayerData playerData = ScriptableObject.CreateInstance<PlayerData>();
        playerData.id = "aa";

        const string path = "Assets/playerData.asset";
        AssetDatabase.CreateAsset(playerData, path);
        AssetDatabase.Refresh();
    }
}
  1. Create Assets/playerData.asset, Using the menu Tools / TestCreateAsset

  2. Create a GameObject and add Player component, Player references playerData.asset
    image

  3. After completing the above operations, using Tools / TestCreateAsset again to create Assets/playerData.asset
    image

Missing
I checked .meta and playerData.asset and found no changes.
How should I solve this problem?

If you call the same code again, you are creating an entirely new asset, replacing the previous. Thus any previous references will become invalid.

If you just want to update the asset, then first check if it exists. If it does not exist yet, create it. Otherwise load the asset (unless you already have an asset object reference), then modify the asset, then call SaveAssetIfDirty(playerData). Note that for ScriptableObjects when changing their properties through scripts you have to call EditorUtility.SetDirty(playerData) beforehand to mark it as “dirty”.

If you want to create multiple assets, then use AssetDatabase.GenerateUniqueAssetPath to ensure the path is unique before calling CreateAsset. This will create files named playerData (1) and so forth, effectively preventing you from overwriting existing assets.

Do not call Refresh() UNLESS you create or modify assets WITHOUT using AssetDatabase methods (eg when using File.WriteAllBytes). All AssetDatabase methods internally ensure that the AssetDatabase is updated correspondingly.

Thank you,
I have successfully resolved the issue and modified the code as follows

using System.IO;
using UnityEditor;
using UnityEngine;
public class TestCreateAsset : Editor {
    [MenuItem("Tools/TestCreateAsset")]
    private static void Test() {
        const string path = "Assets/playerData.asset";

        PlayerData playerData;
        bool isExists = File.Exists(path);

        if (isExists) {
            playerData = AssetDatabase.LoadAssetAtPath<PlayerData>(path);
            playerData.id = "bb";
            EditorUtility.SetDirty(playerData);
            AssetDatabase.SaveAssetIfDirty(playerData);
        } else {
            playerData = ScriptableObject.CreateInstance<PlayerData>();
            playerData.id = "aa";
            AssetDatabase.CreateAsset(playerData, path);
        }

        AssetDatabase.Refresh();
    }
}
1 Like

Again, remove this! It’s utterly unnecessary. Devs just been putting it everywhere out of (bad) habit. There’s absolutely nothing that needs refreshing here. :wink:

Keep in mind that Refresh necessitates a call to UnloadUnusedResources eg effectively wiping any in-editor caching.