Netcode Bootstrap

This commit is contained in:
Luis Gonzalez
2026-05-31 14:27:52 -07:00
parent 99d8d2d2a9
commit 7fa77ce821
1813 changed files with 2921554 additions and 84 deletions
@@ -0,0 +1,61 @@
using Unity.Collections;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.WaybackMachine
{
public struct AnimationEventHistoryData
{
public FixedString32Bytes name;
public FixedString32Bytes stringParam;
public int frameIndex;
public uint nameHash;
public float floatParam;
public int intParam;
public uint stringParamHash;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public AnimationEventHistoryData(in AnimationEventComponent aec, int frameIndex)
{
#if RUKHANKA_DEBUG_INFO
name = aec.name;
stringParam = aec.stringParam;
#else
name = default;
stringParam = default;
#endif
nameHash = aec.nameHash;
floatParam = aec.floatParam;
intParam = aec.intParam;
stringParamHash = aec.stringParamHash;
this.frameIndex = frameIndex;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetName()
{
#if RUKHANKA_DEBUG_INFO
return name.ToString();
#else
return $"{nameHash}";
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetStringParam()
{
#if RUKHANKA_DEBUG_INFO
return stringParam.ToString();
#else
return $"{stringParamHash}";
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: db90f13b072970248951f3c66931feda
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/AnimationEventHistoryData.cs
uploadId: 897522
@@ -0,0 +1,111 @@
using System;
using Rukhanka.Toolbox;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Mathematics;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.WaybackMachine
{
public struct HistoryValue
{
public float value;
public int frameIndex;
}
//---------------------------------------------------------------------------------------//
[BurstCompile]
public struct AnimationHistoryData: IDisposable
{
public FixedString128Bytes animationName;
public int2 frameSpan;
public Hash128 animationHash;
public Hash128 avatarMaskHash;
public AnimationBlendingMode blendMode;
public float layerWeight;
public int layerIndex;
public uint motionId;
public UnsafeList<HistoryValue> historyWeights;
public UnsafeList<HistoryValue> historyAnimTime;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public AnimationHistoryData(in AnimationToProcessComponent atp, int frameIndex)
{
frameSpan = new int2(frameIndex, frameIndex);
animationHash = atp.animation.IsCreated ? atp.animation.Value.hash : new Hash128();
avatarMaskHash = atp.avatarMask.IsCreated ? atp.avatarMask.Value.hash : new Hash128();
blendMode = atp.blendMode;
layerWeight = atp.layerWeight;
layerIndex = atp.layerIndex;
motionId = atp.motionId;
historyWeights = default;
historyAnimTime = default;
animationName = default;
#if RUKHANKA_DEBUG_INFO
if (atp.animation.IsCreated)
{
atp.animation.Value.name.CopyToWithTruncate(ref animationName);
}
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Hash128 ComputeHash()
{
var hasher = new xxHash3.StreamingState(false, 0xaabbccdd);
hasher.Update(animationHash);
hasher.Update(avatarMaskHash);
hasher.Update(blendMode);
hasher.Update(layerIndex);
hasher.Update(layerWeight);
hasher.Update(motionId);
return new Hash128(hasher.DigestHash128());
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Dispose()
{
historyWeights.Dispose();
historyAnimTime.Dispose();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[BurstCompile]
public static float GetHistoryValueForFrame(in UnsafeList<HistoryValue> hvs, int frameIndex)
{
if (hvs.Length == 0)
return 0;
var rv = hvs[0].value;
for (int i = 0; i < hvs.Length; ++i)
{
var hv = hvs[i];
rv = hv.value;
if (hv.frameIndex >= frameIndex)
break;
}
return rv;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetName()
{
#if RUKHANKA_DEBUG_INFO
return animationName.ToString();
#else
return $"{animationHash}";
#endif
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 69ef9f23f2e5f1740b74b1ee3a2aab44
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/AnimationHistoryData.cs
uploadId: 897522
@@ -0,0 +1,75 @@
using Rukhanka.Toolbox;
using Unity.Collections;
using Unity.Mathematics;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.WaybackMachine
{
public struct AnimatorControllerStateHistoryData
{
public FixedString32Bytes name;
public int2 frameSpan;
public int layerIndex;
public int stateId;
public uint motionId;
public float weight;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public AnimatorControllerStateHistoryData(in AnimatorControllerLayerComponent aclc, int stateId, uint motionId, int frameIndex)
{
frameSpan = new (frameIndex, frameIndex);
weight = 1;
this.stateId = stateId;
this.layerIndex = aclc.layerIndex;
this.motionId = motionId;
ref var sb = ref aclc.controller.Value.layers[aclc.layerIndex].states[stateId];
name = default;
#if RUKHANKA_DEBUG_INFO
if (sb.name.Length > 0)
{
sb.name.CopyToWithTruncate(ref name);
}
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetName()
{
#if RUKHANKA_DEBUG_INFO
return name.ToString();
#else
return $"{stateId}";
#endif
}
}
//----------------------------------------------------------------------------------------------------------------//
public struct AnimatorControllerTransitionHistoryData
{
public FixedString64Bytes name;
public int2 frameSpan;
public int srcStateId;
public int dstStateId;
public int transitionId;
public int layerIndex;
public float2 weightRange;
public int srcStateDataIndex;
public int dstStateDataIndex;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetName()
{
#if RUKHANKA_DEBUG_INFO
return name.ToString();
#else
return $"{srcStateId}->{dstStateId}";
#endif
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0e3634df630fd8242828ce80f088b592
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/AnimatorControllerHistoryData.cs
uploadId: 897522
@@ -0,0 +1,51 @@
using Unity.Collections;
using Unity.Mathematics;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.WaybackMachine
{
public struct AnimatorEventHistoryData
{
public FixedString32Bytes name;
public int layerId;
public int stateId;
// History index of begin event for this event. -1 for state enter events
public int beginHistoryIndex;
public int2 frameRange;
public AnimatorControllerEventComponent.EventType eventType;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public AnimatorEventHistoryData(in AnimatorControllerEventComponent acec, int frameIndex)
{
name = default;
#if RUKHANKA_DEBUG_INFO
name = acec.stateName;
#endif
eventType = acec.eventType;
frameRange = new (frameIndex, frameIndex);
layerId = acec.layerId;
stateId = acec.stateId;
beginHistoryIndex = -1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public string GetName()
{
#if RUKHANKA_DEBUG_INFO
return name.ToString();
#else
var prefix = "";
if (eventType == AnimatorControllerEventComponent.EventType.StateEnter)
prefix = "Enter ";
if (eventType == AnimatorControllerEventComponent.EventType.StateExit)
prefix = "Exit ";
return $"{prefix}{layerId}:{stateId}";
#endif
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 25fb6d6e8df4db6499b010dce348b1b2
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/AnimatorEventHistoryData.cs
uploadId: 897522
@@ -0,0 +1,132 @@
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka.WaybackMachine
{
[BurstCompile]
public struct WaybackMachineData: IDisposable
{
public enum FPSMode
{
FPS120,
FPS60,
FPS30
}
public FPSMode fpsMode;
public int lastRecordedFrame;
public NativeList<AnimationHistoryData> animHistory;
public NativeList<AnimatorControllerStateHistoryData> controllerStateHistory;
public NativeList<AnimatorControllerTransitionHistoryData> controllerTransitionHistory;
public NativeList<AnimationEventHistoryData> animationEventHistory;
public NativeList<AnimatorEventHistoryData> animatorEventHistory;
public NativeList<AnimationEventComponent> emittedAnimationEvents;
public NativeList<AnimatorControllerEventComponent> emittedAnimatorEvents;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Clear()
{
foreach (var ah in animHistory)
{
ah.Dispose();
}
lastRecordedFrame = 0;
animHistory.Clear();
animationEventHistory.Clear();
animatorEventHistory.Clear();
controllerStateHistory.Clear();
controllerTransitionHistory.Clear();
EndFrame();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void EndFrame()
{
emittedAnimationEvents.Clear();
emittedAnimatorEvents.Clear();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Construct()
{
fpsMode = FPSMode.FPS60;
animHistory = new (0xff, Allocator.Persistent);
animationEventHistory = new (0xff, Allocator.Persistent);
animatorEventHistory = new (0xff, Allocator.Persistent);
controllerStateHistory = new (0xff, Allocator.Persistent);
controllerTransitionHistory = new (0xff, Allocator.Persistent);
emittedAnimationEvents = new (0xff, Allocator.Persistent);
emittedAnimatorEvents = new (0xff, Allocator.Persistent);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public float GetFrameDuration() => fpsMode switch
{
FPSMode.FPS30 => 1 / 30.0f,
FPSMode.FPS60 => 1 / 60.0f,
FPSMode.FPS120 => 1 / 120.0f,
_ => 1 / 60.0f
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public long GetDataSize()
{
var rv = 0L;
rv += animHistory.Length * UnsafeUtility.SizeOf<AnimationHistoryData>();
foreach (var ah in animHistory)
{
rv += ah.historyWeights.Length * UnsafeUtility.SizeOf<HistoryValue>();
rv += ah.historyAnimTime.Length * UnsafeUtility.SizeOf<HistoryValue>();
}
rv += controllerStateHistory.Length * UnsafeUtility.SizeOf<AnimatorControllerStateHistoryData>();
rv += controllerTransitionHistory.Length * UnsafeUtility.SizeOf<AnimatorControllerTransitionHistoryData>();
rv += animationEventHistory.Length * UnsafeUtility.SizeOf<AnimationEventHistoryData>();
rv += animatorEventHistory.Length * UnsafeUtility.SizeOf<AnimatorEventHistoryData>();
return rv;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Dispose()
{
foreach (var ah in animHistory)
{
ah.Dispose();
}
animHistory.Dispose();
animationEventHistory.Dispose();
animatorEventHistory.Dispose();
controllerStateHistory.Dispose();
controllerTransitionHistory.Dispose();
emittedAnimationEvents.Dispose();
emittedAnimatorEvents.Dispose();
}
}
//---------------------------------------------------------------------------------------//
public struct RecordComponent: IComponentData
{
public NativeReference<WaybackMachineData> wbData;
}
//---------------------------------------------------------------------------------------//
public struct PlaybackComponent: IComponentData
{
public NativeList<AnimationToProcessComponent> playbackData;
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 74b0c11583bee45488d703036960f3c9
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/WaybackMachineComponents.cs
uploadId: 897522
@@ -0,0 +1,39 @@
using Rukhanka.WaybackMachine;
using Unity.Burst;
using Unity.Entities;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
[DisableAutoCreation]
[UpdateAfter(typeof(AnimationCullingSystem))]
[UpdateBefore(typeof(AnimationEventEmitSystem))]
public partial struct WaybackMachinePlaybackSystem: ISystem
{
/////////////////////////////////////////////////////////////////////////////////////////////////////
[BurstCompile]
public void OnCreate(ref SystemState ss)
{
ss.RequireForUpdate<PlaybackComponent>();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
[BurstCompile]
public void OnUpdate(ref SystemState ss)
{
var pc = SystemAPI.GetSingleton<PlaybackComponent>();
var pce = SystemAPI.GetSingletonEntity<PlaybackComponent>();
if (!SystemAPI.HasBuffer<AnimationToProcessComponent>(pce))
return;
var atps = SystemAPI.GetBuffer<AnimationToProcessComponent>(pce);
atps.Clear();
atps.AddRange(pc.playbackData.AsArray());
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8aedb7e58c3175049833f483785cea1f
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/WaybackMachinePlaybackSystem.cs
uploadId: 897522
@@ -0,0 +1,281 @@
using Rukhanka.Toolbox;
using Rukhanka.WaybackMachine;
using Unity;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Mathematics;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
[DisableAutoCreation]
public partial struct WaybackMachineRecordSystem: ISystem, ISystemStartStop
{
int frameCounter;
/////////////////////////////////////////////////////////////////////////////////////////////////////
public void OnStartRunning(ref SystemState ss)
{
frameCounter = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
public void OnStopRunning(ref SystemState ss)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
[BurstCompile]
public void OnCreate(ref SystemState ss)
{
ss.RequireForUpdate<RecordComponent>();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimation(AnimationToProcessComponent atp, ref RecordComponent rc, int frameIndex)
{
var ahs = rc.wbData.Value.animHistory;
var curHistory = new AnimationHistoryData(atp, frameIndex);
// Search back for given animation in history
var foundIndex = -1;
for (var k = ahs.Length - 1; k >= 0; --k)
{
var ah = ahs[k];
if (ah.frameSpan.y + 1 != frameIndex)
continue;
if (ah.ComputeHash() == curHistory.ComputeHash())
{
foundIndex = k;
break;
}
}
if (foundIndex < 0)
{
foundIndex = ahs.Length;
curHistory.historyWeights = new (0xff, Allocator.Persistent);
curHistory.historyAnimTime = new (0xff, Allocator.Persistent);
ahs.Add(curHistory);
}
ref var historyElement = ref ahs.ElementAt(foundIndex);
historyElement.frameSpan.y = frameIndex;
var whv = new HistoryValue() { value = atp.weight, frameIndex = frameIndex };
historyElement.historyWeights.Add(whv);
var thv = new HistoryValue() { value = atp.time, frameIndex = frameIndex };
historyElement.historyAnimTime.Add(thv);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimationEvents(ref SystemState ss, Entity rce, ref RecordComponent rc)
{
if (!SystemAPI.HasBuffer<AnimationEventComponent>(rce))
return;
var animEvents = rc.wbData.Value.emittedAnimationEvents;
// Record animation events
for (var i = 0; i < animEvents.Length; ++i)
{
var aec = animEvents[i];
var ehd = new AnimationEventHistoryData(aec, frameCounter);
rc.wbData.Value.animationEventHistory.Add(ehd);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimations(ref SystemState ss, Entity rce, ref RecordComponent rc)
{
if (!SystemAPI.HasBuffer<AnimationToProcessComponent>(rce))
return;
var atps = SystemAPI.GetBuffer<AnimationToProcessComponent>(rce);
for (var i = 0; i < atps.Length; ++i)
{
var atp = atps[i];
RecordAnimation(atp, ref rc, frameCounter);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimatorTransition(in AnimatorControllerLayerComponent aclc, ref RecordComponent rc, int si, int di)
{
if (aclc.rtd.activeTransition.id < 0)
return;
ref var tb = ref aclc.controller.Value.layers[aclc.layerIndex].states[aclc.rtd.srcState.id].transitions[aclc.rtd.activeTransition.id];
var std = new AnimatorControllerTransitionHistoryData
{
frameSpan = new (frameCounter, frameCounter),
transitionId = aclc.rtd.activeTransition.id,
layerIndex = aclc.layerIndex,
dstStateId = aclc.rtd.dstState.id,
srcStateId = aclc.rtd.srcState.id,
weightRange = new float2(1) * aclc.rtd.activeTransition.normalizedDuration
};
var cth = rc.wbData.Value.controllerTransitionHistory;
// Search for existing entry in history
var i = cth.Length - 1;
for (; i >= 0; --i)
{
var ct = cth[i];
if (ct.srcStateId == std.srcStateId && ct.dstStateId == std.dstStateId && ct.frameSpan.y + 1 == frameCounter && std.layerIndex == ct.layerIndex)
break;
}
// If not found create new entry
if (i < 0)
{
i = cth.Length;
#if RUKHANKA_DEBUG_INFO
tb.name.CopyToWithTruncate(ref std.name);
#endif
cth.Add(std);
}
ref var csv = ref cth.ElementAt(i);
// If found update existing entry
csv.frameSpan.y = frameCounter;
csv.weightRange.y = aclc.rtd.activeTransition.normalizedDuration;
csv.srcStateDataIndex = si;
csv.dstStateDataIndex = di;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
int RecordAnimatorState(in AnimatorControllerLayerComponent aclc, int stateId, uint motionId, ref RecordComponent rc)
{
if (stateId < 0)
return -1;
var shd = new AnimatorControllerStateHistoryData(aclc, stateId, motionId, frameCounter);
var csh = rc.wbData.Value.controllerStateHistory;
// Search for existing entry in history
var i = csh.Length - 1;
for (; i >= 0; --i)
{
var cs = csh[i];
if (cs.stateId == shd.stateId &&
cs.frameSpan.y + 1 == frameCounter &&
cs.layerIndex == shd.layerIndex &&
cs.motionId == shd.motionId)
break;
}
// If not found create new entry
if (i < 0)
{
i = csh.Length;
csh.Add(shd);
}
ref var csv = ref csh.ElementAt(i);
// If found update existing entry
csv.frameSpan.y = frameCounter;
return i;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimatorStates(ref SystemState ss, Entity rce, ref RecordComponent rc)
{
if (!SystemAPI.HasBuffer<AnimatorControllerLayerComponent>(rce))
return;
var aclcs = SystemAPI.GetBuffer<AnimatorControllerLayerComponent>(rce);
for (var i = 0; i < aclcs.Length; ++i)
{
var aclc = aclcs[i];
var srcStateDataIndex = RecordAnimatorState(aclc, aclc.rtd.srcState.id, aclc.rtd.srcState.motionId, ref rc);
var dstStateDataIndex = RecordAnimatorState(aclc, aclc.rtd.dstState.id, aclc.rtd.dstState.motionId, ref rc);
RecordAnimatorTransition(aclc, ref rc, srcStateDataIndex, dstStateDataIndex);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
void RecordAnimatorEvents(ref SystemState ss, Entity rce, ref RecordComponent rc)
{
if (!SystemAPI.HasBuffer<AnimatorControllerEventComponent>(rce))
return;
var acecs = rc.wbData.Value.emittedAnimatorEvents;
for (var i = 0; i < acecs.Length; ++i)
{
var acec = acecs[i];
var aehd = new AnimatorEventHistoryData(acec, frameCounter);
var k = -1;
// For every frame update events append it to the previous to make continuous span
if (aehd.eventType == AnimatorControllerEventComponent.EventType.StateUpdate)
{
k = rc.wbData.Value.animatorEventHistory.Length - 1;
for (; k >= 0; --k)
{
ref var hd = ref rc.wbData.Value.animatorEventHistory.ElementAt(k);
if (hd.stateId == aehd.stateId && hd.layerId == aehd.layerId && hd.eventType == AnimatorControllerEventComponent.EventType.StateUpdate)
{
hd.frameRange.y = frameCounter;
break;
}
}
}
// Find begin event for this event
if (aehd.eventType != AnimatorControllerEventComponent.EventType.StateEnter)
{
var l = rc.wbData.Value.animatorEventHistory.Length - 1;
for (; l >= 0; --l)
{
ref var hd = ref rc.wbData.Value.animatorEventHistory.ElementAt(l);
if (hd.stateId == aehd.stateId && hd.layerId == aehd.layerId && hd.eventType == AnimatorControllerEventComponent.EventType.StateEnter)
break;
}
if (l >= 0)
aehd.beginHistoryIndex = l;
}
// If previous update event was not found, or we are dealing with other event type - add new entry
if (k < 0)
{
rc.wbData.Value.animatorEventHistory.Add(aehd);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
[BurstCompile]
public unsafe void OnUpdate(ref SystemState ss)
{
var rcd = SystemAPI.GetSingletonRW<RecordComponent>();
var rce = SystemAPI.GetSingletonEntity<RecordComponent>();
ref var rc = ref rcd.ValueRW;
var ptr = rc.wbData.GetUnsafePtr();
ptr->lastRecordedFrame = frameCounter;
RecordAnimatorStates(ref ss, rce, ref rc);
RecordAnimationEvents(ref ss, rce, ref rc);
RecordAnimatorEvents(ref ss, rce, ref rc);
RecordAnimations(ref ss, rce, ref rc);
frameCounter++;
rcd.ValueRW.wbData.Value.EndFrame();
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 729c69f8b5d43634e94eaf6c7349836a
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/WaybackMachineRecordSystem.cs
uploadId: 897522
@@ -0,0 +1,18 @@
using Unity.Entities;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
[DisableAutoCreation]
[UpdateAfter(typeof(AnimationApplicationSystem))]
public partial class WaybackMachineRecordSystemGroup: ComponentSystemGroup
{
protected override void OnCreate()
{
base.OnCreate();
RateManager = new RateUtils.FixedRateCatchUpManager(1 / 60.0f);
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: abe7a9fbde95e53458f3d843255da216
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/WaybackMachine/WaybackMachineRecordSystemGroup.cs
uploadId: 897522