- Home /
How to keep a persistent reference to an asset? (Is there an OnAssetRename callback to update the asset's name if it changes?)
Hello,
I have a SceneTransition
MonoBehaviour
(which is essentially a trigger) that lets you select a scene from your project, when the player interacts with it, it just loads the scene you selected.
public class SceneTransition : BaseTrigger, Interaction
{
public string scene;
public void Interact(GameObject actor)
{
Interact();
}
public void Interact()
{
Application.LoadLevel(scene);
}
void Update()
{
if (isPlayerInSight && Input.GetKeyDown(Keys.action)) {
Interact(lastCollidingObject);
}
}
}
(The green ones are scenes included in the build, the reds are not)
The problem with this is that the scene is stored as a string, once you select a scene, the name is set (fixed) - now what happens if you renamed that scene and then tried to load it? you guessed it, it's gonna try and load a scene that doesn't exist and then I'd have to go in and manually reselect the scene to update the string.
So what I tried is, instead of using a string, I used a direct UE.Object
reference to the scene file, but even with that, it seems that if I rename the scene file, the link (reference) gets broken! (as if the asset gets a new location in memory)
So that's why I'm looking for a way, a callback that notifies me if there's a scene rename (asset rename in general, I could filter the results) and then get all the SceneTransitions
in the current scene, and see if anyone of them was referencing the renamed scene, if so then update the old name, with the new one.
(But even if we get to that point, what about the SceneTransitions
that are in the other, unloaded scenes?... :/)
Note that I know about ProjectWindowUtil.StartNameEditingIfProjectWindowExists
and the EndNameEditAction
but I'm not sure if these could help here...
Any ideas?
Thanks!
Answer by Jamora · Feb 23, 2014 at 11:09 AM
You should use the GUID of the asset instead of its name, for the reasons you explained.
To get the GUID you need to know the location of the asset: GetAssetOrSenePath or manually iterate the directory tree for scenes
Then get the asset GUID: AssetPathToGUID
Store the GUID
Whenever you need to access that object: LoadAssetAtPath(GUIDToAssetPath(GUID))
You might run into some problems if the asset is moved, because the GUID seems to operate on the path.
Thank you! Worked like charm!
I subscribed to EditorApplication.update
with this method:
private void UpdateSceneIfThereIsChange()
{
if (sp_scene == null || sp_guid == null || System.String.IsNullOrEmpty(sp_guid.stringValue)) return;
string currentPath = AssetDatabase.GUIDToAssetPath(sp_guid.stringValue);
string currentSceneName = Utils.GetAssetName(currentPath).RemoveExtension();
if (sp_scene.stringValue != currentSceneName) {
Debug.Log("there's been a rename, old name: " + sp_scene.stringValue + " new name: " + currentSceneName);
sp_scene.stringValue = currentSceneName;
sp_scene.serializedObject.Apply$$anonymous$$odifiedProperties();
}
}