I’ve tried all sorts of right-clicking, dragging and Googling, to no effect. Now I’m asking here because I don’t want to believe the Unity team would let something this glaring go unchecked.
I’ve spent the last two days setting up a large blend tree with three 2D-blended branches at the root. I just found out I needed another node before the root for some other cases.
Am I going to have to manually redo everything, every time it happens?
Should I keep a buffer of dummy nodes?
How will the CPU/GPU workload be affected if I do?
Not a solution, but the closest thing I can think of is writing an editor script to change the data in an AnimatorController.
As you can see, there are methods to write blend trees into an animator controller, though I’m not sure I see any way to read from them… I’ll look deeper.
…
Yep! You can get a “motion” for a state.
And since blend trees inherit from motions, you’ll just have to do a type check to see if you then have a blend tree.
And then, I don’t really see any way to surgically replace that blend tree without having to copy out the entire layer’s contents, and re-create it all again.
So, principally, it’s possible to copy out all the layer info, target the blend tree data you want to edit, stuff, then reconstruct the layer. But that sounds like at least a week of quite tough work even for an experienced dev when you factor in all the UI you’d have to do. Yikes.
Sorry that I don’t have an answer, but, yeah, I would very much like someone else to make it easy to move blend tree nodes around.
I found this on another thread, asking similar question with slightly different wording. so pasting this here too since it helped me. i gives an error, but it makes the blend tree asset and one can then use this in a tree slot, allowing you to “make a parent”
using UnityEditor;
using UnityEngine;
using UnityEditor.Animations;
public class CreateBlendtreeAsset : MonoBehaviour {
[MenuItem("AnimTools/GameObject/Asset from Blendtree")]
static void CreateBlendtree()
{
string path = "Assets/";
string currentPath = AssetDatabase.GetAssetPath(Selection.activeObject);
if (currentPath != null)
{
path = currentPath;
}
BlendTree BT = Selection.activeObject as BlendTree;
BlendTree BTcopy = Instantiate<BlendTree>(BT);
AssetDatabase.CreateAsset(BTcopy, AssetDatabase.GenerateUniqueAssetPath(path + "_" + BT.name + ".asset"));
}
}
so put this in some (any) folder named “editor”, it makes a menu to the top bar called animTools
My editor extension adds a tree view window that displays the entire contents of an animator controller and allows you to drag/drop and reorganize blend trees. It supports adding, duplicating, and disconnecting blend trees.
Saving blend trees as assets has some pretty serious issues, the unity editor isn’t really setup to support that in all cases.
From the same thread that l3xxx above found that script, another response has been added, with a super simple editor script that lets you simply copy/paste trees:
So if your current setup is like this: BlendTreeA → motions
And you want a setup like this: BlendTreeB → BlendTreeA → motions
Then first select BlendTreeA, and copy it using the new menu option.
Then create a new blank setup if you need to, that has BlendTreeB → New Blend Tree, and then go into New Blend Tree (i.e. the nested one), then use the menu to paste.
using UnityEditor;
using UnityEngine;
using UnityEditor.Animations;
using System.IO;
public class CreateBlendTreeAsset
{
[MenuItem("Assets/Create/Animation Blend Tree", priority = 402)]
private static void CreateBlendTree()
{
var directory = GetSelectedDirectory();
var asset = new BlendTree();
var path = Path.Combine(directory, "New Blend Tree.asset");
// display immedate rename prompt in the project window
ProjectWindowUtil.CreateAsset(asset, path);
}
private static string GetSelectedDirectory()
{
var activeObject = Selection.activeObject;
if (activeObject == null)
{ // nothing is selected in the project window
return "Assets";
}
var activePath = AssetDatabase.GetAssetPath(activeObject);
if (activeObject is DefaultAsset)
{ // a folder is selected in the project window
return activePath;
}
// an asset is selected in the project window
return Path.GetDirectoryName(activePath);
}
}