using UnityEngine; using UnityEngine.UI; using DG.Tweening; using System.Collections.Generic; using System.Collections; #if UNITY_EDITOR using UnityEditor; [CustomEditor(typeof(EffectControlHelper))] public class EffectControlHelperEditor : Editor { static Keyframe k0 = new Keyframe(0, 0, 1, 1); static Keyframe k1 = new Keyframe(1, 1, 1, 1); EffectControlHelper helper; SerializedProperty tweenProperties; GUIContent content = new GUIContent(); int gridID = 0; AnimationCurve copyCurve; Gradient copyGradient; private void OnEnable() { helper = target as EffectControlHelper; tweenProperties = serializedObject.FindProperty("tweens"); Undo.undoRedoPerformed += OnUndoRedo; Resort(); } private void Resort() { int sequenceID = 0; for (int i = 0; i < tweenProperties.arraySize; i++) { var tween = tweenProperties.GetArrayElementAtIndex(i); SerializedProperty controlType = tween.FindPropertyRelative("controlType"); if ((EffectControlHelper.ControlType)controlType.enumValueIndex == EffectControlHelper.ControlType.SequenceTex) { tween.FindPropertyRelative("key").intValue = sequenceID++; } } } void OnUndoRedo() { serializedObject.Update(); Repaint(); } void OnDisable() { Undo.undoRedoPerformed -= OnUndoRedo; } public override void OnInspectorGUI() { serializedObject.Update(); AddTween(); SetProperty("总延迟", serializedObject.FindProperty("delay")); RepeatSetting(); Resort(); gridID = GUILayout.SelectionGrid(gridID, GetTweenNames(), 2); if (gridID >= 0 && gridID < helper.tweens.Count) { EditorGUILayout.BeginVertical("helpbox"); { ShowListControl(ref gridID); if (gridID >= 0 && gridID < helper.tweens.Count) ShowAndSetTween(gridID); } EditorGUILayout.EndVertical(); } if (GUILayout.Button("测试播放")) { if (!Application.isPlaying) { EditorApplication.isPlaying = true; } else { helper.RePlay(); } } SampleAnimation(); } void AddTween() { SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 0); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制的变换节点", null, typeof(Transform), true), "Set Controller"); SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 3); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制的材质节点", null, typeof(Renderer), true), "Set Controller"); SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 3); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制的UI网格节点", null, typeof(UIMeshRenderer), true), "Set Controller"); SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 3); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制的图形节点", null, typeof(MaskableGraphic), true), "Set Controller"); SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 5); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制显示的节点", null, typeof(GameObject), true), "Set Controller"); SetField((v) => { tweenProperties.GetArrayElementAtIndex(++tweenProperties.arraySize - 1).FindPropertyRelative("body").objectReferenceValue = v; InitTween(tweenProperties.arraySize - 1, 8); serializedObject.ApplyModifiedPropertiesWithoutUndo(); gridID = tweenProperties.arraySize - 1; }, () => EditorGUILayout.ObjectField("拖入需要控制的投影节点", null, typeof(ProjectorPlane), true), "Set Controller"); } void RepeatSetting() { #region 简易复生 SerializedProperty repeatTimes = serializedObject.FindProperty("repeatTimes"); SetField((v) => { repeatTimes.arraySize = Mathf.Max(0, v); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.DelayedIntField("简易重复", repeatTimes.arraySize), "Set Count"); if (repeatTimes.arraySize > 0) { EditorGUILayout.BeginVertical("helpBox"); { for (int i = 0; i < repeatTimes.arraySize; i++) { SetField((v) => { repeatTimes.GetArrayElementAtIndex(i).floatValue = Mathf.Max(0, v); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.FloatField(string.Format(" 延迟[{0}]", i), repeatTimes.GetArrayElementAtIndex(i).floatValue), "Set Time"); } if (repeatTimes.arraySize > 0) { SetProperty("依次偏移", serializedObject.FindProperty("offset")); SetProperty("依次偏转", serializedObject.FindProperty("angleOff")); SetProperty("依次缩放", serializedObject.FindProperty("scale")); SetProperty("存在时间", serializedObject.FindProperty("instanceExistTime")); } } EditorGUILayout.EndVertical(); } #endregion #region 自定义复生 SerializedProperty avatars = serializedObject.FindProperty("avatars"); SerializedProperty avatar; SetField((v) => { int oldSize = avatars.arraySize; avatars.arraySize = Mathf.Max(0, v); serializedObject.ApplyModifiedPropertiesWithoutUndo(); for (int i = oldSize; i < avatars.arraySize; i++) { avatar = avatars.GetArrayElementAtIndex(i); avatar.FindPropertyRelative("scale").vector3Value = Vector3.one; avatar.FindPropertyRelative("duration").floatValue = 1; } serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.DelayedIntField("自定义重复", avatars.arraySize), "Set Count"); for (int i = 0; i < avatars.arraySize; i++) { avatar = avatars.GetArrayElementAtIndex(i); EditorGUILayout.BeginVertical("helpbox"); { SetProperty("延迟", avatar.FindPropertyRelative("delay")); SetProperty("位置", avatar.FindPropertyRelative("position")); SetProperty("角度", avatar.FindPropertyRelative("rotation")); SetProperty("比例", avatar.FindPropertyRelative("scale")); SetProperty("存在时间", avatar.FindPropertyRelative("duration")); } EditorGUILayout.EndVertical(); } #endregion } void ShowListControl(ref int i) { EditorGUILayout.BeginHorizontal(); { EffectControlHelper.TweenGroup tween = helper.tweens[i]; SetField((v) => tween.body = v, () => EditorGUILayout.ObjectField(tween.body, tween.body.GetType(), true), "Change Body"); if (GUILayout.Button("复制", GUILayout.Width(40))) { if (i >= 0) { Undo.RecordObject(helper, "Copy"); EffectControlHelper.TweenGroup clone = new EffectControlHelper.TweenGroup(helper.tweens[i]); helper.tweens.Add(clone); EditorUtility.SetDirty(helper); serializedObject.Update(); } } if (GUILayout.Button("上移", GUILayout.Width(40))) { if (i > 0) { Undo.RecordObject(helper, "Move Up"); tweenProperties.MoveArrayElement(i, i - 1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } } if (GUILayout.Button("下移", GUILayout.Width(40))) { if (i < tweenProperties.arraySize - 1) { Undo.RecordObject(helper, "Move Down"); tweenProperties.MoveArrayElement(i, i + 1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } } if (GUILayout.Button("删除", GUILayout.Width(40))) { Undo.RecordObject(helper, "Remove"); tweenProperties.DeleteArrayElementAtIndex(i--); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } } EditorGUILayout.EndHorizontal(); } void ShowAndSetTween(int i) { SerializedProperty tween = tweenProperties.GetArrayElementAtIndex(i); SerializedProperty controlType = tween.FindPropertyRelative("controlType"); SetField((v) => { if (helper.tweens[i].body is Renderer || helper.tweens[i].body is UIMeshRenderer || helper.tweens[i].body is MaskableGraphic) { if (v != EffectControlHelper.ControlType.TintColor && v != EffectControlHelper.ControlType.UV && v != EffectControlHelper.ControlType.ShaderValue && v != EffectControlHelper.ControlType.SequenceTex) v = EffectControlHelper.ControlType.TintColor; } else if (helper.tweens[i].body is Transform) { if (v != EffectControlHelper.ControlType.Position && v != EffectControlHelper.ControlType.Rotation && v != EffectControlHelper.ControlType.Scale) v = EffectControlHelper.ControlType.Position; } else if (helper.tweens[i].body is GameObject) v = EffectControlHelper.ControlType.Visible; else if (helper.tweens[i].body is ProjectorPlane) v = EffectControlHelper.ControlType.ProjectorPlane; controlType.intValue = (int)v; serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => (EffectControlHelper.ControlType)EditorGUILayout.EnumPopup("控制方式", (EffectControlHelper.ControlType)controlType.enumValueIndex), "Set ControlType"); switch ((EffectControlHelper.ControlType)controlType.enumValueIndex) { case EffectControlHelper.ControlType.Visible: { #region 显示 SetProperty("延迟(不再使用)", tween.FindPropertyRelative("delay")); SetProperty("可见(不再使用)", tween.FindPropertyRelative("visible")); SerializedProperty visibles = tween.FindPropertyRelative("visibles"); SetField((v) => { visibles.arraySize = Mathf.Max(0, v); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.IntField("可视组", visibles.arraySize), "Set Size"); for (int s = 0; s < visibles.arraySize; s++) { EditorGUILayout.BeginHorizontal(); { SerializedProperty visible = visibles.GetArrayElementAtIndex(s); SetField((v) => { visible.FindPropertyRelative("delay").floatValue = Mathf.Max(0, v); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.DelayedFloatField("时间", visible.FindPropertyRelative("delay").floatValue), "Set Delay"); SetField((v) => { visible.FindPropertyRelative("visible").boolValue = v; serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.ToggleLeft("可见", visible.FindPropertyRelative("visible").boolValue, GUILayout.Width(60)), "Set Visible"); } EditorGUILayout.EndHorizontal(); } #endregion break; } case EffectControlHelper.ControlType.Position: case EffectControlHelper.ControlType.Rotation: case EffectControlHelper.ControlType.Scale: { #region 变换动画 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); SetProperty("循环(-1=无限循环)", tween.FindPropertyRelative("loop")); SetProperty("循环方式", tween.FindPropertyRelative("loopType")); SerializedProperty vectorCtrl = tween.FindPropertyRelative("vectorCtrl"); SetProperty("开始于", vectorCtrl.FindPropertyRelative("from")); SetProperty("结束于", vectorCtrl.FindPropertyRelative("to")); SetProperty("使用绝对旋转方式", tween.FindPropertyRelative("useWorldRot")); SetProperty("使用缓动代替曲线", tween.FindPropertyRelative("useEase")); if (tween.FindPropertyRelative("useEase").boolValue) SetProperty("缓动类型", tween.FindPropertyRelative("ease")); else { SerializedProperty curves = tween.FindPropertyRelative("curves"); if (curves.arraySize < 3) { int oldSize = curves.arraySize; curves.arraySize = 3; for (int c = oldSize; c < curves.arraySize; c++) curves.GetArrayElementAtIndex(c).animationCurveValue = new AnimationCurve(k0, k1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } SetCurve("X曲线", curves.GetArrayElementAtIndex(0)); SetCurve("Y曲线", curves.GetArrayElementAtIndex(1)); SetCurve("Z曲线", curves.GetArrayElementAtIndex(2)); } #endregion break; } case EffectControlHelper.ControlType.TintColor: { #region 颜色动画 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); SetProperty("循环(-1=无限循环)", tween.FindPropertyRelative("loop")); SetProperty("循环方式", tween.FindPropertyRelative("loopType")); SerializedProperty colorCtrl = tween.FindPropertyRelative("colorCtrl"); if (tween.FindPropertyRelative("body").objectReferenceValue is Renderer) { Renderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as Renderer; SelectProperty("颜色属性名", colorCtrl.FindPropertyRelative("colorName"), GetShaderProperties(renderer.sharedMaterial, ShaderUtil.ShaderPropertyType.Color)); } SetGradient("颜色变化", helper.tweens[i].colorCtrl.gradient, colorCtrl.FindPropertyRelative("gradient")); #endregion break; } case EffectControlHelper.ControlType.UV: { #region UV动画 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); SetProperty("循环(-1=无限循环)", tween.FindPropertyRelative("loop")); SetProperty("循环方式", tween.FindPropertyRelative("loopType")); SerializedProperty uvCtrl = tween.FindPropertyRelative("uvCtrl"); if (tween.FindPropertyRelative("body").objectReferenceValue is Renderer) { Renderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as Renderer; if (renderer.sharedMaterial) SelectProperty("UV属性名", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.sharedMaterial, ShaderUtil.ShaderPropertyType.Vector, ShaderUtil.ShaderPropertyType.TexEnv)); } else if (tween.FindPropertyRelative("body").objectReferenceValue is UIMeshRenderer) { UIMeshRenderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as UIMeshRenderer; if (renderer.material) SelectProperty("UV属性名", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Vector, ShaderUtil.ShaderPropertyType.TexEnv)); } else if (tween.FindPropertyRelative("body").objectReferenceValue is MaskableGraphic) { MaskableGraphic renderer = tween.FindPropertyRelative("body").objectReferenceValue as MaskableGraphic; if (renderer.material) SelectProperty("UV属性名", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Vector)); } SerializedProperty uvInfoFrom = uvCtrl.FindPropertyRelative("from"); SerializedProperty uvInfoTo = uvCtrl.FindPropertyRelative("to"); SetField((v) => { uvInfoFrom.vector4Value = new Vector4(v.x, v.y, uvInfoFrom.vector4Value.z, uvInfoFrom.vector4Value.w); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.Vector2Field("Tiling From", new Vector2(uvInfoFrom.vector4Value.x, uvInfoFrom.vector4Value.y)), "Set UV Tiling"); SetField((v) => { uvInfoTo.vector4Value = new Vector4(v.x, v.y, uvInfoTo.vector4Value.z, uvInfoTo.vector4Value.w); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.Vector2Field("Tiling To", new Vector2(uvInfoTo.vector4Value.x, uvInfoTo.vector4Value.y)), "Set UV Tiling"); SetField((v) => { uvInfoFrom.vector4Value = new Vector4(uvInfoFrom.vector4Value.x, uvInfoFrom.vector4Value.y, v.x, v.y); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.Vector2Field("Offset From", new Vector2(uvInfoFrom.vector4Value.z, uvInfoFrom.vector4Value.w)), "Set UV Offset"); SetField((v) => { uvInfoTo.vector4Value = new Vector4(uvInfoTo.vector4Value.x, uvInfoTo.vector4Value.y, v.x, v.y); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => EditorGUILayout.Vector2Field("Offset To", new Vector2(uvInfoTo.vector4Value.z, uvInfoTo.vector4Value.w)), "Set UV Offset"); SetProperty("使用缓动代替曲线", tween.FindPropertyRelative("useEase")); if (tween.FindPropertyRelative("useEase").boolValue) SetProperty("缓动类型", tween.FindPropertyRelative("ease")); else { SerializedProperty curves = tween.FindPropertyRelative("curves"); if (curves.arraySize < 4) { int oldSize = curves.arraySize; curves.arraySize = 4; for (int c = oldSize; c < curves.arraySize; c++) curves.GetArrayElementAtIndex(c).animationCurveValue = new AnimationCurve(k0, k1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } SetCurve("U Tiling Curve", curves.GetArrayElementAtIndex(0)); SetCurve("V Tiling Curve", curves.GetArrayElementAtIndex(1)); SetCurve("U Offset Curve", curves.GetArrayElementAtIndex(2)); SetCurve("V Offset Curve", curves.GetArrayElementAtIndex(3)); } #endregion break; } case EffectControlHelper.ControlType.SequenceTex: { #region 序列动画 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); SetProperty("循环(-1=无限循环)", tween.FindPropertyRelative("loop")); SetProperty("key值(不可有重复,从0开始的整数)", tween.FindPropertyRelative("key")); SerializedProperty uvCtrl = tween.FindPropertyRelative("uvCtrl"); if (tween.FindPropertyRelative("body").objectReferenceValue is Renderer) { Renderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as Renderer; if (renderer.sharedMaterial) SelectProperty("序列纹理属性名", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.sharedMaterial, ShaderUtil.ShaderPropertyType.TexEnv)); } else if (tween.FindPropertyRelative("body").objectReferenceValue is UIMeshRenderer) { UIMeshRenderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as UIMeshRenderer; if (renderer.material) SelectProperty("序列纹理UV", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Vector)); } else if (tween.FindPropertyRelative("body").objectReferenceValue is MaskableGraphic) { MaskableGraphic renderer = tween.FindPropertyRelative("body").objectReferenceValue as MaskableGraphic; if (renderer.material) SelectProperty("序列纹理UV", uvCtrl.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Vector)); } SerializedProperty uvInfoFrom = uvCtrl.FindPropertyRelative("from"); SerializedProperty uvInfoTo = uvCtrl.FindPropertyRelative("to"); //X,Y = 列数,行数 SetField((v) => { v.x = v.x == 0 ? v.x = 1 : v.x; v.y = v.y == 0 ? v.y = 1 : v.y; uvInfoFrom.vector4Value = new Vector4(1 / v.x, 1 / v.y, 0, 1 - 1 / v.y); uvInfoTo.vector4Value = new Vector4(1 / v.x, 1 / v.y, 1 - 1 / v.x, 0); serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => { int xCount = (int)(1 / uvInfoFrom.vector4Value.x + 0.5f); int yCount = (int)(1 / uvInfoFrom.vector4Value.y + 0.5f); return EditorGUILayout.Vector2Field("U Count | V Count", new Vector2(xCount, yCount)); }, "Set Col And Row"); #endregion break; } case EffectControlHelper.ControlType.ShaderValue: { #region 值变化 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); SetProperty("循环(-1=无限循环)", tween.FindPropertyRelative("loop")); SetProperty("循环方式", tween.FindPropertyRelative("loopType")); SerializedProperty floatCtrol = tween.FindPropertyRelative("floatCtrl"); if (tween.FindPropertyRelative("body").objectReferenceValue is Renderer) { Renderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as Renderer; if (renderer.sharedMaterial) SelectProperty("值属性名", floatCtrol.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.sharedMaterial, ShaderUtil.ShaderPropertyType.Float, ShaderUtil.ShaderPropertyType.Range)); } else if (tween.FindPropertyRelative("body").objectReferenceValue is UIMeshRenderer) { UIMeshRenderer renderer = tween.FindPropertyRelative("body").objectReferenceValue as UIMeshRenderer; if (renderer.material) SelectProperty("值属性名", floatCtrol.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Float, ShaderUtil.ShaderPropertyType.Range)); } else if(tween.FindPropertyRelative("body").objectReferenceValue is MaskableGraphic) { MaskableGraphic renderer = tween.FindPropertyRelative("body").objectReferenceValue as MaskableGraphic; if (renderer.material) SelectProperty("值属性名", floatCtrol.FindPropertyRelative("propertyName"), GetShaderProperties(renderer.material, ShaderUtil.ShaderPropertyType.Float, ShaderUtil.ShaderPropertyType.Range)); } SetProperty("开始于", floatCtrol.FindPropertyRelative("from")); SetProperty("结束于", floatCtrol.FindPropertyRelative("to")); SetProperty("使用缓动代替曲线", tween.FindPropertyRelative("useEase")); if (tween.FindPropertyRelative("useEase").boolValue) SetProperty("缓动类型", tween.FindPropertyRelative("ease")); else { SerializedProperty curves = tween.FindPropertyRelative("curves"); if (curves.arraySize < 1) { curves.arraySize = 1; curves.GetArrayElementAtIndex(0).animationCurveValue = new AnimationCurve(k0, k1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } SetCurve("曲线", curves.GetArrayElementAtIndex(0)); } #endregion break; } case EffectControlHelper.ControlType.ProjectorPlane: { #region 投影面 SetProperty("延迟", tween.FindPropertyRelative("delay")); SetProperty("持续时间", tween.FindPropertyRelative("duration")); EditorGUILayout.LabelField("", "持续时间为0时,仅创建不更新,为-1时,每帧更新直到本体消亡,大于0时保持每帧更新", "Helpbox"); #endregion break; } } } void InitTween(int i, int controlType) { SerializedProperty tween = tweenProperties.GetArrayElementAtIndex(tweenProperties.arraySize - 1); tween.FindPropertyRelative("controlType").intValue = controlType; tween.FindPropertyRelative("duration").floatValue = 1f; tween.FindPropertyRelative("loop").intValue = 1; SerializedProperty colorCtrl = tween.FindPropertyRelative("colorCtrl"); colorCtrl.FindPropertyRelative("colorName").stringValue = "_TintColor"; SerializedProperty unCtrl = tween.FindPropertyRelative("uvCtrl"); unCtrl.FindPropertyRelative("propertyName").stringValue = "_UV"; unCtrl.FindPropertyRelative("from").vector4Value = new Vector4(1, 1, 0, 0); unCtrl.FindPropertyRelative("to").vector4Value = new Vector4(1, 1, 0, 0); SerializedProperty curves = tween.FindPropertyRelative("curves"); switch (controlType) { case 0: case 1: case 2: { curves.arraySize = 3; for (int c = 0; c < 3; c++) curves.GetArrayElementAtIndex(c).animationCurveValue = new AnimationCurve(k0, k1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); } break; case 3: { serializedObject.ApplyModifiedPropertiesWithoutUndo(); helper.tweens[i].colorCtrl.gradient = new Gradient(); helper.tweens[i].colorCtrl.gradient.SetKeys( new GradientColorKey[2] { new GradientColorKey(Color.white, 0), new GradientColorKey(Color.white, 1) }, new GradientAlphaKey[2] { new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1) }); EditorUtility.SetDirty(helper); serializedObject.Update(); } break; case 4: { curves.arraySize = 4; for (int c = 0; c < 4; c++) curves.GetArrayElementAtIndex(c).animationCurveValue = new AnimationCurve(k0, k1); serializedObject.ApplyModifiedPropertiesWithoutUndo(); } break; } } List<string> GetShaderProperties(Material material, params ShaderUtil.ShaderPropertyType[] type) { Shader shader = material.shader; List<string> properties = new List<string>(); int count = ShaderUtil.GetPropertyCount(shader); for (int i = 0; i < count; i++) { ShaderUtil.ShaderPropertyType propertyType = ShaderUtil.GetPropertyType(shader, i); for (int j = 0; j < type.Length; j++) if (propertyType == type[j]) properties.Add(ShaderUtil.GetPropertyName(shader, i)); } return properties; } string[] GetTweenNames() { List<string> names = new List<string>(); for (int i = 0; i < helper.tweens.Count; i++) { if (!helper.tweens[i].body) { helper.tweens.RemoveAt(i--); EditorUtility.SetDirty(helper); serializedObject.Update(); continue; } names.Add(string.Format("{0}<{1}>", helper.tweens[i].body.name, helper.tweens[i].controlType.ToString())); } return names.ToArray(); } void SetField<T>(System.Action<T> value, System.Func<T> func, string undoTip = null) { EditorGUI.BeginChangeCheck(); T result = func(); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(helper, undoTip == null ? "Field Change" : undoTip); value(result); EditorUtility.SetDirty(helper); } } void SetProperty(string label, SerializedProperty property, string undoTip = null) { EditorGUI.BeginChangeCheck(); content.text = label == null ? "" : label; EditorGUILayout.PropertyField(property, content, true); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(helper, undoTip == null ? "Property Change" : undoTip); serializedObject.ApplyModifiedPropertiesWithoutUndo(); EditorUtility.SetDirty(helper); } } void SelectProperty(string label, SerializedProperty nameProperty, List<string> filterProperties) { EditorGUILayout.BeginHorizontal(); { SetProperty(label, nameProperty); SetField((v) => { nameProperty.stringValue = v; serializedObject.ApplyModifiedPropertiesWithoutUndo(); }, () => { int d = filterProperties.FindIndex(n => n.Equals(nameProperty.stringValue)); int p = EditorGUILayout.Popup(d, filterProperties.ToArray(), GUILayout.Width(80)); if (p != d) return filterProperties[p]; return nameProperty.stringValue; }); } EditorGUILayout.EndHorizontal(); } void SetCurve(string label, SerializedProperty curve) { EditorGUILayout.BeginHorizontal(); { SetProperty(label, curve); GUI.color = copyCurve == null ? Color.white : Color.yellow; if (GUILayout.Button(copyCurve == null ? "复制曲线" : "粘贴曲线", GUILayout.Width(54))) { if (copyCurve == null) { copyCurve = curve.animationCurveValue; } else { curve.animationCurveValue = new AnimationCurve(copyCurve.keys); copyCurve = null; serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(helper); } } GUI.color = Color.white; } EditorGUILayout.EndHorizontal(); } void SetGradient(string label, Gradient gradient, SerializedProperty gradProperty) { EditorGUILayout.BeginHorizontal(); { SetProperty(label, gradProperty); GUI.color = copyGradient == null ? Color.white : Color.yellow; if (GUILayout.Button(copyGradient != null ? "粘贴" : "复制", GUILayout.Width(54))) { if (copyGradient == null) { copyGradient = new Gradient(); copyGradient.SetKeys(gradient.colorKeys, gradient.alphaKeys); } else { Undo.RecordObject(helper, "Copy"); gradient.SetKeys(copyGradient.colorKeys, copyGradient.alphaKeys); EditorUtility.SetDirty(helper); serializedObject.Update(); copyGradient = null; Repaint(); } } GUI.color = Color.white; } EditorGUILayout.EndHorizontal(); } void SampleAnimation() { if (string.IsNullOrEmpty(helper.animationPath)) { string relativePath = AssetDatabase.GetAssetPath(PrefabUtility.GetPrefabParent(helper)); helper.animationPath = string.IsNullOrEmpty(relativePath) ? helper.animationPath : relativePath.Split('.')[0]; } SetField((v) => helper.animationPath = v, () => EditorGUILayout.DelayedTextField("采样动画路径", helper.animationPath), "Set Bake Path"); if (GUILayout.Button("采样到动画")) { if (!Application.isPlaying) return; string relativePath = helper.animationPath; if (System.IO.Directory.Exists(relativePath.Substring(0, relativePath.LastIndexOf('/')))) helper.BakeToClip((c) => { AnimationClip clip; if (clip = (AnimationClip)AssetDatabase.LoadAssetAtPath(relativePath + ".anim", typeof(AnimationClip))) { EditorUtility.CopySerialized(c, clip); EditorUtility.SetDirty(clip); } else AssetDatabase.CreateAsset(c, relativePath + ".anim"); }); } } } #endif public class EffectControlHelper : MonoBehaviour { public Vector3 worldRot = Vector3.zero; public enum ControlType { Position = 0, Rotation = 1, Scale = 2, TintColor = 3, UV = 4, Visible = 5, ShaderValue = 6, SequenceTex = 7, ProjectorPlane = 8 } [System.Serializable] public class TweenGroup { public Object body; public ControlType controlType; public float delay; public float duration; public int loop; public int key; public LoopType loopType; public Vector3Control vectorCtrl; public ColorControl colorCtrl; public UVControl uvCtrl; public FloatControl floatCtrl; public bool useEase; public bool useWorldRot; public Vector3 worldRot = Vector3.zero; public AnimationCurve[] curves; public Ease ease; public bool visible; public VisableGroup[] visibles; public TweenGroup() { } public TweenGroup(TweenGroup source) { body = source.body; controlType = source.controlType; delay = source.delay; duration = source.duration; loop = source.loop; key = source.key; loopType = source.loopType; vectorCtrl = new Vector3Control(); vectorCtrl.from = source.vectorCtrl.from; vectorCtrl.to = source.vectorCtrl.to; colorCtrl = new ColorControl(); colorCtrl.colorName = source.colorCtrl.colorName; colorCtrl.gradient = new Gradient(); colorCtrl.gradient.SetKeys(source.colorCtrl.gradient.colorKeys, source.colorCtrl.gradient.alphaKeys); uvCtrl = new UVControl(); uvCtrl.propertyName = source.uvCtrl.propertyName; uvCtrl.from = source.uvCtrl.from; uvCtrl.to = source.uvCtrl.to; floatCtrl = new FloatControl(); floatCtrl.propertyName = source.floatCtrl.propertyName; floatCtrl.from = source.floatCtrl.from; floatCtrl.to = source.floatCtrl.to; useEase = source.useEase; curves = new AnimationCurve[source.curves.Length]; for (int i = 0; i < curves.Length; i++) curves[i] = new AnimationCurve(source.curves[i].keys); ease = source.ease; visible = source.visible; } public TweenGroup(Object body) { this.body = body; if (body is Transform) controlType = ControlType.Position; else if (body is Renderer || body is MaskableGraphic || body is UIMeshRenderer) controlType = ControlType.TintColor; else controlType = ControlType.Visible; } public void SetValue(float t) { if (body is Transform) { Vector3 v; Evalute(out v, t); switch (controlType) { case ControlType.Position: (body as Transform).localPosition = v; break; case ControlType.Rotation: if (useWorldRot) (body as Transform).eulerAngles = v + worldRot; else (body as Transform).localEulerAngles = v; break; case ControlType.Scale: (body as Transform).localScale = v; break; } } else if (body is Renderer) { Renderer r = body as Renderer; if (r.material) { switch (controlType) { case ControlType.TintColor: if (colorCtrl.gradient != null) r.material.SetColor(colorCtrl.colorName, colorCtrl.gradient.Evaluate(t)); break; case ControlType.UV: { Vector4 v; Evalute(out v, t); r.material.SetVector(uvCtrl.propertyName, v); } break; case ControlType.ShaderValue: { float v; Evalute(out v, t); r.material.SetFloat(floatCtrl.propertyName, v); } break; } } } else if (body is MaskableGraphic) { MaskableGraphic i = body as MaskableGraphic; switch (controlType) { case ControlType.TintColor: if (colorCtrl.gradient != null) i.color = colorCtrl.gradient.Evaluate(t); break; case ControlType.UV: { Vector4 v; Evalute(out v, t); if (i.material) i.material.SetVector(uvCtrl.propertyName, v); else if (i is RawImage) (i as RawImage).uvRect = new Rect(v.z, v.w, v.x, v.y); } break; case ControlType.ShaderValue: { if (i.material) { float v; Evalute(out v, t); i.material.SetFloat(floatCtrl.propertyName, v); } } break; } } else if (body is UIMeshRenderer) { UIMeshRenderer r = body as UIMeshRenderer; switch (controlType) { case ControlType.TintColor: if (colorCtrl.gradient != null) r.SetColor(colorCtrl.gradient.Evaluate(t)); break; case ControlType.UV: { Vector4 cur; Evalute(out cur, t); r.SetUV(uvCtrl.propertyName, cur); } break; case ControlType.ShaderValue: { float cur; Evalute(out cur, t); r.SetValue(floatCtrl.propertyName, cur); } break; } } } public void SetValue(Vector4 v) { if (controlType != ControlType.SequenceTex) return; if (body is Renderer) { Renderer r = body as Renderer; if (r.material) { r.material.SetTextureScale(uvCtrl.propertyName, new Vector2(v.x, v.y)); r.material.SetTextureOffset(uvCtrl.propertyName, new Vector2(v.z, v.w)); } } else if (body is MaskableGraphic) { MaskableGraphic i = body as MaskableGraphic; if (i.material) i.material.SetVector(uvCtrl.propertyName, v); else if (i is RawImage) (i as RawImage).uvRect = new Rect(v.z, v.w, v.x, v.y); } else if (body is UIMeshRenderer) { (body as UIMeshRenderer).SetUV(uvCtrl.propertyName, v); } } void Evalute(out Vector3 v, float t) { if (useEase) v = Vector3.LerpUnclamped(vectorCtrl.from, vectorCtrl.to, t); else { v.x = Mathf.LerpUnclamped(vectorCtrl.from.x, vectorCtrl.to.x, curves[0].Evaluate(t)); v.y = Mathf.LerpUnclamped(vectorCtrl.from.y, vectorCtrl.to.y, curves[1].Evaluate(t)); v.z = Mathf.LerpUnclamped(vectorCtrl.from.z, vectorCtrl.to.z, curves[2].Evaluate(t)); } } void Evalute(out Vector4 v, float t) { if (useEase) v = Vector4.LerpUnclamped(uvCtrl.from, uvCtrl.to, t); else { v.x = Mathf.LerpUnclamped(uvCtrl.from.x, uvCtrl.to.x, curves[0].Evaluate(t)); v.y = Mathf.LerpUnclamped(uvCtrl.from.y, uvCtrl.to.y, curves[1].Evaluate(t)); v.z = Mathf.LerpUnclamped(uvCtrl.from.z, uvCtrl.to.z, curves[2].Evaluate(t)); v.w = Mathf.LerpUnclamped(uvCtrl.from.w, uvCtrl.to.w, curves[3].Evaluate(t)); } } void Evalute(out float v, float t) { if (useEase) v = Mathf.LerpUnclamped(floatCtrl.from, floatCtrl.to, t); else v = Mathf.LerpUnclamped(floatCtrl.from, floatCtrl.to, curves[0].Evaluate(t)); } public void HideColor() { if (controlType != ControlType.TintColor) return; if (body is Renderer) { Renderer r = body as Renderer; if (r.material) r.material.SetColor(colorCtrl.colorName, new Color(0, 0, 0, 0)); } else if (body is MaskableGraphic) { MaskableGraphic r = body as MaskableGraphic; if (r.material) r.material.SetColor(colorCtrl.colorName, new Color(0, 0, 0, 0)); } else if (body is UIMeshRenderer) { //UIMeshRenderer r = body as UIMeshRenderer; //if (r.material) // r.material.SetColor(colorCtrl.colorName, new Color(0, 0, 0, 0)); } } } [System.Serializable] public class Vector3Control { public Vector3 from; public Vector3 to; public string followHandler; } [System.Serializable] public class ColorControl { public string colorName; public Gradient gradient; } [System.Serializable] public class UVControl { public string propertyName; public Vector4 from; public Vector4 to; } [System.Serializable] public class FloatControl { public string propertyName; public float from; public float to; } [System.Serializable] public struct VisableGroup { public float delay; public bool visible; } [System.Serializable] public class Avatar { public float delay; public Vector3 position; public Vector3 rotation; public Vector3 scale = Vector3.one; public float duration = 1; } public float delay; public float[] repeatTimes; public Vector3 offset; public Vector3 angleOff; public Vector3 scale = Vector3.one; public float instanceExistTime = 1; public Avatar[] avatars; public string animationPath; private bool isBase = true; public bool IsBase { get { return isBase; } set { isBase = value; } } public bool isOriginal = true; public List<TweenGroup> tweens = new List<TweenGroup>(); private List<Tweener> tweeners = new List<Tweener>(); private Dictionary<Transform, Vector3> posOrgState; private Dictionary<Transform, Vector3> rotOrgState; private Dictionary<Transform, Vector3> sclOrgState; private Dictionary<GameObject, bool> goOrgState; private Vector3 orgPos = Vector3.zero; private Vector3 orgRot = Vector3.zero; private Vector3 orgScl = Vector3.one; IEnumerator WaitOneFrame(System.Action ac) { yield return 1; ac(); } private void OnEnable() { StartCoroutine(WaitOneFrame(RePlay)); } private static int Compare(TweenGroup a, TweenGroup b) { if (a.delay == b.delay) { return 0; } if (a.delay > b.delay) { return 1; } else { return -1; } } private void OnDisable() { for (int i = 0; i < tweeners.Count; i++) { tweeners[i].Kill(); } tweeners.Clear(); } public void RePlay() { ResetOriginalState(); if (IsBase) { orgPos = transform.localPosition; orgRot = transform.localEulerAngles; orgScl = transform.localScale; tweens.Sort(Compare); } Delay(delay, Play); } System.Collections.IEnumerator StartPlay() { if (delay > 0) { yield return new WaitForSeconds(delay); } } private void Play() { for (int i = 0; i < tweens.Count; i++) { tweens[i].worldRot = worldRot; if (!tweens[i].body) continue; switch (tweens[i].controlType) { case ControlType.Position: { if (tweens[i].vectorCtrl == null) continue; Transform tr = tweens[i].body as Transform; if (posOrgState == null) posOrgState = new Dictionary<Transform, Vector3>(); if (!posOrgState.ContainsKey(tr)) posOrgState.Add(tr, tr.localPosition); DoValue(tweens[i]); break; } case ControlType.Rotation: { if (tweens[i].vectorCtrl == null) continue; Transform tr = tweens[i].body as Transform; if (rotOrgState == null) rotOrgState = new Dictionary<Transform, Vector3>(); if (!rotOrgState.ContainsKey(tr)) rotOrgState.Add(tr, tr.localEulerAngles); DoValue(tweens[i]); break; } case ControlType.Scale: { if (tweens[i].vectorCtrl == null) continue; Transform tr = tweens[i].body as Transform; if (sclOrgState == null) sclOrgState = new Dictionary<Transform, Vector3>(); if (!sclOrgState.ContainsKey(tr)) sclOrgState.Add(tr, tr.localScale); DoValue(tweens[i]); break; } case ControlType.TintColor: { if (tweens[i].colorCtrl == null) continue; DoColor(tweens[i]); break; } case ControlType.UV: { if (tweens[i].uvCtrl == null) continue; DoValue(tweens[i]); break; } case ControlType.SequenceTex: { if (tweens[i].uvCtrl == null) continue; DoTexSequence(tweens[i]); break; } case ControlType.ShaderValue: { if (tweens[i].floatCtrl == null) continue; DoValue(tweens[i]); break; } case ControlType.Visible: { if (tweens[i].visibles == null) continue; GameObject go = tweens[i].body as GameObject; if (goOrgState == null) goOrgState = new Dictionary<GameObject, bool>(); if (!goOrgState.ContainsKey(go)) goOrgState.Add(go, go.activeSelf); DoVisible(tweens[i]); break; } case ControlType.ProjectorPlane: { if (tweens[i].visibles == null) continue; DoProjector(tweens[i]); break; } } } if (IsBase) { SpawnRepeatSimple(); SpawnAvatar(); } } #region 控制变化 private void DoValue(TweenGroup tg) { tweeners.Add(DOTween.To(tg.SetValue, 0f, 1f, tg.duration) .SetDelay(tg.delay) .SetEase(tg.useEase ? tg.ease : Ease.Linear) .SetLoops(tg.loop, tg.loopType)); } private void DoColor(TweenGroup tg) { tweeners.Add(DOTween.To(tg.SetValue, 0f, 1f, tg.duration) .SetDelay(tg.delay) .SetEase(Ease.Linear) .SetLoops(tg.loop, tg.loopType) .OnKill(tg.HideColor)); } private void DoTexSequence(TweenGroup tg) { int xCount = (int)(1 / tg.uvCtrl.from.x + 0.5f); int totalCount = xCount * (int)(1 / tg.uvCtrl.from.y + 0.5f); if (xCount != 0 && totalCount != 0) { //tg.SetValue(new Vector4(tg.uvCtrl.from.x, tg.uvCtrl.from.y, 0, 1 - tg.uvCtrl.from.y)); //Delay(tg.delay, delegate { DoTexSequence(tg, xCount, totalCount, tg.duration / totalCount, 1, tg.loop, tg.key); }); //DoTexSequence(tg, xCount, totalCount, tg.duration / totalCount, 1, tg.loop, tg.key); tg.SetValue(new Vector4(tg.uvCtrl.from.x, tg.uvCtrl.from.y, 0, 1 - tg.uvCtrl.from.y)); tweeners.Add(DOTween.To(EmptySet, 0, tg.delay, tg.delay).SetEase(Ease.Linear).SetId(tg.key).OnComplete(delegate { DoTexSequence(tg, xCount, totalCount, tg.duration / totalCount, 1, tg.loop, tg.key); })); } } private void DoTexSequence(TweenGroup tg, int xCount, int totalCount, float intervalTime, int focus, int loop = -1, int seqKey = 0) { if (focus == totalCount && loop > 0) loop--; if (loop != 0) { focus %= totalCount; tg.SetValue(new Vector4(tg.uvCtrl.from.x, tg.uvCtrl.from.y, focus % xCount * tg.uvCtrl.from.x, 1 - (1 + focus / xCount) * tg.uvCtrl.from.y)); if (intervalTime > 0) { var tw = GetTweenerFromKey(seqKey); if (tw == null) { tweeners.Add(DOTween.To(EmptySet, 0, intervalTime, intervalTime).SetEase(Ease.Linear).SetId(seqKey).OnComplete(delegate { DoTexSequence(tg, xCount, totalCount, intervalTime, ++focus, loop, seqKey); })); } else { tw.OnComplete(delegate { DoTexSequence(tg, xCount, totalCount, intervalTime, ++focus, loop, seqKey); }); tw.Restart(); } } else { DoTexSequence(tg, xCount, totalCount, intervalTime, ++focus, loop, seqKey); } } } private Tweener GetTweenerFromKey(int key) { Tweener tw = null; if (tweeners == null || tweeners.Count < 1) return tw; for (int i = 0; i < tweeners.Count; i++) { if (tweeners[i].id != null && (tweeners[i].id is int) && (int)tweeners[i].id == key) { tw = tweeners[i]; break; } } return tw; } private void DoVisible(TweenGroup tg) { GameObject go = tg.body as GameObject; for (int i = 0; i < tg.visibles.Length; i++) { VisableGroup vg = tg.visibles[i]; Delay(vg.delay, delegate { if (vg.visible) { ParticleSystem[] pss = go.GetComponentsInChildren<ParticleSystem>(true); for (int p = 0; p < pss.Length; p++) pss[p].Clear(); TrailRenderer[] trs = go.GetComponentsInChildren<TrailRenderer>(true); for (int l = 0; l < trs.Length; l++) trs[l].Clear(); } go.SetActive(vg.visible); }); } } private void DoProjector(TweenGroup tg) { ProjectorPlane pp = tg.body as ProjectorPlane; Delay(tg.delay, delegate { if (tg.duration == 0) pp.Projector(); else if (tg.duration == -1) tweeners.Add(DOTween.To(delegate (float t) { pp.Projector(); }, 0, 1, 1).SetLoops(-1)); else tweeners.Add(DOTween.To(delegate (float t) { pp.Projector(); }, 0, 1, tg.duration)); }); } #endregion #region 控制复生 private void SpawnRepeatSimple() { if (repeatTimes != null) for (int i = 0; i < repeatTimes.Length; i++) SpawnRepeatSimple(repeatTimes[i], i + 1); } private void SpawnRepeatSimple(float delay, int index) { Delay(Mathf.Max(0.01f, delay), delegate { if (!IsBase) return; GameObject ins = Instantiate(this.gameObject); ins.transform.SetParent(transform.parent); ins.transform.localScale = new Vector3() { x = orgScl.x * Mathf.Pow(scale.x, index), y = orgScl.y * Mathf.Pow(scale.y, index), z = orgScl.z * Mathf.Pow(scale.z, index) }; ins.transform.localPosition = orgPos + offset * index; ins.transform.localEulerAngles = orgRot + angleOff * index; EffectControlHelper ech = ins.GetComponent<EffectControlHelper>(); ech.IsBase = false; Delay(ech.delay + instanceExistTime, delegate { Destroy(ins); }, delegate { Destroy(ins); }); }); } private void SpawnAvatar() { if (avatars != null) for (int i = 0; i < avatars.Length; i++) SpawnAvatar(avatars[i]); } private void SpawnAvatar(Avatar avatar) { Delay(Mathf.Max(0.01f, avatar.delay), delegate { if (!IsBase) return; GameObject ins = Instantiate(this.gameObject); ins.transform.SetParent(transform.parent); ins.transform.localPosition = avatar.position; ins.transform.localEulerAngles = avatar.rotation; ins.transform.localScale = avatar.scale; EffectControlHelper ech = ins.GetComponent<EffectControlHelper>(); ech.IsBase = false; ech.worldRot = avatar.rotation; Delay(ech.delay + avatar.duration, delegate { Destroy(ins); }, delegate { Destroy(ins); }); }); } #endregion private static void EmptySet(float v) { } private void Delay(float time, TweenCallback onComplete, TweenCallback onKill = null) { if (time > 0) tweeners.Add( DOTween.To(EmptySet, 0, time, time) .SetEase(Ease.Linear) .OnComplete(onComplete) .OnKill(onKill)); else onComplete(); } public void ResetOriginalState() { if (posOrgState != null) { var iter = posOrgState.GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Key != null) { iter.Current.Key.localPosition = iter.Current.Value; } } iter.Dispose(); } if (rotOrgState != null) { var iter = rotOrgState.GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Key != null) { iter.Current.Key.localEulerAngles = iter.Current.Value; } } iter.Dispose(); } if (sclOrgState != null) { var iter = sclOrgState.GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Key != null) { iter.Current.Key.localScale = iter.Current.Value; } } iter.Dispose(); } if (goOrgState != null) { var iter = goOrgState.GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Key != null) { iter.Current.Key.SetActive(iter.Current.Value); } } iter.Dispose(); } } public void BakeToClip(System.Action<AnimationClip> clipCallback) { AnimationClip clip = new AnimationClip(); clip.frameRate = 30; List<TweenGroup> longTimeTweens = new List<TweenGroup>(tweens); longTimeTweens.Sort((a, b) => (b.delay + b.duration).CompareTo(a.delay + a.duration)); float waitTime = longTimeTweens[0].delay + longTimeTweens[0].duration; OnDisable(); OnEnable(); Delay(delay, () => { for (int i = 0; i < tweens.Count; i++) { TweenGroup tween = tweens[i]; switch (tween.controlType) { case ControlType.Position: { Transform tr = tween.body as Transform; string relativePath = GetRelativePath(tr); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localPosition.x, (cx) => clip.SetCurve(relativePath, typeof(Transform), "localPosition.x", cx)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localPosition.y, (cy) => clip.SetCurve(relativePath, typeof(Transform), "localPosition.y", cy)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localPosition.z, (cz) => clip.SetCurve(relativePath, typeof(Transform), "localPosition.z", cz)); break; } case ControlType.Rotation: { Transform tr = tween.body as Transform; string relativePath = GetRelativePath(tr); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localEulerAngles.x, (cx) => clip.SetCurve(relativePath, typeof(Transform), "localEulerAngles.x", cx)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localEulerAngles.y, (cy) => clip.SetCurve(relativePath, typeof(Transform), "localEulerAngles.y", cy)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localEulerAngles.z, (cz) => clip.SetCurve(relativePath, typeof(Transform), "localEulerAngles.z", cz)); break; } case ControlType.Scale: { Transform tr = tween.body as Transform; string relativePath = GetRelativePath(tr); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localScale.x, (cx) => clip.SetCurve(relativePath, typeof(Transform), "localScale.x", cx)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localScale.y, (cy) => clip.SetCurve(relativePath, typeof(Transform), "localScale.y", cy)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => tr.localScale.z, (cz) => clip.SetCurve(relativePath, typeof(Transform), "localScale.z", cz)); break; } case ControlType.TintColor: { if (tween.body is Renderer) { Renderer rd = tween.body as Renderer; string relativePath = GetRelativePath(rd.transform); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.colorCtrl.colorName).r, (cr) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.colorCtrl.colorName + ".r", cr)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.colorCtrl.colorName).g, (cg) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.colorCtrl.colorName + ".g", cg)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.colorCtrl.colorName).b, (cb) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.colorCtrl.colorName + ".b", cb)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.colorCtrl.colorName).a, (ca) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.colorCtrl.colorName + ".a", ca)); } break; } case ControlType.UV: { if (tween.body is Renderer) { Renderer rd = tween.body as Renderer; string relativePath = GetRelativePath(rd.transform); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.uvCtrl.propertyName).r, (cx) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + ".x", cx)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.uvCtrl.propertyName).g, (cy) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + ".y", cy)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.uvCtrl.propertyName).b, (cz) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + ".z", cz)); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetColor(tween.uvCtrl.propertyName).a, (cw) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + ".w", cw)); } break; } case ControlType.SequenceTex: { if (tween.body is Renderer) { Renderer rd = tween.body as Renderer; string relativePath = GetRelativePath(rd.transform); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetTextureScale(tween.uvCtrl.propertyName).x, (cx) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + "_ST.x", cx), true); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetTextureScale(tween.uvCtrl.propertyName).y, (cy) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + "_ST.y", cy), true); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetTextureOffset(tween.uvCtrl.propertyName).x, (cz) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + "_ST.z", cz), true); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetTextureOffset(tween.uvCtrl.propertyName).y, (cw) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.uvCtrl.propertyName + "_ST.w", cw), true); } break; } case ControlType.ShaderValue: { Renderer rd = tween.body as Renderer; string relativePath = GetRelativePath(rd.transform); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => rd.material.GetFloat(tween.floatCtrl.propertyName), (cv) => clip.SetCurve(relativePath, typeof(Renderer), "material." + tween.floatCtrl.propertyName, cv)); break; } case ControlType.Visible: { GameObject go = tween.body as GameObject; string relativePath = GetRelativePath(go.transform); RecordCurve(tween, new AnimationCurve(), tween.delay + tween.duration, () => go.activeSelf ? 1 : 0, (cv) => clip.SetCurve(relativePath, typeof(GameObject), "m_IsActive", cv), true); break; } } } Delay(waitTime + 1, () => clipCallback(clip)); }); } private string GetRelativePath(Transform tr) { string relativePath = ""; if (tr != transform) { relativePath = tr.name; while (tr.parent != transform) { tr = tr.parent; relativePath = string.Format("{0}/{1}", tr.name, relativePath); } } return relativePath; } private void RecordCurve(TweenGroup tween, AnimationCurve curve, float duration, System.Func<float> value, System.Action<AnimationCurve> result, bool constant = false) { int frame = (int)(duration * 30 + 0.5f); for (int count = 0; count <= frame; count++) { float time = Mathf.Lerp(0, duration, (float)count / frame); Delay(time, () => { Keyframe key = new Keyframe(time, value()); key.tangentMode = constant ? 103 : 34;//103 is Constant , 34 is Auto if (curve.keys.Length > 1) { key.inTangent = constant ? float.PositiveInfinity : (value() - curve.keys[curve.keys.Length - 1].value) / (time - curve.keys[curve.keys.Length - 1].time); key.outTangent = constant ? float.PositiveInfinity : (value() - curve.keys[curve.keys.Length - 1].value) / (time - curve.keys[curve.keys.Length - 1].time); } curve.AddKey(key); }); } Delay(duration + 0.5f, () => result(curve)); } }