1
\$\begingroup\$

I can create an animation file by clicking "Animation", then selecting a gameobject, then press record and then change bone rotations in the Inspector. The animation window will be notified about the bone rotation changes and add this to the animation file like this:

enter image description here

This works fine as long as the Inspector is used to change the bone rotations.

Bone rotations done by a script are not recorded.

Is there a trick to record these bone rotations via script anyways? For example using something like (pseudo-code) this? ->

rShoulder.rotation.dirty = true;

For your interest, I have attached the script that I use to rotate the bones and which are not recorded. This script works perfectly fine, but it doesn't trigger animation changes:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyPlayer : MonoBehaviour
{
    public Transform Target;

    private void OnGUI()
    {
        if (GUI.Button(new Rect(0, 70, 50, 30), "Transfer rotations to other model with same rig"))
        {
            List<Transform> nTheseTransforms = new List<Transform>();
            Helpers.GetAllChildren(this.transform, ref nTheseTransforms);

            List<Transform> nTargetTransforms = new List<Transform>();
            Helpers.GetAllChildren(Target, ref nTargetTransforms);

            foreach (Transform nThisTransform in nTheseTransforms)
            {
                foreach (Transform nTargetTransform in nTargetTransforms)
                {
                    if (nThisTransform.name == nTargetTransform.name)
                    {
                        nTargetTransform.localRotation = nThisTransform.localRotation;
                        break;
                    }
                }
            }
        }
    }
    public static void GetAllChildren(Transform parent, ref List<Transform> transforms)
    {
        foreach (Transform t in parent)
        {
            transforms.Add(t);
            GetAllChildren(t, ref transforms);
        }
    }

}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Do you observe any change to this behaviour when you use Undo.RecordObject to log the change your script is making? \$\endgroup\$
    – DMGregory
    Commented Sep 8, 2020 at 14:15
  • \$\begingroup\$ @DMGregory You are my hero!!! I got it to work. I will post an answer now. \$\endgroup\$
    – tmighty
    Commented Sep 8, 2020 at 18:43

1 Answer 1

1
\$\begingroup\$

DMGregory kindly pointed to me towards the solution.

The Animation window uses the Undo system to record the changes. The trick is to call

Undo.RecordObject(...) 

on the object that is about to be changed.

At first I tried it with Undo.RecordObject(nTargetTransform, "Rotation"). This didn't have any effect, so I thought this approach would simply not work.

Then I read a code sample here, and they used the argument "Inspector", and that worked. The bone rotations done by script were now being recorded.

Here is the full, working code:

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

public class MyPlayer : MonoBehaviour
{
    public Transform Target;

    private void OnGUI()
    {
        if (GUI.Button(new Rect(0, 70, 50, 30), "Transfer rotations to other model with same rig"))
        {
            List<Transform> nTheseTransforms = new List<Transform>();
            Helpers.GetAllChildren(this.transform, ref nTheseTransforms);

            List<Transform> nTargetTransforms = new List<Transform>();
            Helpers.GetAllChildren(Target, ref nTargetTransforms);

            foreach (Transform nThisTransform in nTheseTransforms)
            {
                foreach (Transform nTargetTransform in nTargetTransforms)
                {
                    if (nThisTransform.name == nTargetTransform.name)
                    {
                        Undo.RecordObject(nTargetTransform, "Inspector");
                        nTargetTransform.localRotation = nThisTransform.localRotation;
                        break;
                    }
                }
            }
        }
    }
    public static void GetAllChildren(Transform parent, ref List<Transform> transforms)
    {
        foreach (Transform t in parent)
        {
            transforms.Add(t);
            GetAllChildren(t, ref transforms);
        }
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .