/// <summary> /// 编码成AnimationCurve /// </summary> /// <param name="clip"></param> /// <param name="curve"></param> public void encodeData(CompressedClipData clip, AnimationCurve curve) { List <Keyframe> keys = new List <Keyframe>(curve.keys); deleteOverframe(clip.frameRate, keys); EncodeFrames(clip, curve, keys); }
/// <summary> /// 编码成AnimationCurve /// </summary> /// <param name="clip"></param> /// <param name="curve"></param> public void encodeData(CompressedClipData clip, AnimationCurve curve, ValueMode valueMode, bool tan) { float maxTime = clip.length; float time = clip.length; float frameRate = clip.frameRate; List <Keyframe> keys = new List <Keyframe>(curve.keys); deleteOverframe(frameRate, keys); var length = keys.Count; //keysData = new uint[length]; if (valueMode == ValueMode.Byte1) { keysValueByte = new byte[length]; } else { keysValueByte = new byte[length * 2]; } if (tan) { keysTans = new float[length]; } //计算最大值和最小值 valueMin = float.MaxValue; valueMax = float.MinValue; for (int i = 0; i < length; i++) { var key = keys[i]; valueMin = Mathf.Min(valueMin, key.value); valueMax = Mathf.Max(valueMax, key.value); } int timeBytes = Mathf.CeilToInt((time * frameRate + 1) / 8); keysTime = new byte[timeBytes]; float valueSize = valueMax - valueMin; //编码时间和关键帧值 for (int i = 0; i < length; i++) { var key = keys[i]; //时间 int keyIndex = Mathf.RoundToInt(key.time * frameRate); int byteIndex = keyIndex / 8; int byteBit = keyIndex % 8; byte keysTimeByte = keysTime[byteIndex]; keysTime[byteIndex] |= (byte)(1 << byteBit); encodBytes(keysValueByte, valueMode, i, ref key); if (tan) { keysTans[i] = key.inTangent; } } this.valueMode = (byte)valueMode; encodeDebugData(keys); }
protected virtual void InitEncode(CompressedClipData clip, AnimationCurve curve, List <Keyframe> keys) { //计算最大值和最小值 valueMin = float.MaxValue; valueMax = float.MinValue; var keysCount = keys.Count; for (int i = 0; i < keysCount; i++) { var key = keys[i]; valueMin = Mathf.Min(valueMin, key.value); valueMax = Mathf.Max(valueMax, key.value); } this.keysValueByte = new byte[keysCount]; }
//压缩曲线数据 void CompressCurveData(CompressedClipData compressingData, EditorCurveBinding binding) { if (binding.isPPtrCurve) { //属性帧不压缩,还原到stubClip里 var keyframes = AnimationUtility.GetObjectReferenceCurve(rawClip, binding); AnimationUtility.SetObjectReferenceCurve(stubClip, binding, keyframes); } else if (UncompressFields.Contains(binding.propertyName)) { //白名单内的属性也不压缩 var curve = AnimationUtility.GetEditorCurve(rawClip, binding); AnimationUtility.SetEditorCurve(stubClip, binding, curve); } else { //从共享数据里获取字段ID var propertyId = shareData.getFieldIndex(binding.path, binding.type.FullName, binding.propertyName); // var curve = AnimationUtility.GetEditorCurve(rawClip, binding);// curves[i]; //检测是否需要存储切线数据 bool needStoreTanData = false; if (stateFlag && stateFlag.rotationTan && binding.propertyName.StartsWith("m_LocalRotation.")) { needStoreTanData = true; } //选择不同的存储方式 CurveDataBasicValues curveData; if (needStoreTanData) { var storeTanData = new CurveDataStoreTan(); compressingData.curvesStoreTan.Add(storeTanData); curveData = storeTanData; } else { var calcTanData = new CurveDataCalcTan(); compressingData.curvesCalcTan.Add(calcTanData); curveData = calcTanData; } curveData.initProperty(propertyId, binding.path, binding.type.FullName, binding.propertyName); curveData.encodeData(compressingData, curve); stateMachineFields.Add(binding); } }
//压缩Clip数据 public CompressedClipData CompressClipData() { CompressedClipData compressingData = ScriptableObject.CreateInstance <CompressedClipData>(); compressingData.name = rawClip.name + "_data"; compressingData.length = rawClip.length; compressingData.wrapMode = (byte)rawClip.wrapMode; compressingData.frameRate = (byte)rawClip.frameRate; //data.shareData = shareData; EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(rawClip); for (int i = 0; i < bindings.Length; i++) { CompressCurveData(compressingData, bindings[i]); } compressingData.shareData = shareData; EditorUtility.SetDirty(shareData); return(compressingData); }
protected virtual void EncodeFrames(CompressedClipData clip, AnimationCurve curve, List <Keyframe> keyframes) { float maxTime = clip.length; float clipLength = clip.length; float frameRate = clip.frameRate; var keysCount = keyframes.Count; InitEncode(clip, curve, keyframes); initFramesTime(clipLength, frameRate); //编码时间和关键帧值 for (int keyIndex = 0; keyIndex < keysCount; keyIndex++) { var keyframe = keyframes[keyIndex]; EncodeFrameTime(keysTime, keyIndex, frameRate, keyframe.time); EncodeFrameValue(keyIndex, ref keyframe); } encodeDebugData(keyframes); }
//解码动画曲线 public virtual AnimationCurve decodeData(CompressedClipData clip) { float maxTime = clip.length; AnimationCurve curve = new AnimationCurve(); var length = keysValueByte.Length; // float ValueMax = valueMode == ValueMode.Byte1 ? byte.MaxValue : ushort.MaxValue; var keys = new Keyframe[length]; for (int i = 0; i < length; i++) { Keyframe key = new Keyframe(); DecodeFrame(i, ref key); keys[i] = key; } decodeTime(clip, keys); decodeDebugData(keys); curve.keys = keys; SmoothTangents(curve, length); return(curve); }
//解码动画曲线 public AnimationCurve decodeData(CompressedClipData clip) { float maxTime = clip.length; ValueMode valueMode = (ValueMode)this.valueMode; AnimationCurve curve = new AnimationCurve(); var length = keysValueByte.Length; if (valueMode == ValueMode.Byte2 || valueMode == ValueMode.ValueTan) { length = length / 2; } // float ValueMax = valueMode == ValueMode.Byte1 ? byte.MaxValue : ushort.MaxValue; var keys = new Keyframe[length]; bool tansData = keysTans != null && keysTans.Length > 0; for (int i = 0; i < length; i++) { Keyframe key = new Keyframe(); decodeBytes(keysValueByte, valueMode, i, ref key); if (tansData) { key.inTangent = keysTans[i]; key.outTangent = keysTans[i]; } keys[i] = key; } decodeTime(clip, keys); decodeDebugData(keys); curve.keys = keys; if (valueMode != ValueMode.ValueTan && !tansData) { for (int i = 0; i < length; i++) { curve.SmoothTangents(i, 0f); } } return(curve); }
//解码时间信息 void decodeTime(CompressedClipData clip, Keyframe[] keys) { float frameRate = clip.frameRate; for (int i = 0, idx = 0; i < keysTime.Length; i++) { byte timeBits = keysTime[i]; for (int j = 0; j < 8; j++) { if (((timeBits >> j) & 1) != 0) { if (keys.Length <= idx) { Debug.LogError("解码动画数据异常:帧时间索引:" + idx + " 当前帧:" + (i * 8 + j) + " 动画名称:" + clip.name + " 曲线:" + property); } else { keys[idx++].time = (i * 8 + j) / frameRate; } } } } }
public string Process() { this.rawClip = animatorState.motion as AnimationClip; if (!rawClip) { return(null); } this.stateFlag = findStateFlag(animatorState); //查找标记,检查是否可以跳过 if (stateFlag && stateFlag.skipCompressed) { return(null); } var size = UnityEngine.Profiler.GetRuntimeMemorySize(rawClip); //小于16K 不压缩 if (size < 1024 * 16) { return(null); } string rawClipPath = AssetDatabase.GetAssetPath(rawClip); if (string.IsNullOrEmpty(rawClipPath)) { return(null); } string anim_gen_dir = Path.GetDirectoryName(rawClipPath) + "/_anim_gen_"; string dataDir = anim_gen_dir + "/datas"; string stubDir = anim_gen_dir + "/stubs"; Directory.CreateDirectory(anim_gen_dir); Directory.CreateDirectory(dataDir); Directory.CreateDirectory(stubDir); this.shareData = getShareData(anim_gen_dir); this.stubClip = new AnimationClip(); AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(rawClip); stubClip.SetCurve("", typeof(CompressedAnimationDirver), "stubAnimParam", AnimationCurve.Linear(0, 0, rawClip.length, 1)); stubClip.name = rawClip.name + "_stub"; this.clipData = CompressClipData(); AnimationUtility.SetAnimationClipSettings(stubClip, settings); //*注意:这里是为了兼容通过AnimationClipSettings设置Loop而Wrap没设置 if (settings.loopTime) { clipData.wrapMode = (byte)WrapMode.Loop; stubClip.wrapMode = WrapMode.Loop; } else { stubClip.wrapMode = rawClip.wrapMode; } animatorState.motion = stubClip; AssetDatabase.CreateAsset(stubClip, stubDir + "/" + stubClip.name + ".anim"); string dataPath = dataDir + "/" + clipData.name + ".asset"; AssetDatabase.CreateAsset(clipData, dataPath); var stateProxy = animatorState.AddStateMachineBehaviour <CompressionAnimatorStateProxy>(); stateProxy.data = clipData; return(dataPath); }
internal void DoStateEnter(Animator animator, ref AnimatorStateInfo stateInfo, CompressedClipData data) { if (!data) { playingClip = null; return; } var clip = data.getOrCreateClip(); var anim = GetOrCreateAnimation(); var clipState = anim[clip.name]; if (clipState == null) { anim.AddClip(clip, clip.name); } if (!anim.isPlaying) { anim.Play(clip.name); } else { anim.CrossFade(clip.name); } animator.updateMode = AnimatorUpdateMode.AnimatePhysics; playingClip = clip; //anim.localBounds = new Bounds(new Vector3(9527 * 2, 9527 * 2, -9527 * 100), new Vector3()); }
internal void DoStateExit(Animator animator, ref AnimatorStateInfo stateInfo, CompressedClipData data) { if (!data) { return; } var clip = data.getOrCreateClip(); anim.Stop(clip.name); if (clip == playingClip) { playingClip = null; } }
protected override void InitEncode(CompressedClipData clip, AnimationCurve curve, List <Keyframe> keys) { base.InitEncode(clip, curve, keys); keysTans = new float[keys.Count]; }