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

Transitions do not play the full animation #99

Open
KamiGrave opened this issue Oct 3, 2018 · 15 comments
Open

Transitions do not play the full animation #99

KamiGrave opened this issue Oct 3, 2018 · 15 comments

Comments

@KamiGrave
Copy link

I've got an idle animation that lasts for 1000 milliseconds and an attack animation that lasts for 600. On a transition with 100 milliseconds of transition time, only the very end of the attack animation plays. This depends on what progress the idle animation is on. If I transition at the start of the animation (near time 0) I see more of the animation. If I wait until the animation is half way through, I only get a 'thrust' as the transition tries to align the animations.

See the attached gif for what's happening inside the example application.

examplebroken

The first shows almost the full swing (what I'd consider to be a near successful transition), the second is the same animation but transitioned half way through the idle animation, and results in a thrust motion (which would be great if it was a thrust attack!).
There's only two animations in the file, the idle and the attack. I removed the others to make it easier to debug. I can provide this file if required.

@rfadeev
Copy link
Contributor

rfadeev commented Oct 9, 2018

Could you please provide Spriter project and code snippet you use to make a transition to be able to reproduce the issue?

@KamiGrave
Copy link
Author

WeeKnights.zip

The code is just the MonoGame example from this repository. I had to edit the Constants file to add the scml file.
I also edited the transition time in the ExampleGame.cs to be 100, instead of 1000. (line 103)

@loodakrawa
Copy link
Owner

This is the intended behaviour. What happens is, animations get interpolated based on a normalised progress. In this example:

Animation A is at 700/1000 ms or 0.7 progress
You transition to B with a 100ms interval.
Animation B starts at 0.7 progress or 600 * 0.7 == 420ms.

Usually, the transitions happen between animations such as walking/running/jumping and this behaviour makes them look more natural. On the other hand, attack animations are usually jumped into straight away i.e. no interpolation.

That being said, this use case is completely valid and I believe the right solution is to expand the interpolation methods with an enum to specify the interpolation mode. Something like:
InterpolationMode.CurrentProgress
InterpolationMode.FromStart

@KamiGrave
Copy link
Author

I did a custom solution which basically involved me passing through the transition time and using that for getting the second animation frames. It's a bit of a hack for the moment to get things working (No idea what would happen if the transition time was longer than the target animation, I guess it would just hang at the last frame or loop).
I am using the transitions to smooth out the move from one attack to another in a combo system, the attacks are data driven so creating bespoke animations isn't really an option. The hack I've done to the transition logic appears to be working for me, but it's not a very clean solution as you basically lose the ability to interpolate using the normalised progress as before.

@alextilkin
Copy link

alextilkin commented Jan 4, 2020

I'm running into this issue, and I can't seem to come up with a good way of transitioning to attack animations. I tried KamiGrave's solution but it doesn't really fix the problem completely for me. I'd be happy to give up the normalized transitions entirely if I could get it to cleanly transition to the start of animations. The way things are set up now transitions are basically useless for anything like an attack.

@KamiGrave
Copy link
Author

@luciddream00 The solution I came up with was a bit of a hack and is in my own fork of the SpriterDotNet repo. There's probably a much cleaner solution that I didn't look for under the expectation that this may be fixed at some point in the main repo (this one) and I didn't want to clash with it. In retrospect, I should probably have introduced a clean solution and set it up for a pull request.
As it happens, I'm no longer using SpriterDotNet or MonoGame, but this was one issue I resolved before moving onto an engine.
It should be noted as well that I had to modify the animations as well because of the transition time from one attack to the other. There was also issues about events firing during the transitions that made things a bit difficult too.

@alextilkin
Copy link

alextilkin commented Jan 4, 2020

Thanks for the info. I think I came up with a pretty clean solution that loses the normalized transitions, but just uses simple transitions that work more like you'd expect for attacks and whatnot. If anyone else runs into this in the future, here is what I did:

At line 192 in the Animator class, I changed

if (NextAnimation != null && totalTransitionTime != 0.0f)
{
	elapsed += elapsed * factor * CurrentAnimation.Length / NextAnimation.Length;
	transitionTime += Math.Abs(elapsed);
	factor = transitionTime / totalTransitionTime;
	if (transitionTime >= totalTransitionTime)
	{
		float progress = Progress;
		Play(NextAnimation.Name);
		Progress = progress;
		NextAnimation = null;
	}
}

Time += elapsed;

to

if (NextAnimation != null && totalTransitionTime != 0.0f)
{
	elapsed += elapsed * factor * CurrentAnimation.Length / NextAnimation.Length;

	transitionTime += Math.Abs(elapsed);
	factor = transitionTime / totalTransitionTime;
	if (transitionTime >= totalTransitionTime)
	{
		//float progress = Progress;
		Play(NextAnimation.Name);
		Progress = 0;// progress;
		NextAnimation = null;
	}
}
else
{
	Time += elapsed;
}

and in FrameDataCalculator at line 34 I changed

float targetTimeSecond = targetTime / first.Length * second.Length;

to

float targetTimeSecond = 0;

Basically, all it does is have animations transition from the current animation to the start of the next animation.

@Martenfur
Copy link

@luciddream00 Thanks, this absolutely solved transition issues. This should really be the default behavior, I dunno why the author thinks janky transitions are better.

@loodakrawa
Copy link
Owner

@luciddream00 Thanks, this absolutely solved transition issues. This should really be the default behavior, I dunno why the author thinks janky transitions are better.

I did it so people like you, who have nothing better to do than criticizing open source projects instead of actually contributing, have something to do.

@Martenfur
Copy link

I did it so people like you, who have nothing better to do than criticizing open source projects instead of actually contributing, have something to do.

I mean. I could make my fork public and submit my changes, if you wanna. But you probably won't like them and won't merge them anyway, since you got pull requests open for two years.

@loodakrawa
Copy link
Owner

I did it so people like you, who have nothing better to do than criticizing open source projects instead of actually contributing, have something to do.

I mean. I could make my fork public and submit my changes, if you wanna. But you probably won't like them and won't merge them anyway, since you got pull requests open for two years.

You are probably right. Based on the lack of understanding you showed when you opened other issues in the past few days I highly doubt your code would improve this project in any way.

@alextilkin
Copy link

For what it's worth, I very much appreciate the library even if I had to fiddle with it a bit to act the way I want.

@loodakrawa
Copy link
Owner

For what it's worth, I very much appreciate the library even if I had to fiddle with it a bit to act the way I want.

I'm very glad to hear that. That was my main motivation to go open source in the first place - hopefully help someone with the code I planned to write for myself anyway. I am trying to maintain it and improve it, but sometimes it's difficult to give it all the love it deserves due to, well, life happening. Since I'm already working on version 2 (albeit slowly) which is almost a complete rewrite, I'm less active in improving the current version since I'll address all these things (like this issue) directly in the next version.

@Martenfur
Copy link

You are probably right. Based on the lack of understanding you showed when you opened other issues in the past few days I highly doubt your code would improve this project in any way.

Your tendency to overengineer and my degree of understanding don't have much in common, tbh.
And damn, why so salty? I am genuinely trying to help your thingy and you're behaving like a total dick.

@loodakrawa
Copy link
Owner

You are probably right. Based on the lack of understanding you showed when you opened other issues in the past few days I highly doubt your code would improve this project in any way.

Your tendency to overengineer and my degree of understanding don't have much in common, tbh.
And damn, why so salty? I am genuinely trying to help your thingy and you're behaving like a total dick.

You've been nothing but rude and condescending and you haven't suggested a single useful thing. If this is your way of "trying to help", go do it somewhere else.

Repository owner deleted a comment from Martenfur Jul 16, 2020
Repository owner deleted a comment from Martenfur Jul 16, 2020
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

5 participants