Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTF/GLB with multiple Animations Doesn't work #476

Closed
KhizarAziz opened this issue Aug 4, 2019 · 8 comments
Closed

GLTF/GLB with multiple Animations Doesn't work #476

KhizarAziz opened this issue Aug 4, 2019 · 8 comments

Comments

@KhizarAziz
Copy link

Using GLTFComponent Script to Load GLB from Assets...
I tried several files which contain some animations.....
*File which contained only 1 animation loaded fine. an example file is
robot.glb.zip

*Files which contained more animations didn't loaded. : e.g
Bee.glb.zip

I got these Errors:

Errors

Error 1. (IndexOutOfRangeException: Index was outside the bounds of the array.)
in Code Below

private static void SetTangentMode(AnimationCurve curve, int keyframeIndex, InterpolationType interpolation)
		{
			var key = curve.keys[keyframeIndex]; // On this line
			switch (interpolation)
			{
				case InterpolationType.CATMULLROMSPLINE:
					key.inTangent = 0;
					key.outTangent = 0;
					break;
				case InterpolationType.LINEAR:
					key.inTangent = GetCurveKeyframeLeftLinearSlope(curve, keyframeIndex);
					key.outTangent = GetCurveKeyframeLeftLinearSlope(curve, keyframeIndex + 1);
					break;
				case InterpolationType.STEP:
					key.inTangent = float.PositiveInfinity;
					key.outTangent = float.PositiveInfinity;
					break;
				default:
					throw new NotImplementedException();
			}
			curve.MoveKey(keyframeIndex, key);			
		}

Error 2: (Unity does not allow you to put two keyframes in with the same time, so this should never occur)
In Code Below:

private static float GetCurveKeyframeLeftLinearSlope(AnimationCurve curve, int keyframeIndex)
		{
			if (keyframeIndex <= 0 || keyframeIndex >= curve.keys.Length)
			{
				return 0;
			}
			var valueDelta = curve.keys[keyframeIndex].value - curve.keys[keyframeIndex - 1].value;
			var timeDelta = curve.keys[keyframeIndex].time - curve.keys[keyframeIndex - 1].time;
			Debug.Assert(timeDelta > 0, "Unity does not allow you to put two keyframes in with the same time, so this should never occur.");

			return valueDelta / timeDelta;
		}

Issue Details:
So basically the problem is when i try to load the file with more than 1 animations, UnityGLTF cant load it. and it crashes on line "var key = curve.keys[keyframeIndex];" in method named "SetTangentMode()" in script "GLTFSceneImporter.cs."

I tried to debug, and the error is due to the array "curve.key[]" because the length of this array is being reduced in size after some iterations in loop. i couldn't figure out why... e.g initially it's length was 34, but after 8th iteration.. the size becomes 33... and after a while 32.... i have no clue why... and when the loop tries to access the 33th index.... its fails.

you can reproduce the error by using the attached files below.

Bee.glb.zip
blue_whale_-_textured.zip
wolf.glb.zip

@supriyarasal
Copy link

Has anyone got a fix for this? I have been trying for multiple animations and it's not going anywhere.Only one is getting played from many animations on load of .gltf file.

@ravip
Copy link

ravip commented Sep 27, 2019

I am also facing this issue.

@HenkHull
Copy link

I am using a different GLTF loader written by a third party and it can import all animations

@jmo7
Copy link

jmo7 commented Oct 4, 2019

HenkHull, what loader are you using?

@nodermatt
Copy link

@HenkHull I would also be interested to hear how you integrated a third-party loader within UnityGLTF.

@enaraartetxe
Copy link

Hi! I came across the same problem a few weeks ago and as I don't see any other solution this is my approach:
As @khizerawan commented "the error is due to the array "curve.key[]" because the length of this array is being reduced in size after some iterations in loop".
That's because according to Unity documentation "If a keyframe already exists at key.time, then the time of the old keyframe's position key[index].time will be used instead" https://docs.unity3d.com/ScriptReference/AnimationCurve.MoveKey.html so whenever two keyframes share the same time, it discards one of them and the array shrinks one size.
To solve it, I've just added a quick check to verify key.inTangent and key.outTangent values are not NaN or Infinite (divided by zero in GetCurveKeyframeLeftLinearSlope) before the curve.MoveKey().

private static void SetTangentMode(AnimationCurve curve, Keyframe[] keyframes, int keyframeIndex, InterpolationType interpolation)
        {
            ...

            if (!float.IsNaN(key.inTangent) && !float.IsNaN(key.outTangent) && !float.IsInfinity(key.inTangent) && !float.IsInfinity(key.outTangent))
                 curve.MoveKey(keyframeIndex, key);
        }

I don't know if there is a better solution out there but I've tested with a couple of models and they work now :)

@EricBeetsOfficial-Opuscope

Hi.

I tested this fix, that's also work for the models I have. Thank you for that.

Is there an official fix or maybe you can create a PR ?

Best,
Eric

@pfcDorn
Copy link
Contributor

pfcDorn commented Feb 9, 2024

Please update to the latest version and open a new issue if the problem persists. Thanks!

@pfcDorn pfcDorn closed this as completed Feb 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants