Search Unity

[Released] Ultimate Replay - Complete state based replay system

Discussion in 'Assets and Asset Store' started by scottyboy805, Jun 28, 2017.

  1. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Icon.png

    Asset Store | Documentation

    Want to try before you buy? Take a look at Ultimate Replay -Trial on the asset store!​

    Ultimate Replay is a complete state based replay system ideally suited to kill cams or action replay applications. Using Ultimate Replay you are able to record objects during game-play and then have them replay their actions at a later time. Due to the state based nature of the system, it is possible to view replays from any angle or even fly around the scene as playback occurs.

    Main.png

    Features
    • Quick and easy setup / integration into existing projects.
    • Simple API for replay and playback control means that very little scripting knowledge is required.
    • Uses a state based approach meaning that you can view playback from different camera angles or even fly around as playback occurs.
    • Full support for instantiation or destruction of objects during recording.
    • Fully interpolated playback means that you can record at ultra low frames rates(5fps and less) and retain smooth and accurate replays.
    • Supports playback at any speed from ultra-slow motion to 2 or 4x.
    • Supports reverse playback which can be used to produce a rewind effect.
    • Playback can be pause and resumed at a later date.
    • Full playback seek support allows you to jump to any point in a recording.
    • Full control over recording frame rate to make sure you capture the best quality recording at the smallest memory cost.
    • Recording an object is as simple as attaching a script.
    • Built-in support for transform recording.
    • Built-in support for audio recording.
    • Easily create your own component recorders to expand the capabilities.
    • Memory recording can be setup as continuous or as a rolling butter configuration.
    • ReplayVars allow script variables to be recorded simply by adding an attribute.
    • Get useful hints about the storage requirements for all replay objects.
    • Includes example GUI controls for playback manipulation.
    • Comprehensive .chm documentation of the API for quick and easy reference.
    • Fully commented C# source code included.

    Ultimate Replay is available on the Asset Store!​

     

    Attached Files:

    Last edited: Aug 4, 2017
    ZhavShaw likes this.
  2. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Ultimate Replay has now been submitted to the asset store and is currently pending review.
     
  3. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Ultimate Replay is now available on the asset store!
     
  4. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    I have added a demo video to the first post which shows some of the features of Ultimate Replay.
     
  5. The-Britain

    The-Britain

    Joined:
    Mar 31, 2015
    Posts:
    714
    How hard would it be to style a Prince of Persia time rewind game using this?
     
  6. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    That should be fairly easy to achieve. I take it you just want to rewind the player character? If so then you can just make the character a replay object and record using a rolling memory buffer to keep the last X amount of seconds of recording. You can then rewind the player whenever you need to. Animation would take a little more work but is still achievable. We are currently waiting for a trial version of Ultimate Replay to be released which should be very soon so it may be worth having a play around when it is released.
     
  7. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    We have now released a trial version of Ultimate Replay so you can try before you buy. You can get it for free on the asset store here.

    As it is a trial version it is not meant for use in finished products and has some limitations:
    • Source code is not included.
    • Some features may be disabled or have reduced functionality.
    • Will not work in standalone players (Editor only).
    We will still offer full support including feature requests, bug reports and general support for this version.
     
  8. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Ultimate Replay 1.0.1 has been submitted to the asset store for review and should be available within a few days.

    This update includes a beta version of the ReplayFileTarget which can be used to stream recordings to and from file. It has been released as a beta version as requested by a number of users and it still under development to improve a number of aspects.

    At the minute, the ReplayFileTarget is not fully optimized and there is quite a bit of room for improvement in both the performance and file size aspects. We will soon be looking into chunk prediction fetching to prevent the slight buffering effect you may see during playback. We will then look into file compression along with wasteful storage so that data is not stored if nothing has changed.

    During our testing we were able to record 300 objects transforms at a record rate of 48 fps for a period of 5 minutes which resulted in a file size of approximately 100mb. Of course this is an extreme record rate and not likely to be used in the real world as you can get away with record rates as low as 6fps without noticing any measurabe difference. We will however be striving to reduce that amount in the future but for now we think it is not too bad :)

    If you are using the trial version of Ultimate Replay then the ReplayFileTarget will be accessible upon import however the recording length will be limited to 5 minutes. If you are using the full version you will need to add a pre-processor define symbol to your project called 'ULTIMATEREPLAY_EXPERIMENTAL' in order to enable the ReplayFileTarget.

    If you do find any bugs or strange behavior do please let us know so we can get them fixed. (Contact info on first post). Also feel free to let us know of any improvements in general that you think could be made.
     
    Last edited: Sep 7, 2017
  9. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    The asset store team seem to be on form as they have already verified the update. Give it a try and let us know what you think!
     
  10. mertakbal

    mertakbal

    Joined:
    Jun 19, 2013
    Posts:
    9
    hi trivial interactive people,
    I have the full version of Ultimate Replay. I was eagerly waiting for the ReplayFileTarget feature. Just downloaded the new release and have following issues:
    - I opened ReplayFileTargetTest scene from Experimental folder. From the ReplayFileTarget Script on Replay Manager object I get the yellow warning "The associated script can not be loaded. Please fix any compile errors and assign a valid script." The mentioned scripts codes are almost completely commented out. Shall I uncomment them first?

    - As you recommend above as a full version owner I should "need to add a pre-processor define symbol to your project called 'ULTIMATEREPLAY_EXPERIMENTAL' in order to enable the ReplayFileTarget." Unfortunately I dont know how to do this.

    - If I solve the issues above, I would like to know where the stream record/read file is located and whether this file can be opened by a default csv/xml/json or any other kind of text/data editor?

    Thank you in advance
    Mert
     
  11. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    The ReplayFileTarget is disabled by default because it is still in beta and adding a pre-processor define symbol will enable the scripts. You can do this by going to 'Edit->Project Settings->Player' and looking for the field called 'Scripting Define Symbols' under the 'Configuration' header. Simply enter 'ULTIMATEREPLAY_EXPERIMENTAL' into that field and Unity will recompile the scripts and the ReplayFileTarget should be activated.

    The location of the replay file can be set in the inspector or via a script so you can have full control over that. Also it will not be possible to open the file in a text editor as it is a binary file for best recording and streaming performance.
     
  12. mertakbal

    mertakbal

    Joined:
    Jun 19, 2013
    Posts:
    9
    Unfortunately after adding the 'ULTIMATEREPLAY_EXPERIMENTAL' to 'Scripting Define Symbols', I still get the warning.

    upload_2017-9-11_11-2-17.png
     
  13. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    I just tried it and it did not work straight away for me either. I had to change some code in the project and then switch back to Unity and then it updated the script reference. I guess that the code needs to be changed in order for Unity to recompile and reload the scripts.
     
  14. mertakbal

    mertakbal

    Joined:
    Jun 19, 2013
    Posts:
    9
    I see. It would be great, if you could share the changes or make a new update available in the asset store.
    Best wishes
     
  15. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    As soon as it is out of beta it will be included in the main package without having to do anything :)
     
  16. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.0.2 of UltimateReplay has been submitted to the asset store.

    This version includes some minor bug fixes including:
    • Fixed a bug in ReplayFileTarget which would sometimes cause an IOException because the stream is not writable.
    • Fixed a NullReferenceException when creating a ReplayManager via script.
    • A few other small fixes.
    The trial version will now display an error when trying to build a release version to say that it is not supported as opposed to failing with an ArgumentException.
     
  17. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.0.3 has been submitted to the asset store. This version includes:
    • ReplayAnimator component (Experimental)
    • More optimized ReplayTransform which now includes a LowPrecision setting which will store the transform with lower accuracy and half the size.
    • A few other small bug fixes.
    The ReplayAnimator as you might have guessed is designed to record and replay an Animator component so you are able to record and replay animations in your game. At the minute it is in beta and will continue to be worked on and does not support all features of the Animator yet such as cross fading.
     
  18. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Hello, I have the full version of this plugin and I'm trying to setup a very simple recording of a ball being instantiated and then moving. I'm getting an error whenever I run ReplayManager.BeginPlayback(true);

    Error:
    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. UltimateReplay.Core.DefaultReplayPreparer.PrepareComponentForPlayback (UnityEngine.Component component) (at Assets/UltimateReplay/Scripts/Core/DefaultReplayPreparer.cs:69)
    3. UltimateReplay.Core.DefaultReplayPreparer.PrepareForPlayback (UltimateReplay.ReplayObject replayObject) (at Assets/UltimateReplay/Scripts/Core/DefaultReplayPreparer.cs:40)
    4. UltimateReplay.Core.ReplayScene.RegisterReplayObject (UltimateReplay.ReplayObject replayObject) (at Assets/UltimateReplay/Scripts/Core/ReplayScene.cs:68)
    5. UltimateReplay.ReplayObject.Awake () (at Assets/UltimateReplay/Scripts/ReplayObject.cs:74)
    6. UnityEngine.Object:Instantiate(GameObject, Vector3, Quaternion)
    7. UltimateReplay.ReplayManager:ReplayInstantiate(GameObject, Vector3, Quaternion) (at Assets/UltimateReplay/Scripts/ReplayManager.cs:933)
    8. UltimateReplay.Storage.ReplaySnapshot:RestoreReplayObjects(ReplayScene) (at Assets/UltimateReplay/Scripts/Storage/ReplaySnapshot.cs:439)
    9. UltimateReplay.Core.ReplayScene:RestoreSnapshot(ReplaySnapshot) (at Assets/UltimateReplay/Scripts/Core/ReplayScene.cs:174)
    10. UltimateReplay.ReplayManager:SetPlaybackFrame(Single, PlaybackOrigin) (at Assets/UltimateReplay/Scripts/ReplayManager.cs:628)
    11. UltimateReplay.ReplayManager:BeginPlayback(Boolean, PlaybackDirection) (at Assets/UltimateReplay/Scripts/ReplayManager.cs:742)
    12. ReplayScript:PlayButton() (at Assets/Scripts/SkillsChallengeScripts/ReplayScript.cs:91)
    13. ReplayScript:<Start>m__5() (at Assets/Scripts/SkillsChallengeScripts/ReplayScript.cs:39)
    14. UnityEngine.EventSystems.EventSystem:Update()
    15.  
    Is this a known issue? or am I messing something?
     
  19. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi, We have not seen that error before but it seems like a null component reference is getting sent to the replay system for some reason. Looking at the code where the error is generated, I cant see how a null reference exception can be thrown because all the components come from 'gameObject.GetComponentsInChildren'. What components do you have attached to the object you want to record? A screenshot of the inspector with the object selected would be very useful if possible.
     
    Last edited: Oct 13, 2017
  20. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Ball.JPG
    The transform is the only thing I need recorded, and its instantiation into the world. It is one of the prefab elements in the replay manager

    *Edit: I was able to get it to stop the error by deleting the render trail that wasnt being used.
    I'm still having issues with getting the playback to work. Doesnt seem to want to play anything.
     
    Last edited: Oct 13, 2017
  21. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    When I run ReplayManager.BeginPlayback(true); I can see some of the objects I recorded show up in the Hierarchy, but the objects are in strange static locations with absolutely no movement.
     
  22. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Thanks for the screenshot. I have done a bit of testing and all the built in components work fine on our end. Obviously we cant test the scripts you have attached though but they should not cause a problem. Do you add or destroy any of the scripts in either 'Awake' or 'Start'?

    I expect the previous error is causing the position of the object to not be set by the replay system. If we fix the error you are getting then I expect that the object will have its correct position set.

    Could you try adding the following code before line 69 of the 'DefaultReplayPreparer' class located at 'Assets/UltimateReplay/Scripts/Core/' and see if the error goes away. I suspect the way that Unity implements the '==' operator may have something to do with it:

    Code (CSharp):
    1. if (component == null) return;
     
    Last edited: Oct 13, 2017
  23. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    I am no longer getting the error.
    Now I'm just having trouble getting the ball to move. I attached the scripts to my camera and that mostly works, but that is already in the scene and is never deleted.
    It is not working for the ball. I can see it getting instantiated to a weird position by the replay manager, but it never moves.

    I also noticed its not getting instantiated under its original parent
     
  24. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Would it be possible to send me the project or an equivalent project that has the same error to info@trivialinteractive.co.uk. it is very difficult to help without being able to actually see how everything is setup.

    Yes, replay objects are not instantiated under the original parent because a lot more information about the hierarchy would also need to be stored.
     
  25. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    I sent a test project to that email.
     
  26. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Great, I will take a look and get back to you.
     
  27. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    A quick question while you look at that. Does this plugin support saving replays to a list? The game I'm working on is a golf game and Id like to be able to open a list of previous shots I've taking during that session (no need to save to file) and play specific ones.
     
  28. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    The replay system uses targets to save recorded replay information. The ReplayManager has an active target which you can change to cause the recording to be stored in the target that you specify so you can achieve what you want using a list of ReplayMemoryTarget objects and by simply setting the active target of the replay manager whenever you need.
     
  29. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Hmmmm. I don't think I'm understanding the ReplayMemoryTarget system.
    Currenty I have that script attached to an empty gameObject along with the ReplayManager. Are you saying I need a new instance of the ReplayMemoryTarget script for each shot I want to save?
     
  30. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Yes you will need a ReplayMemoryTarget for every replay you want to record. You can then set the ReplayManagers active target to whichever one of those memory targets you want to record to or playback.
     
  31. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    So I deleted the ReplayMemoryTarget that was in the scene since I have to do this programmatically anyways and now I have something like this instead:
    Code (CSharp):
    1. ReplayTarget replayTarget = new ReplayMemoryTarget();
    2. ReplayManager.Target = replayTarget;
    How do I change the Record Seconds? Its exposed to the editor, which I can't use, but I don't seem to have access to it from the code.
     
  32. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    You are storing the new ReplayMemoryTarget as the base ReplayTarget class so information specific to the ReplayMemoryTarget class is not accessible. Simply define the variable as a ReplayMemoryTarget like so and you will be able to access the record seconds:

    Code (CSharp):
    1. ReplayMemoryTarget replayTarget = gameObject.AddComponent<ReplayMemoryTarget>();
    2. replayTarget.recordSeconds = 5;
    3. ReplayManager.Target = replayTarget;
    Also, the ReplayMemoryTarget is a mono behaviour so needs to be created using 'AddComponent' instead of using 'new'.
     
    Last edited: Oct 16, 2017
  33. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    @fssdev I have had a good look at the project you sent and have managed to get the ball to record properly. It turned out to be a bug which caused the replay id for some replay components to not be stored so when the replay system wanted to re position objects in the scene, it could not find them using their ID.

    It also looks like you want to record a number of other objects but some of them are not setup correctly. For example, your 'SCTarget' object has a ReplayTransform component so I assume you want to record it but it looks like it is dynamically created and destroyed a number of times which is fine, however in order for it to be recorded properly in the replay it needs to either stay the same object so the id does not change or be instantiated during recording. Note that it should also be marked as a replay prefab if using the second option.

    I have emailed you a link where you can download the project with the changes. Let me know if you need help to record any other objects as it may not be straight forward since you create and destroy a few objects dynamically.
     
  34. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.0.4 has been submitted to the asset store. This version includes:
    • Fixed a bug that caused dynamically instantiated replay objects to have their observed component identities regenerated causing the components to not receive the replay data they should.
    • Changed the way dynamically spawned replay objects are created so that their position, rotation and scale are restored.
    Thanks to @fssdev for helping us find this issue.
     
  35. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    So my logic flow in code for use of this plugin is this:
    Code (CSharp):
    1. shotData.replayTarget = GameObject.Find("ReplayManager").AddComponent<ReplayMemoryTarget>(); //Add all replays to a single component, save a reference to each
    2. shotData.replayTarget.recordSeconds = 30;
    3. ReplayManager.Target = shotData.replayTarget; //set the newly made replay as the target
    4.  
    5. ReplayManager.BeginRecording(true);
    6. //hit a ball
    7. ReplayManager.StopRecording();
    8.  
    9. //now I want to recall a replay
    10. ReplayManager.Target = gameScript.savedShotDataList[0].replayTarget; //grab what we know is there for testing
    11.  
    12. ReplayManager.BeginPlayback(true); // nothing happens
    Its as if the ReplayMemoryTarget is not recording or not able to recall its recording.
     
  36. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    You don't show any code that indicates that you ever record anything to 'savedShotData[0].replayTarget'. Are you sure that it contains recorded data? IE: you record to that target previously and is not shown in the code you posted. If you don't record to that memory target then the recording length will be 0 and will cause playback to end immediately which may be what you are experiencing.
     
  37. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Above that code I am doing this:
    Code (CSharp):
    1. savedShotDataList.Add(shotData);
    I think this is the part where I'm getting lost.
    So I thought in line 3, I'm setting the record target. So all I have to do is record start/stop and its saved to that target, correct? I have a reference to that target in savedShotDataList[0].replayTarget, so I set that as the RecordManager target and BeginPlayback.
    Am I missing the idea?
     
  38. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    OK, I understand the setup a bit better now. In theory that should work so something must be going wrong in the process. In the code where you have a comment '//hit a ball', I assume that 'StopRecording' is only called after a period of time has passed and not straight after the 'BeginRecording' call. Also it may be useful to print out the duration and memory size of the target to see if it actually contains any data:

    Code (CSharp):
    1. ReplayMemoryTarget target = // Find target
    2.  
    3. Debug.Log(target.Duration);
    4. Debug.Log(target.MemorySize);
     
  39. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    @fssdev You also point out a useful use case for a memory target that can store multiple recordings. We may look into creating a specific recording target to handle this problem to make our asset easier to use.
     
  40. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    I think I see where I messed up.
    Code (CSharp):
    1. ReplayManager.Target = shotData.replayTarget; //set the newly made replay as the target
    I'm creating the ReplayMemoryTarget and then setting it to the replayManager, but I never put that reference back into the list I created.
    What I would need to do is this:
    Code (CSharp):
    1. shotData.replayTarget = ReplayManager.Target;
    But that is not possible because ReplayManager.Target returns a ReplayTarget, not a ReplayMemoryTarget.
     
  41. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    'shotData.replayTarget' already contains the new reference to the memory target so you shouldn't need to update it again so I doubt that it is the problem. BTW you can cast the replay target that the manager returns like so:

    Code (CSharp):
    1. // Like this
    2. ReplayMemoryTarget target = (ReplayMemoryTarget)ReplayManager.Target;
    3.  
    4. // Or even better
    5. target = ReplayManager.Target as ReplayMemoryTarget;
     
  42. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Hmmm, yeah I tried casting. Nothing I do seems to work. The data will not save. Can you try this on your end?
     
  43. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    It is late now (UK) but I will take a look for you first thing in the morning. If I get enough time I may also look at implementing a dedicated memory target that can store any number of recordings.
     
  44. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    The new memory target system you sent seems to be working, but I'm still struggling to get the ball to replay in my main scene. Its instantiating in the scene, but thats about it.
     
  45. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Glad the replay target is working out for you.

    Did you get the project link I emailed you containing the changes and bug fix? The ball was replaying fine for me in that project after we fixed the bug in the replay system.
     
  46. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Unfortunately its too costly to maintain that test project, I had to go back to the main project. The only difference between the two regarding this though is the Hierarchy is different. I'm not sure why that would have such a big affect on the replay system
     
  47. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    OK, Have you downloaded the latest version of UltimateReplay from the asset store because it contains a bug fix that we found using your project.
     
  48. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    I have the latest.
    I think you mentioned something about this problem above, I'll read through again to see if I can find it. Its the issue where the ball instantiates in an odd place in the world and never moves.
     
  49. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    One thing we did change in your game code was to begin recording before you instantiate the golf ball when the player is taking a shot. Maybe give that a try also.
     
  50. fssdev

    fssdev

    Joined:
    Jan 16, 2017
    Posts:
    49
    Yep, that was it. I knew you had mentioned something like that before, I think it was in the email.