Keyframe









How do I use Keyframe
Below are practical examples compiled from projects for learning and reference purposes

Featured Snippets


File name: PhotonTransformViewPositionModel.cs Copy
35     public AnimationCurve InterpolateSpeedCurve = new AnimationCurve( new Keyframe[] {
36                                                                               new Keyframe( -1, 0, 0, Mathf.Infinity ),
37                                                                               new Keyframe( 0, 1, 0, 0 ),
38                                                                               new Keyframe( 1, 1, 0, 1 ),
39                                                                               new Keyframe( 4, 4, 1, 0 ) } );
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
222         private void SetGameObjectForRef(GameObject root, Ref childRef, float time)
223         {
224             TimelineKey key = childRef.Referenced;
225             if (time < 0) time = key.Time;
226
227             TimelineKey lastKey;
228             lastKeyframeCache.TryGetValue(key.Timeline, out lastKey);
229
230             //Get the relative path based on the current hierarchy
231             var relativePath = childRef.RelativePath;
232
233             //If this is the root, skip it
234             if (string.IsNullOrEmpty(relativePath))
235             {
236                 Debug.Log("Skipping root node in SetGameObjectForRef (SHOULD NEVER HAPPEN)");
237                 return;
238             }
239
240
241             //Find the gameObject based on relative path
242             var transform = root.transform.Find(relativePath);
243             if (transform == null)
244             {
245                 Debug.LogError("ERROR: Unable to find GameObject at relative path " + relativePath);
246                 return;
247             }
248
249             var gameObject = transform.gameObject;
250             gameObject.SetActive(true);
251
252             //Get transform data from ref
253             Vector3 localPosition;
254             Vector3 localScale;
255             Vector3 localEulerAngles;
256
257             childRef.BakeTransforms(out localPosition, out localEulerAngles, out localScale);
258
259             //Set the current GameObject's transform data
260             transform.localPosition = localPosition;
261             transform.localScale = localScale;
262
263             //Spin the object in the correct direction
264             var oldEulerAngles = transform.localEulerAngles;
265
266             if (oldEulerAngles.z - localEulerAngles.z > 180) localEulerAngles.z += 360;
267             else if (localEulerAngles.z - oldEulerAngles.z > 180) localEulerAngles.z -= 360;
268             /*
269             switch(childRef.Unmapped.Spin)
270             {
271                 case SpinDirection.Clockwise:
272                     while (oldEulerAngles.z > localEulerAngles.z) localEulerAngles.z += 360;
273                     break;
274                 case SpinDirection.CounterClockwise:
275                     while (oldEulerAngles.z < localEulerAngles.z) localEulerAngles.z -= 360;
276                     break;
277             }*/
278             transform.localEulerAngles = localEulerAngles;
279
280             int zIndex = -1;
281             var spriteKey = key as SpriteTimelineKey;
282             if (spriteKey != null)
283             {
284                 zIndex = ((ObjectRef)childRef).ZIndex;
285                 //transform.GetComponent().sortingOrder = zIndex;
286             }
287
288             acb.SetCurve(root.transform, transform, time, lastKey, zIndex);
289
290
291             //Get last-used game object for this Timeline - needed to clean up reparenting
292             GameObject lastGameObject;
293             if (lastGameObjectCache.TryGetValue(key.Timeline, out lastGameObject) && gameObject != lastGameObject)
294             {
295                 //Let Unity handle the global->local position cruft for us
296                 lastGameObject.transform.position = transform.position;
297                 lastGameObject.transform.eulerAngles = transform.eulerAngles;
298
299                 //TODO: Also need to do something about scale - this is a little more tricky
300                 lastGameObject.transform.localScale = localScale;
301
302                 //Deactivate the old object
303                 lastGameObject.SetActive(false);
304
305                 acb.SetCurve(root.transform, lastGameObject.transform, time, lastKey);
306             }
307
308             //Set cached value for last keyframe
309             lastKeyframeCache[key.Timeline] = key;
310         }
File name: AnimationBuilder.cs Copy
312         private void BuildSpriteChangeCurve(ref AnimationClip clip, KeyValuePair> timeline)
313         {
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: AnimationCurveBuilder.cs Copy
110         public void SetCurveActiveOnly(Transform root, Transform current, float time)
111         {
112             var path = AnimationUtility.CalculateTransformPath(current, root);
113             var obj = GetOrCreateAnimationCurves(path);
114
115             //IsActive curve
116             float val = (current.gameObject.activeInHierarchy) ? 1.0f : 0.0f;
117             obj.Curves[(int)AnimationCurveIndex.IsActive].AddKey(new Keyframe(time, val, float.PositiveInfinity, float.PositiveInfinity) { tangentMode = 0 });
118         }
File name: AnimationCurveBuilder.cs Copy
128         private void UpdateTransformCurve(ObjectCurves obj, Transform current, float time, TimelineKey lastTimelineKey, int zIndex = -1)
129         {
130             float val;
131             //IsActive curve
132             val = (current.gameObject.activeSelf) ? 1.0f : 0.0f;
133             obj.Curves[(int)AnimationCurveIndex.IsActive].AddKey(new Keyframe(time, val, float.PositiveInfinity, float.PositiveInfinity) { tangentMode = 0 });
134
135             //Position curves
136             obj.Curves[(int)AnimationCurveIndex.LocalPositionX].AddKey(new Keyframe(time, current.localPosition.x) { tangentMode = 0 }, lastTimelineKey);
137             obj.Curves[(int)AnimationCurveIndex.LocalPositionY].AddKey(new Keyframe(time, current.localPosition.y) { tangentMode = 0 }, lastTimelineKey);
138             obj.Curves[(int)AnimationCurveIndex.LocalPositionZ].AddKey(new Keyframe(time, current.localPosition.z, float.PositiveInfinity, float.PositiveInfinity)); //Z value always has instant transition
139
140             //Rotation curves
141             var quat = Quaternion.Euler(current.localEulerAngles);
142             obj.Curves[(int)AnimationCurveIndex.LocalRotationX].AddKey(new Keyframe(time, quat.x) { tangentMode = 0 }, lastTimelineKey);
143             obj.Curves[(int)AnimationCurveIndex.LocalRotationY].AddKey(new Keyframe(time, quat.y) { tangentMode = 0 }, lastTimelineKey);
144             obj.Curves[(int)AnimationCurveIndex.LocalRotationZ].AddKey(new Keyframe(time, quat.z) { tangentMode = 0 }, lastTimelineKey);
145             obj.Curves[(int)AnimationCurveIndex.LocalRotationW].AddKey(new Keyframe(time, quat.w) { tangentMode = 0 }, lastTimelineKey);
146
147             //Scale curves
148             obj.Curves[(int)AnimationCurveIndex.LocalScaleX].AddKey(new Keyframe(time, current.localScale.x) { tangentMode = 0 }, lastTimelineKey);
149             obj.Curves[(int)AnimationCurveIndex.LocalScaleY].AddKey(new Keyframe(time, current.localScale.y) { tangentMode = 0 }, lastTimelineKey);
150             obj.Curves[(int)AnimationCurveIndex.LocalScaleZ].AddKey(new Keyframe(time, current.localScale.z) { tangentMode = 0 }, lastTimelineKey);
151
152             //Sprite Curves
153             var spriteTimelineKey = lastTimelineKey as SpriteTimelineKey;
154             if (spriteTimelineKey != null)
155             {
156                 obj.IsSpriteKey = true;
157                 obj.Curves[(int)AnimationCurveIndex.ColorR].AddKey(new Keyframe(time, spriteTimelineKey.Tint.r) { tangentMode = 0 }, lastTimelineKey);
158                 obj.Curves[(int)AnimationCurveIndex.ColorG].AddKey(new Keyframe(time, spriteTimelineKey.Tint.g) { tangentMode = 0 }, lastTimelineKey);
159                 obj.Curves[(int)AnimationCurveIndex.ColorB].AddKey(new Keyframe(time, spriteTimelineKey.Tint.b) { tangentMode = 0 }, lastTimelineKey);
160                 obj.Curves[(int)AnimationCurveIndex.ColorA].AddKey(new Keyframe(time, spriteTimelineKey.Tint.a) { tangentMode = 0 }, lastTimelineKey);
161                 obj.Curves[(int)AnimationCurveIndex.ZIndex].AddKey(new Keyframe(time, zIndex, float.PositiveInfinity, float.PositiveInfinity));
162             }
163         }
File name: AnimationCurveUtils.cs Copy
36         public static void AddKey(this AnimationCurve curve, Keyframe keyframe, TimelineKey lastKey)
37         {
38             var keys = curve.keys;
39
40             //Early out - if this is the first key on this curve just add it
41             if (keys.Length == 0)
42             {
43                 curve.AddKey(keyframe);
44                 return;
45             }
46
47             if (lastKey == null)
48             {
49                 Debug.Log(string.Format("ERROR: NULL lastkey passed to AddKey when curve contains {0} keys", keys.Length));
50                 return;
51             }
52
53             //Get the last keyframe
54             Keyframe lastKeyframe = keys[keys.Length - 1];
55
56             //If no TimelineKey is supplied, default to Linear curve
57             CurveType curveType = lastKey.CurveType;
58
59             switch (curveType)
60             {
61                 case CurveType.Instant:
62                     lastKeyframe.outTangent = 0;
63                     curve.MoveKey(keys.Length - 1, lastKeyframe);
64
65                     keyframe.inTangent = float.PositiveInfinity;
66                     curve.AddKey(keyframe);
67                     break;
68
69                 case CurveType.Linear:
70                     var val = (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
71                     lastKeyframe.outTangent = val;
72                     curve.MoveKey(keys.Length - 1, lastKeyframe);
73
74                     keyframe.inTangent = val;
75                     curve.AddKey(keyframe);
76                     break;
77
78                 case CurveType.Quadratic:
79                     {
80                         //Increase to cubic
81                         var c1 = (2 * lastKey.CurveParams[0]) / 3;
82                         var c2 = 1 - (2 * lastKey.CurveParams[0] + 1) / 3;
83
84                         //Convert [0,1] into unity-acceptable tangents
85                         c1 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
86                         c2 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
87
88                         //Set the out tangent for the previous frame and update
89                         lastKeyframe.outTangent = c1;
90                         curve.MoveKey(keys.Length - 1, lastKeyframe);
91
92                         //Set the in tangent for the current frame and add
93                         keyframe.inTangent = c2;
94                         curve.AddKey(keyframe);
95                         break;
96                     }
97
98                 case CurveType.Cubic:
99                     {
100                         //Get curve parameters
101                         var c1 = lastKey.CurveParams[0];
102                         var c2 = 1 - lastKey.CurveParams[1];
103
104                         //Convert [0,1] into unity-acceptable tangents
105                         c1 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
106                         c2 *= 3 * (keyframe.value - lastKeyframe.value) / (keyframe.time - lastKeyframe.time);
107
108                         //Set the out tangent for the previous frame and update
109                         lastKeyframe.outTangent = c1;
110                         curve.MoveKey(keys.Length - 1, lastKeyframe);
111
112                         //Set the in tangent for the current frame and add
113                         keyframe.inTangent = c2;
114                         curve.AddKey(keyframe);
115                         break;
116                     }
117
118                 default:
119                     Debug.LogWarning("CurveType " + curveType.ToString() + " not yet supported!");
120                     break;
121             }
122         }
File name: AnimationCurveUtils.cs Copy
127         public static void AddLinearKey(this AnimationCurve curve, Keyframe keyframe)
128         {
129             var keys = curve.keys;
130             //Second or later keyframe - make the slopes linear
131             if (keys.Length > 0)
132             {
133                 var lastFrame = keys[keys.Length - 1];
134                 float slope = (keyframe.value - lastFrame.value) / (keyframe.time - lastFrame.time);
135                 lastFrame.outTangent = keyframe.inTangent = slope;
136
137                 //Update the last keyframe
138                 curve.MoveKey(keys.Length - 1, lastFrame);
139             }
140
141             //Add the new frame
142             curve.AddKey(keyframe);
143         }
File name: AnimationCurveUtils.cs Copy
145         public static void AddKeyIfChanged(this AnimationCurve curve, Keyframe keyframe)
146         {
147             var keys = curve.keys;
148             //If this is the first key on this curve, always add
149             //NOTE: Add TWO copies of the first frame, then we adjust the last frame as we move along
150             //This guarantees a minimum of two keys in each curve
151             if (keys.Length == 0 || !ENABLE_KEYFRAME_REDUCATION)
152             {
153                 curve.AddKey(keyframe);
154                 keyframe.time += float.Epsilon;
155                 curve.AddKey(keyframe);
156             }
157             else
158             {
159                 //TODO: This method of keyframe reduction causes artifacts in animations that are supposed to deliberately pause
160                 //Find the last keyframe
161                 Keyframe lastKey = keys[keys.Length - 1];
162                 if (lastKey.time >= keyframe.time)
163                     Debug.LogError("Keyframes not supplied in consecutive order!!!");
164
165                 //Grab 2 frames ago
166                 var last2Key = keys[keys.Length - 2];
167
168                 //If the previous 2 frames were different, add a new frame
169                 if (lastKey.value != last2Key.value)
170                 {
171                     curve.AddKey(keyframe);
172                 }
173                 //The previous frame is redundant - just move it
174                 else
175                 {
176                     curve.MoveKey(keys.Length - 1, keyframe);
177                 }
178             }
179         }

Keyframe 113 lượt xem

Gõ tìm kiếm nhanh...