AnimationClip
How do I use Animation Clip
Below are practical examples compiled from projects for learning and reference purposes
Featured Snippets
File name: AnimationBuilder.cs
Copy
57 public List58 {
59 var allAnimClips = AssetDatabase.LoadAllAssetRepresentationsAtPath(scmlAssetPath).OfType
60 Debug.Log(string.Format("Found {0} animation clips at {1}", allAnimClips.Count, scmlAssetPath));
61
62 var newAnimClips = new List
63
64 foreach (var animation in entity.Animations)
65 {
66 var animClip = MakeAnimationClip(root, animation, Path.GetDirectoryName(scmlAssetPath));
67 Debug.Log(string.Format("Added animClip({0}) to asset path ({1}) WrapMode:{2}", animClip.name, scmlAssetPath, animClip.wrapMode));
68 newAnimClips.Add(animClip);
69
70 var originalAnimClip = allAnimClips.Where(clip => clip.name == animClip.name).FirstOrDefault();
71 if (originalAnimClip != null)
72 {
73 Debug.Log("Replacing animation clip " + animClip.name);
74 EditorUtility.CopySerialized(animClip, originalAnimClip);
75 allAnimClips.Remove(originalAnimClip);
76 }
77 else
78 AssetDatabase.AddObjectToAsset(animClip, scmlAssetPath);
79 }
80
81 //Remove any animation clips that are no longer present in the SCML
82 foreach(var clip in allAnimClips)
83 {
84 //This may be a bad idea
85 UnityEngine.Object.DestroyImmediate(clip, true);
86 }
87
88 return newAnimClips;
89 }
File name: AnimationBuilder.cs
Copy
91 public AnimationClip MakeAnimationClip(GameObject root, Animation animation, string baseFolderPath)
92 {
93 //Clear local caches
94 lastGameObjectCache.Clear();
95 animationEvents.Clear();
96 lastKeyframeCache.Clear();
97 spriteChangeKeys.Clear();
98 spriteBaseFolder = baseFolderPath;
99
100 var animClip = new AnimationClip();
101 animClip.name = animation.Name;
102
103 //Set clip to Generic type
104 //AnimationUtility.SetAnimationType(animClip, ModelImporterAnimationType.Generic);
105
106 //Populate the animation curves & events
107 MakeAnimationCurves(root, animClip, animation);
108
109 return animClip;
110 }
File name: AnimationBuilder.cs
Copy
112 private void MakeAnimationCurves(GameObject root, AnimationClip animClip, Animation animation)
113 {
114 acb = new AnimationCurveBuilder();
115
116 //Get a list of all sprites on this GO
117 var allSprites = root.GetComponentsInChildren
118
119 //Add a key for all objects on the first frame
120 SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), 0);
121
122 foreach (var mainlineKey in animation.MainlineKeys)
123 {
124
125 var visibleSprites = SetGameObjectForKey(root, animClip, mainlineKey);
126 var hiddenSprites = allSprites.Except(visibleSprites);
127 HideSprites(root, hiddenSprites, mainlineKey.Time);
128 }
129
130 switch (animation.LoopType)
131 {
132 case LoopType.True:
133 //Cycle back to first frame
134 SetGameObjectForKey(root, animClip, animation.MainlineKeys.First(), animation.Length);
135 break;
136 case LoopType.False:
137 //Duplicate the last key at the end time of the animation
138 SetGameObjectForKey(root, animClip, animation.MainlineKeys.Last(), animation.Length);
139 break;
140 default:
141 Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString());
142 break;
143 }
144
145 //Add the curves to our animation clip
146 //NOTE: This MUST be done before modifying the settings, thus the double switch statement
147 acb.AddCurves(animClip);
148
149 foreach (var sprite in spriteChangeKeys)
150 {
151 if (sprite.Value.Count > 0)
152 {
153 BuildSpriteChangeCurve(ref animClip, sprite);
154 }
155 }
156
157 //Set the loop/wrap settings for the animation clip
158 var animSettings = AnimationUtility.GetAnimationClipSettings(animClip);
159 switch(animation.LoopType)
160 {
161 case LoopType.True:
162 animClip.wrapMode = WrapMode.Loop;
163 animSettings.loopTime = true;
164 break;
165 case LoopType.False:
166 animClip.wrapMode = WrapMode.ClampForever;
167 break;
168 case LoopType.PingPong:
169 animClip.wrapMode = WrapMode.PingPong;
170 animSettings.loopTime = true;
171 break;
172 default:
173 Debug.LogWarning("Unsupported loop type: " + animation.LoopType.ToString());
174 break;
175 }
176
177 animClip.SetAnimationSettings(animSettings);
178
179 //Debug.Log(string.Format("Setting animation {0} to {1} loop mode (WrapMode:{2} LoopTime:{3}) ", animClip.name, animation.LoopType, animClip.wrapMode, animSettings.loopTime));
180 }
File name: AnimationBuilder.cs
Copy
201 private HashSet202 {
203 HashSet
204 //Could do this recursively - this is easier
205 Stack toProcess = new Stack(mainlineKey.GetChildren(null));
206
207 while (toProcess.Count > 0)
208 {
209 var next = toProcess.Pop();
210
211 paths.Add(next.RelativePath);
212 SetGameObjectForRef(root, next, time);
213 SetSpriteEvent(animClip, time, next);
214
215 var children = mainlineKey.GetChildren(next);
216 foreach (var child in children) toProcess.Push(child);
217 }
218
219 return paths;
220 }
File name: AnimationBuilder.cs
Copy
312 private void BuildSpriteChangeCurve(ref AnimationClip clip, KeyValuePair313 {
314 // First you need to create Editor Curve Binding
315 EditorCurveBinding curveBinding = new EditorCurveBinding();
316
317 // I want to change the sprites of the sprite renderer, so I put the typeof(SpriteRenderer) as the binding type.
318 curveBinding.type = typeof(SpriteRenderer);
319
320 // Regular path to the GameObject that will be changed
321 curveBinding.path = timeline.Key;
322
323 // This is the property name to change the sprite of a sprite renderer
324 curveBinding.propertyName = "m_Sprite";
325
326 // An array to hold the object keyframes
327 ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[timeline.Value.Count];
328
329 int i = 0;
330 foreach (var key in timeline.Value)
331 {
332 keyFrames[i] = new ObjectReferenceKeyframe();
333 // set the time
334 keyFrames[i].time = key.Time;
335 // set reference for the sprite you want
336 keyFrames[i].value = key.Sprite;
337 i++;
338
339 }
340
341 AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames);
342 }
File name: AnimationBuilder.cs
Copy
358 /// Creates an event to change the sprite for the specified Ref (if applicable)
363 private void SetSpriteEvent(AnimationClip clip, float time, Ref reference)
364 {
365 var spriteKey = reference.Referenced as SpriteTimelineKey;
366 //Only add event for SpriteTimelineKey objects
367 if (spriteKey != null)
368 {
369 if (time < 0) time = spriteKey.Time;
370 if (!spriteChangeKeys.ContainsKey(reference.RelativePath))
371 {
372 spriteChangeKeys[reference.RelativePath] = new List
373 }
374
375 //Add the key to the dictionary to later build all the curves at once.
376 spriteChangeKeys[reference.RelativePath].Add(new SpriteChangeKey() { Time = time, Sprite = AssetUtils.GetSpriteAtPath(spriteKey.File.Name, spriteBaseFolder) });
377 }
378 }
File name: AnimationCurveBuilder.cs
Copy
45 public void AddCurves(AnimationClip animClip)
46 {
47 foreach(var kvp in curveCache)
48 {
49 var curves = kvp.Value.Curves;
50 //Position curves
51 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localPosition.x", curves[(int)AnimationCurveIndex.LocalPositionX]);
52 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localPosition.y", curves[(int)AnimationCurveIndex.LocalPositionY]);
53 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localPosition.z", curves[(int)AnimationCurveIndex.LocalPositionZ]);
54
55 //Rotation curves
56 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localRotation.x", curves[(int)AnimationCurveIndex.LocalRotationX]);
57 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localRotation.y", curves[(int)AnimationCurveIndex.LocalRotationY]);
58 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localRotation.z", curves[(int)AnimationCurveIndex.LocalRotationZ]);
59 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localRotation.w", curves[(int)AnimationCurveIndex.LocalRotationW]);
60
61 //Scale curves
62 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localScale.x", curves[(int)AnimationCurveIndex.LocalScaleX]);
63 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localScale.y", curves[(int)AnimationCurveIndex.LocalScaleY]);
64 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(Transform), "localScale.z", curves[(int)AnimationCurveIndex.LocalScaleZ]);
65
66 //IsActive curve
67 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(GameObject), "m_IsActive", curves[(int)AnimationCurveIndex.IsActive]);
68
69 if (kvp.Value.IsSpriteKey)
70 {
71 //Color Tint curve
72 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(SpriteRenderer), "m_Color.r", curves[(int)AnimationCurveIndex.ColorR]);
73 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(SpriteRenderer), "m_Color.g", curves[(int)AnimationCurveIndex.ColorG]);
74 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(SpriteRenderer), "m_Color.b", curves[(int)AnimationCurveIndex.ColorB]);
75 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(SpriteRenderer), "m_Color.a", curves[(int)AnimationCurveIndex.ColorA]);
76 SetCurveIfNotEmpty(ref animClip, kvp.Key, typeof(SortingOrderUpdate), "SortingOrder", curves[(int)AnimationCurveIndex.ZIndex]);
77 }
78 }
79
80 //animClip.EnsureQuaternionContinuity();
81 }
File name: AnimationCurveBuilder.cs
Copy
120 private void SetCurveIfNotEmpty(ref AnimationClip clip, string path, Type component, string property, AnimationCurve curve)
121 {
122 if (curve.keys.Length > 0)
123 {
124 clip.SetCurve(path, component, property, curve);
125 }
126 }
File name: ScmlPostProcessor.cs
Copy
66 static void ImportScml(string assetPath)
67 {
68 string folderPath = Path.GetDirectoryName(assetPath);
69
70 //Load the SCML as XML
71 var doc = new XmlDocument();
72 doc.Load(assetPath);
73
74 //Parse the SCML file
75 var scml = new Spriter.ScmlObject(doc);
76
77 //TODO: Verify that all files/folders exist
78 var pb = new PrefabBuilder();
79 foreach (var entity in scml.Entities)
80 {
81 //TODO: Settings file to customize prefab location
82 var prefabPath = Path.Combine(folderPath, entity.Name + ".prefab");
83
84 //Change to forward slash for asset database friendliness
85 prefabPath = prefabPath.Replace('\\', '/');
86
87 //Either instantiate the existing prefab or create a new one
88 GameObject go;
89 var prefabGo = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
90 if (prefabGo == null)
91 {
92 go = new GameObject();
93 prefabGo = PrefabUtility.CreatePrefab(prefabPath, go, ReplacePrefabOptions.ConnectToPrefab);
94 }
95 else
96 {
97 go = GameObject.Instantiate(prefabGo) as GameObject;
98
99 var oldAnimator = go.GetComponent
100 if (oldAnimator) GameObject.DestroyImmediate(oldAnimator);
101 }
102
103 //Build the prefab based on the supplied entity
104 pb.MakePrefab(entity, go, folderPath);
105
106 var animator = go.AddComponent
107
108
109
110 //Add animations to prefab object
111 var anim = new AnimationBuilder();
112 var allAnimClips = anim.BuildAnimationClips(go, entity, prefabPath);
113 AssetDatabase.SaveAssets();
114
115 var animatorControllerPath = Path.ChangeExtension(prefabPath, "controller");
116 UnityEditor.Animations.AnimatorController oldController = (UnityEditor.Animations.AnimatorController)AssetDatabase.LoadAssetAtPath(animatorControllerPath, typeof (UnityEditor.Animations.AnimatorController));
117 UnityEditor.Animations.AnimatorController controller = oldController;
118
119 if (!oldController)
120 {
121 controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(animatorControllerPath);
122 foreach (var animationClip in allAnimClips)
123 {
124 if (animationClip)
125 {
126 //UnityEditor.Animations.AnimatorController.AddAnimationClipToController(controller, animationClip);
127 }
128 }
129 }
130 UnityEditor.Animations.AnimatorController.SetAnimatorController(animator, controller);
131 go.SetActive(true);
132 //Update the prefab
133 PrefabUtility.ReplacePrefab(go, prefabGo, ReplacePrefabOptions.ConnectToPrefab);
134
135 //Add a generic avatar - because why not?
136 //TODO: May need to eventually break this into a separate class
137 // ie: if we want to look for a root motion node by naming convention
138 //var avatar = AvatarBuilder.BuildGenericAvatar(go, "");
139 //avatar.name = go.name;
140 //AssetDatabase.AddObjectToAsset(avatar, prefabPath);
141
142 GameObject.DestroyImmediate(go);
143
144 AssetDatabase.SaveAssets();
145 }
146 }
File name: AnimationCurveUtils.cs
Copy
189 public static void SetAnimationSettings(this AnimationClip animClip, AnimationClipSettings settings)
190 {
191 //Use reflection to get the internal method
192 BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.NonPublic;
193 MethodInfo mInfo = typeof(AnimationUtility).GetMethod("SetAnimationClipSettings", bindingFlags);
194 mInfo.Invoke(null, new object[] { animClip, settings });
195 }
AnimationClip 199 lượt xem
Gõ tìm kiếm nhanh...