Search Unity

Feedbacks for experimental feature: GameObjectRecorder (2017.1)

Discussion in 'Animation' started by Deleted User, Apr 24, 2017.

  1. metroidsnes

    metroidsnes

    Joined:
    Jan 5, 2014
    Posts:
    63
  2. Tortuap

    Tortuap

    Joined:
    Dec 4, 2013
    Posts:
    48
    Hello
    Why do the GameObjectRecorder sample recorded data ?
    Could we have an option to disable that ?

    I'm recording a custom Component (with one float member) witch have specific value changes at specific times.

    What I would expect is a set of keys for each value change, at precise time of the change.

    What I get is a sampled recording, with keys each 49th frames, whatever if the value hasn't changed, and no keys between even if the value has changed 10 times between.
     
  3. Deleted User

    Deleted User

    Guest

    @Tortuap We're aware of this limitation (it's been raised in a previous message here in this thread IIRC). There is indeed a compression of the recorded data, otherwise you would see a keys every frame, but our compression algorithm does force the creation of a keys once every 50 frames. This limitation is here in order to accelerate the compression process.

    I would like to fix that one day, but it's never been raised in the context of a game project and, on the other hand, the animation compression algorithm can be critical in some game projects (think of FPS games where the compression can have a disastrous effect if the bones shakes just even a little). So, in that matter, keeping the current compression behaviour outweigh the benefit of changing it for another one that would not have a significant impact.

    So, for now, we'll keep the current behaviour. The future solution would be to create a new compression algorithm and propose it as an option.
     
  4. jaraen

    jaraen

    Joined:
    Jul 28, 2016
    Posts:
    17
    @RomainFaillot, this is absolutely awesome, thanks a lot for sharing. Just started playing with it and got stuck on trying to record an animated humanoid character. I read in some early comment that they were not supported yet. Is it still the case? Is there any workaround? Using Unity 2018.2.0f2 Thanks a lot!
     
    Last edited: Sep 18, 2018
    Deleted User likes this.
  5. Deleted User

    Deleted User

    Guest

    Hi @jaraen,

    Yes, unfortunately it still not possible to record humanoid properties. We have a plan, but we're focusing on other features at the moment (namely the Animation C# Jobs and Runtime Rigging). We're not forgetting the GameObjectRecorder, but we simply rotate on the new features we want to bring on the next releases. I hope you understand ;)

    The only workaround I see right now is to record your humanoid character (be careful that the GameObjectRecorder's root is the same as where the Animator's GameObject), and have also a generic prefab of your character where you'd be able to replay the recorded animation on.
     
  6. Tortuap

    Tortuap

    Joined:
    Dec 4, 2013
    Posts:
    48
    Hi @RomainFaillot,
    I've developed my own recording solution, so far I'm good now.
    But, I don't get why "otherwise you would see a key every frame" if no property has changed ?
     
  7. Deleted User

    Deleted User

    Guest

    It's simply because we don't compress the data on the fly (in order to lose the minimum amount of time while recording). The compression is done when calling SaveToClip().

    So if the compression pass wasn't there you would not exactly have a key every frame, but a key for every time TakeSnapshot() was called.

    Edit: but it might be improved with an idea that we have which would lead to less keys without too much impact on the recording.
     
  8. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,137
    It just took me a little while to "re-find" this feature and I have just spent my remaining three votes for Use the GameObjectRecorder in the Player ... but I have read about the limitations. I also had a quick look at Unity Recorder but this looks like it can handle a lot more than we need, adding a lot of complexity I'd rather not have to deal with ;-)

    We already have a fully functional gameplay recording system and our own simple JSON format to store the gameplay data that we have recorded. But I was considering replacing our own approach with something that's built-in.

    What we need and use this for is recording player movement data in VR, so we have at least head and two hand poses, but this could also be much more if people add additional tracking points (like for feet, hips, knees, elbows or even finger tracking). For us, only the pose (position, rotation) is interesting. Obviously, we're tracking physical body movement, so we could make quite a few assumptions based on that (it's impossible, for example, the have instant changes of velocity due to momentum).

    The way we do "compression" is by defining a resolution (could be only 10 frames per second, even though we run at 90), and distance thresholds (so we don't generate data just due to some jittering). What I was hoping GameObjectRecorder would solve for us is converting the keyframes into curves, which, if done in a smart way could theoretically reduce data quite significantly while not losing as much quality ... but I don't even know whether or not this problem is well solved (I do know that existing reduction algorithms in Unity / Blender can add significant skating when the original animation was perfect).

    So, I'd just like to add my voice to those who want/need this in players (there's no way we can make use of this when it's only available in the editor). Also, we would not need saving this to animation clips. What we would need is only a way to access the data so we can serialize it to JSON, and then somehow play it back; all in runtime.

    Do you think this could happen any time soon?
     
  9. Deleted User

    Deleted User

    Guest

    Hi @jashan,

    Your request makes perfect sense, and thanks for explaining it nicely

    Your votes are really important to us (for real!). It has a direct impact on our priorities since it is taken into account when calculating what we call the "User Pain" score of an issue. In other words, the more votes this feature has, the higher it gets in our priorities.

    The good news is that, slowly, and through fixing other issues, we're getting to a point where authoring animation at runtime is almost possible. But we're not there yet.

    Right now, I can't get you any date on when this will happen, but I'm confident it will happen. Although the animation roadmap seems small, it is filled with heavy features (such as a brand new C# animation system) which already take us the vast majority of our time.

    So, TL;DR, we're slowly getting there.

    Cheers!
     
  10. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,296
    That would be so cool! I'd love to put an animation replay in game but it's too much work for a small team right now. I'll keep an eye on the thread.
    +1 for me :p (also voted)
     
    Deleted User likes this.
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,551
    I just got a notification about an update on this thread.

    Looks like I never answered.

    But... You know that's quite limited and makes it very hard to expand? You MUST have serializable members, for no other reasons but the animation to feed values into them, even if not needed.

    How about I want to put values in animation track "A", and at some point in time, I want to evaluate what "A" is. Right now, I need the whole system to do the evaluation all the time, even if not needed. I simply cannot put a value in, and get a value out when needed.

    Serialization in Unity has never been a strong suit and there's 0 plan to make it better in the future. :(
     
  12. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,137
    Sounds good! One unfortunate thing is that I'm already recording and storing data, so whenever it lands, I'll probably have to change my data format (which only stores keyframes and then the playback system lerps between those naively ;-) ) ... but the good thing about this, on the other hand, is that there's no pressure ;-)
     
    Deleted User likes this.
  13. benthroop

    benthroop

    Joined:
    Jan 5, 2007
    Posts:
    137
    Hey thanks for making this. We're using it for avatar recording in VR and it works great.

    We're seeing something that seems like a bug and I want to put it to you Romain. We are making one animation clip after another and saving them. This works great. Each time we start a new clip, we make a new GameObjectRecorder, snapshot into it, then save the clip.

    However, we just had the idea to insert AnimationEvents into the clips right before they are saved. We accumulate a few events as the clip is being recorded and then right in the same function where we call GameObjectRecorder.SaveToClip, we insert the events into the clip.

    So, this almost works. If we make 4 clips in a row in one run, then the first 3 do not save their AnimationEvents. However the last one does.

    Can you think of anything particular with AnimationEvents and SaveToClip that might cause them to, perhaps, get inserted asynchronously? Wondering if there's a race condition somewhere in here. Happy to share code if it helps.

    Thanks
     
  14. benthroop

    benthroop

    Joined:
    Jan 5, 2007
    Posts:
    137
    Actually we're all set. It turns out that we were using a function to add events that is documented as not persisting properly. Docs say "Note that events added with AddEvent will only persist until play mode is exited of player is quit. If you want to add an event to a clip persistently, use AnimationUtility.SetAnimationEvents from the Unity editor.". So we switched to SetAnimationEvents and everything is fine. Just leaving this note here in case anyone else gets bitten by that.
     
    Deleted User likes this.
  15. caolanmacgp2

    caolanmacgp2

    Joined:
    Mar 3, 2019
    Posts:
    2
    If I wanted to only record Scale or position how would I do that
     
  16. Deleted User

    Deleted User

    Guest

    You would need to create the right EditorCurveBinding and use the Bind method, like this:
    Code (CSharp):
    1. m_Recorder.Bind(EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalScale.x"););
    2. m_Recorder.Bind(EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalScale.y"););
    3. m_Recorder.Bind(EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalScale.z"););
     
  17. caolanmacgp2

    caolanmacgp2

    Joined:
    Mar 3, 2019
    Posts:
    2
    Is there any way I could Record say for example simulation speed on a particle system. I have m_Recorder.Bind(EditorCurveBinding.FloatCurve("", typeof(ParticleSystem), "m_SimulationSpeed"));
    but in the animation file it record 1 frame at the start and 1 at the end. Any way to fix this?
    (Im using unity 2017)
     
  18. Deleted User

    Deleted User

    Guest

    If it's "animatable", then it's possible.
    Maybe try with m_Recorder.BindComponent(GetComponent<ParticleSystem>()) and see the properties that are recorded
     
  19. shedworksdigital

    shedworksdigital

    Joined:
    Nov 7, 2016
    Posts:
    40
    Hi, I'm having some trouble with binding recursive transforms to a GameObjectRecorder.

    I'm trying to record the movements of a character, as well as all the movements of the bone transforms in the character's rig. The idea is to record some gameplay, then play it back and render it out into video for a trailer. I've written a simple test script to do this that looks like this:

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEditor.Animations;
    3. using UnityEngine;
    4.  
    5. public class TestRecorder : MonoBehaviour
    6. {
    7.     public string AssetName;
    8.  
    9.     private GameObjectRecorder _recorder;
    10.  
    11.     private void Awake()
    12.     {
    13.         _recorder = new GameObjectRecorder(gameObject);
    14.     }
    15.  
    16.     private void Update()
    17.     {
    18.         if (Input.GetKeyDown(KeyCode.Return))
    19.         {
    20.             if (!_recorder.isRecording) StartRecording();
    21.             else StopRecording();
    22.             return;
    23.         }
    24.      
    25.         if(_recorder.isRecording) _recorder.TakeSnapshot(Time.deltaTime);
    26.     }
    27.  
    28.     private void StartRecording()
    29.     {
    30.         _recorder.BindComponentsOfType<Transform>(gameObject, false);
    31.         _recorder.BindComponentsOfType<Transform>(transform.Find("AnimatedRig").gameObject, true);
    32.  
    33.         _recorder.TakeSnapshot(0f);
    34.     }
    35.  
    36.     private void StopRecording()
    37.     {
    38.         var clip = new AnimationClip();
    39.         _recorder.SaveToClip(clip);
    40.         _recorder.ResetRecording();
    41.      
    42.         AssetDatabase.CreateAsset(clip, $"Assets/{AssetName}.anim");
    43.     }
    44. }
    45.  
    The curves for the root transform record properly, but all the curves for the child transforms just come out as constants set to 0,0,0. Here's a link to a .anim file recorded using the above script.

    I'm calling BindComponentsOfType twice because the root object has a lot of other children that aren't relevant to the animation, so this is a way to keep the .anim files more manageable. If I just call BindComponentsOfType once, with the recursive parameter set to true, I get exactly the same problem.

    Any thoughts on how I can fix this?
     
  20. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,667
    Hi @shedworksdigital

    There is nothing obvious from your code snippet that could explain this behaviour.

    could you log a bug please?

    I did some tests last week with GameObjectRecorder on both 2019.2 and our latest trunk version and it was working as expected.
     
    shedworksdigital likes this.
  21. shedworksdigital

    shedworksdigital

    Joined:
    Nov 7, 2016
    Posts:
    40
    Thanks @Mecanim-Dev - I just submitted a report with a repro project. Don't have a link to it yet but I'll post it here when it comes through.

    Edit: the ticket number is 1151193_krhqig12ve1qanq4
     
    Last edited: May 2, 2019
    Mecanim-Dev likes this.
  22. unity_327743090

    unity_327743090

    Joined:
    Mar 16, 2019
    Posts:
    3
    I hope that the level below the root object I add is optional, how do I modify the code?
     
  23. unity_327743090

    unity_327743090

    Joined:
    Mar 16, 2019
    Posts:
    3
    And how do I control Destroy and active?
     
  24. Janoooba

    Janoooba

    Joined:
    Feb 9, 2016
    Posts:
    20
    Heyo, this is working great so far. I am also using it to record blend shapes, but atm I have it set to record the entire meshrenderer, which means it records attributes that I'm not interested in. Is there any way to bind only the blend shapes? I can't figure out what path I need to pass it to get this done.
     
  25. Polaaa

    Polaaa

    Joined:
    Sep 29, 2017
    Posts:
    7
    Any news for humanoid support?
     
  26. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,001
    If you happen to have Final IK, you are already able to record humanoid animation with the recently added Baker tool. Doesn't have support for blend shapes or custom animation curves/events yet though.
     
  27. Janoooba

    Janoooba

    Joined:
    Feb 9, 2016
    Posts:
    20
    For anyone who stumbles upon this in the future, I figured it out. You can bind individual blendshapes using the following code:

    Code (CSharp):
    1. for (int i = 0; i < skinnedMesh.sharedMesh.blendShapeCount; i++)
    2. {
    3.     string blendShapeName = skinnedMesh.sharedMesh.GetBlendShapeName(i);
    4.     EditorCurveBinding binding = EditorCurveBinding.FloatCurve("", typeof(SkinnedMeshRenderer), $"blendShape.{blendShapeName}");
    5.     blendshapeRecorder.Bind(binding);
    6. }
    You must target the blend shapes by name, using "blendShape.[name]"
     
unityunity