diff --git a/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs b/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs
index 8afa2e9..6d3a415 100644
--- a/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs
+++ b/Assets/Coffee/UIExtensions/UIParticle/Scripts/Editor/UIParticleEditor.cs
@@ -6,6 +6,7 @@ using System.Linq;
 using UnityEditor.IMGUI.Controls;
 using System;
 using System.Reflection;
+using ShaderPropertyType = Coffee.UIExtensions.UIParticle.AnimatableProperty.ShaderPropertyType;
 
 namespace Coffee.UIExtensions
 {
@@ -13,6 +14,108 @@ namespace Coffee.UIExtensions
 	[CanEditMultipleObjects]
 	public class UIParticleEditor : GraphicEditor
 	{
+		class AnimatedPropertiesEditor
+		{
+			static readonly List<string> s_ActiveNames = new List<string> ();
+			static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder ();
+
+			public string name;
+			public ShaderPropertyType type;
+
+			static string CollectActiveNames (SerializedProperty sp, List<string> result)
+			{
+				result.Clear ();
+				for (int i = 0; i < sp.arraySize; i++)
+				{
+					result.Add (sp.GetArrayElementAtIndex (i).FindPropertyRelative ("m_Name").stringValue);
+				}
+
+				s_Sb.Length = 0;
+				if (result.Count == 0)
+				{
+					s_Sb.Append ("Nothing");
+				}
+				else
+				{
+					result.Aggregate (s_Sb, (a, b) => s_Sb.AppendFormat ("{0}, ", b));
+					s_Sb.Length -= 2;
+				}
+
+				return s_Sb.ToString ();
+			}
+
+			public static void DrawAnimatableProperties (SerializedProperty sp, Material mat)
+			{
+				if (!mat || !mat.shader)
+					return;
+				bool isClicked = false;
+				using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth (false)))
+				{
+					var r = EditorGUI.PrefixLabel (EditorGUILayout.GetControlRect (true), new GUIContent (sp.displayName, sp.tooltip));
+					isClicked = GUI.Button (r, CollectActiveNames (sp, s_ActiveNames), EditorStyles.popup);
+				}
+
+				if (isClicked)
+				{
+					GenericMenu gm = new GenericMenu ();
+					gm.AddItem (new GUIContent ("Nothing"), s_ActiveNames.Count == 0, () =>
+					{
+						sp.ClearArray ();
+						sp.serializedObject.ApplyModifiedProperties ();
+					});
+
+
+					for (int i = 0; i < sp.arraySize; i++)
+					{
+						var p = sp.GetArrayElementAtIndex (i);
+						var name = p.FindPropertyRelative ("m_Name").stringValue;
+						var type = (ShaderPropertyType)p.FindPropertyRelative ("m_Type").intValue;
+						AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = name, type = type }, false);
+					}
+
+					for (int i = 0; i < ShaderUtil.GetPropertyCount (mat.shader); i++)
+					{
+						var pName = ShaderUtil.GetPropertyName (mat.shader, i);
+						var type = (ShaderPropertyType)ShaderUtil.GetPropertyType (mat.shader, i);
+						AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName, type = type }, true);
+
+						if (type == ShaderPropertyType.Texture)
+						{
+							AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_ST", type = ShaderPropertyType.Vector }, true);
+							AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_HDR", type = ShaderPropertyType.Vector }, true);
+							AddMenu (gm, sp, new AnimatedPropertiesEditor () { name = pName + "_TexelSize", type = ShaderPropertyType.Vector }, true);
+						}
+
+					}
+
+					gm.ShowAsContext ();
+				}
+			}
+
+			public static void AddMenu (GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
+			{
+				if (add && s_ActiveNames.Contains (property.name))
+					return;
+
+				menu.AddItem (new GUIContent (string.Format ("{0} ({1})", property.name, property.type)), s_ActiveNames.Contains (property.name), () =>
+				{
+					var index = s_ActiveNames.IndexOf (property.name);
+					if (0 <= index)
+					{
+						sp.DeleteArrayElementAtIndex (index);
+					}
+					else
+					{
+						sp.InsertArrayElementAtIndex (sp.arraySize);
+						var p = sp.GetArrayElementAtIndex (sp.arraySize - 1);
+						p.FindPropertyRelative ("m_Name").stringValue = property.name;
+						p.FindPropertyRelative ("m_Type").intValue = (int)property.type;
+					}
+					sp.serializedObject.ApplyModifiedProperties ();
+				});
+			}
+		}
+
 		//################################
 		// Constant or Static Members.
 		//################################
@@ -25,6 +128,15 @@ namespace Coffee.UIExtensions
 		static readonly Color s_ShapeGizmoThicknessTint = new Color (0.7f, 0.7f, 0.7f, 1.0f);
 		static Material s_Material;
 
+		static readonly List<string> s_MaskablePropertyNames = new List<string> ()
+		{
+			"_Stencil",
+			"_StencilComp",
+			"_StencilOp",
+			"_StencilWriteMask",
+			"_StencilReadMask",
+			"_ColorMask",
+		};
 
 		//################################
 		// Public/Protected Members.
@@ -88,7 +200,7 @@ namespace Coffee.UIExtensions
 			EditorGUI.EndDisabledGroup ();
 
 			// AnimatableProperties
-			AnimatedProperty.DrawAnimatableProperties (_spAnimatableProperties, current.material);
+			AnimatedPropertiesEditor.DrawAnimatableProperties (_spAnimatableProperties, current.material);
 
 			current.GetComponentsInChildren<ParticleSystem> (true, s_ParticleSystems);
 			if (s_ParticleSystems.Any (x => x.GetComponent<UIParticle> () == null))
@@ -125,118 +237,9 @@ namespace Coffee.UIExtensions
 			serializedObject.ApplyModifiedProperties ();
 		}
 
-		static readonly List<string> s_MaskablePropertyNames = new List<string> ()
-		{
-			"_Stencil",
-			"_StencilComp",
-			"_StencilOp",
-			"_StencilWriteMask",
-			"_StencilReadMask",
-			"_ColorMask",
-		};
 
 
-		class AnimatedProperty
-		{
-			static readonly List<string> s_ActiveNames = new List<string> ();
-			static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder ();
 
-			public string name;
-			public ShaderUtil.ShaderPropertyType type;
-
-			static string CollectActiveNames (SerializedProperty sp, List<string> result)
-			{
-				result.Clear ();
-				for (int i = 0; i < sp.arraySize; i++)
-				{
-					result.Add (sp.GetArrayElementAtIndex (i).FindPropertyRelative ("name").stringValue);
-				}
-
-				s_Sb.Length = 0;
-				if (result.Count == 0)
-				{
-					s_Sb.Append ("Nothing");
-				}
-				else
-				{
-					result.Aggregate (s_Sb, (a, b) => s_Sb.AppendFormat ("{0}, ", b));
-					s_Sb.Length -= 2;
-				}
-
-				return s_Sb.ToString ();
-			}
-
-			public static void DrawAnimatableProperties (SerializedProperty sp, Material mat)
-			{
-				if (!mat || !mat.shader)
-					return;
-				bool isClicked = false;
-				using (new EditorGUILayout.HorizontalScope (GUILayout.ExpandWidth(false)))
-				{
-					var r = EditorGUI.PrefixLabel (EditorGUILayout.GetControlRect (true), new GUIContent(sp.displayName, sp.tooltip));
-					isClicked = GUI.Button (r, CollectActiveNames (sp, s_ActiveNames), EditorStyles.popup);
-				}
-
-				if(isClicked)
-				{
-					GenericMenu gm = new GenericMenu ();
-					gm.AddItem (new GUIContent ("Nothing"), s_ActiveNames.Count == 0, () =>
-					{
-						sp.ClearArray ();
-						sp.serializedObject.ApplyModifiedProperties ();
-					});
-
-
-					for (int i = 0; i < sp.arraySize; i++)
-					{
-						var p = sp.GetArrayElementAtIndex (i);
-						var name = p.FindPropertyRelative ("name").stringValue;
-						var type = (ShaderUtil.ShaderPropertyType)p.FindPropertyRelative ("type").intValue;
-						AddMenu (gm, sp, new AnimatedProperty () { name = name, type = type }, false);
-					}
-
-					for (int i = 0; i < ShaderUtil.GetPropertyCount (mat.shader); i++)
-					{
-						var pName = ShaderUtil.GetPropertyName (mat.shader, i);
-						var type = ShaderUtil.GetPropertyType (mat.shader, i);
-						AddMenu (gm, sp, new AnimatedProperty () { name = pName, type = type }, true);
-
-						if (type == ShaderUtil.ShaderPropertyType.TexEnv)
-						{
-							AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_ST", type = ShaderUtil.ShaderPropertyType.Vector }, true);
-							AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_HDR", type = ShaderUtil.ShaderPropertyType.Vector }, true);
-							AddMenu (gm, sp, new AnimatedProperty () { name = pName + "_TexelSize", type = ShaderUtil.ShaderPropertyType.Vector }, true);
-						}
-
-					}
-
-					gm.ShowAsContext ();
-				}
-			}
-
-			public static void AddMenu (GenericMenu menu, SerializedProperty sp, AnimatedProperty property, bool add)
-			{
-				if (add && s_ActiveNames.Contains (property.name))
-					return;
-
-				menu.AddItem (new GUIContent (string.Format ("{0} ({1})", property.name, property.type)), s_ActiveNames.Contains (property.name), () =>
-				{
-					var index = s_ActiveNames.IndexOf (property.name);
-					if (0 <= index)
-					{
-						sp.DeleteArrayElementAtIndex (index);
-					}
-					else
-					{
-						sp.InsertArrayElementAtIndex (sp.arraySize);
-						var p = sp.GetArrayElementAtIndex (sp.arraySize - 1);
-						p.FindPropertyRelative ("name").stringValue = property.name;
-						p.FindPropertyRelative ("type").intValue = (int)property.type;
-					}
-					sp.serializedObject.ApplyModifiedProperties ();
-				});
-			}
-		}
 
 
 		//################################
diff --git a/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs b/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs
index 437dee9..05bbc19 100755
--- a/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs
+++ b/Assets/Coffee/UIExtensions/UIParticle/Scripts/UIParticle.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Profiling;
 using UnityEngine.UI;
+using ShaderPropertyType = Coffee.UIExtensions.UIParticle.AnimatableProperty.ShaderPropertyType;
 
 
 namespace Coffee.UIExtensions
@@ -41,7 +42,7 @@ namespace Coffee.UIExtensions
 		static MaterialPropertyBlock s_Mpb;
 
 		[System.Serializable]
-		public class AnimatableProperty
+		public class AnimatableProperty : ISerializationCallbackReceiver
 		{
 			public enum ShaderPropertyType
 			{
@@ -49,11 +50,25 @@ namespace Coffee.UIExtensions
 				Vector,
 				Float,
 				Range,
-				TexEnv,
+				Texture,
 			};
 
-			public string name;
-			public ShaderPropertyType type;
+			[SerializeField]
+			string m_Name;
+			[SerializeField]
+			ShaderPropertyType m_Type;
+			public int id { get; private set; }
+			public ShaderPropertyType type { get { return m_Type; } }
+
+
+			public void OnBeforeSerialize ()
+			{
+			}
+
+			public void OnAfterDeserialize ()
+			{
+				id = Shader.PropertyToID (m_Name);
+			}
 		}
 
 
@@ -429,18 +444,7 @@ namespace Coffee.UIExtensions
 					canvasRenderer.SetTexture (mainTexture);
 
 					// Copy the value from MaterialPropertyBlock to CanvasRenderer (#41)
-					if (Application.isPlaying && 0 < m_AnimatableProperties.Length)
-					{
-						_renderer.GetPropertyBlock (s_Mpb);
-						for (int i = 0; i < canvasRenderer.materialCount; i++)
-						{
-							var mat = canvasRenderer.GetMaterial (i);
-							foreach (var ap in m_AnimatableProperties)
-							{
-								mat.SetVector (ap.name, s_Mpb.GetVector (ap.name));
-							}
-						}
-					}
+					UpdateAnimatableMaterialProperties ();
 
 					Profiler.EndSample ();
 				}
@@ -500,5 +504,43 @@ namespace Coffee.UIExtensions
 				_parent._children.Add (this);
 			}
 		}
+
+		/// <summary>
+		/// Copy the value from MaterialPropertyBlock to CanvasRenderer (#41)
+		/// </summary>
+		void UpdateAnimatableMaterialProperties ()
+		{
+#if UNITY_EDITOR
+			if (!Application.isPlaying)
+				return;
+#endif
+			if (0 == m_AnimatableProperties.Length)
+				return;
+
+			_renderer.GetPropertyBlock (s_Mpb);
+			for (int i = 0; i < canvasRenderer.materialCount; i++)
+			{
+				var mat = canvasRenderer.GetMaterial (i);
+				foreach (var ap in m_AnimatableProperties)
+				{
+					switch (ap.type)
+					{
+						case ShaderPropertyType.Color:
+							mat.SetColor (ap.id, s_Mpb.GetColor (ap.id));
+							break;
+						case ShaderPropertyType.Vector:
+							mat.SetVector (ap.id, s_Mpb.GetVector (ap.id));
+							break;
+						case ShaderPropertyType.Float:
+						case ShaderPropertyType.Range:
+							mat.SetFloat (ap.id, s_Mpb.GetFloat (ap.id));
+							break;
+						case ShaderPropertyType.Texture:
+							mat.SetTexture (ap.id, s_Mpb.GetTexture (ap.id));
+							break;
+					}
+				}
+			}
+		}
 	}
 }
\ No newline at end of file