logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Issue #64. LoopAnim fails to initiate an animation (Read 296 times)
Masterkent
Developer Team
Offline



Posts: 1091
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Issue #64. LoopAnim fails to initiate an animation
Jun 2nd, 2018 at 2:08pm
Print Post  
Sometimes a call to LoopAnim does not result in playing any animation. Then a subsequent call to FinishAnim may either return the control immediately or initiate an endless waiting for finishing an animation.

The following video shows how to reproduce this glitch in game:
https://www.youtube.com/watch?v=SqC3bRIiqNs

In this case, FinishAnim returns immediately after calling PlayThreatening which indirectly invokes LoopAnim('Swim', -1.0/WaterSpeed,, 0.5).

Code
Select All
FaceEnemy:
	if ( Enemy == none || Enemy.health <= 0 || Enemy.bdeleteme || Enemy == self )
		GotoState('Attacking');
	Acceleration = vect(0,0,0);
	if (NeedToTurn(enemy.Location))
	{
		PlayTurning();
		TurnToward(Enemy);
		TweenToPatrolStop(0.2);
		FinishAnim();
		NextAnim = '';
	}

Threaten:
	if ( (Enemy == none) ||  (Enemy.Health <=0) || (Enemy.bDeleteme) || (Enemy == self)
			|| (AttitudeTo(Enemy) < ATTITUDE_Threaten) )
		GotoState('Attacking');

	PlayThreatening();
	FinishAnim();

	if ( (Enemy == none) ||  (Enemy.Health <=0) || (Enemy.bDeleteme) || (Enemy == self)
			|| (AttitudeTo(Enemy) < ATTITUDE_Threaten) )
		GotoState('Attacking');

	if (Orders == 'Guarding')
	{ //stay between enemy and guard object
		If (Enemy.bIsPlayer &&
			(VSize(Enemy.Location - OrderObject.Location) < OrderObject.CollisionRadius + 2 * CollisionRadius + MeleeRange))
		{
			AttitudeToPlayer = ATTITUDE_Hate;
			GotoState('Attacking');
		}
	}
	else if (FRand() < 0.9 - Aggressiveness) //mostly just turn
		Goto('FaceEnemy');
	else if (VSize(Enemy.Location - Location) < 2.5 * (CollisionRadius + Enemy.CollisionRadius + MeleeRange))
		Goto('FaceEnemy'); 


When the mob does not need to turn, there is no any waiting function call between label 'FaceEnemy' and evaluation of Goto('FaceEnemy'), so we have an infinite loop here:

Quote:
Warning: SkaarjScout dark.SkaarjScout1 Infinite loop in state code - possibly because of state change to State UnrealShare.ScriptedPawn.Threatening during execution of subexpression!

I've seen such "frozen" mobs many times in online games, but I'm not sure if this is the cause of it (monsters with regular attitude towards players don't seem to freeze so often).

Although it looks like I found some way to hack-fix this particular case on UScript-level, I believe that a proper fix should revise the native implementation of LoopAnim in C++.
  
Back to top
 
IP Logged
 
Smirftsch
Forum Administrator
*****
Offline



Posts: 7725
Location: at home
Joined: Apr 30th, 1998
Gender: Male
Re: Issue #64. LoopAnim fails to initiate an animation
Reply #1 - Jun 3rd, 2018 at 6:49am
Print Post  
will look into it.
  

Sometimes you have to lose a fight to win the war.
Back to top
WWWICQ  
IP Logged
 
Smirftsch
Forum Administrator
*****
Offline



Posts: 7725
Location: at home
Joined: Apr 30th, 1998
Gender: Male
Re: Issue #64. LoopAnim fails to initiate an animation
Reply #2 - Jun 4th, 2018 at 5:07pm
Print Post  
mmh, right now I see no simple fix for it, how would your hackfix look like? Perhaps this gives me an other idea.
  

Sometimes you have to lose a fight to win the war.
Back to top
WWWICQ  
IP Logged
 
.:..:
Board Moderator
Developer Team
*****
Offline



Posts: 1430
Location: Finland
Joined: Aug 16th, 2005
Gender: Male
Re: Issue #64. LoopAnim fails to initiate an animation
Reply #3 - Jun 4th, 2018 at 6:37pm
Print Post  
Well I would suggest a fix in FinishAnim code instead (sent PM to Smirf with the code).
Because currently it forced bLoopAnim to false, and skip state code polling if AnimFrame is past LastFrame, so I suggest not setting it to false and skip the AnimFrame<LastFrame check for looping animations, and as a failsafe, initiate Sleep(0) if polling isn't started.
  

Shivaxi wrote on Jul 25th, 2013 at 12:50pm:
...and now im stuck trying to fix everything you broke for the next 227 release xD Tongue

(ಠ_ಠ)
Back to top
ICQYIM  
IP Logged
 
Masterkent
Developer Team
Offline



Posts: 1091
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Re: Issue #64. LoopAnim fails to initiate an animation
Reply #4 - Jun 4th, 2018 at 8:54pm
Print Post  
Smirftsch wrote on Jun 4th, 2018 at 5:07pm:
how would your hackfix look like? Perhaps this gives me an other idea.

There are two options:

1) since I observed the bug only when AnimRate < 0 && AnimFrame < 0 after calling LoopAnim, I'd set AnimFrame to 0 (thus, skipping the tweening phase) when this condition is detected:

Code
Select All
PlayTurning();
if (AnimRate < 0 && AnimFrame < 0)
	AnimFrame = 0;
 


Code
Select All
PlayThreatening();
if (AnimRate < 0 && AnimFrame < 0)
	AnimFrame = 0; 


and so on.

2) Alternatively, the implementation of Actor.IsAnimating

Code
Select All
	UBOOL IsAnimating() const
	{
		return
			(AnimSequence!=NAME_None)
		&&	(AnimFrame>=0 ? AnimRate!=0.f : TweenRate!=0.f);
	} 


suggests that AnimFrame < 0 && TweenRate == 0 makes no sense if the actor is supposed to play an animation, so it's possible to adjust AnimFrame as shown below:

Code
Select All
PlayTurning();
if (AnimFrame < 0 && TweenRate == 0)
	AnimFrame = 0;
 


Code
Select All
PlayThreatening();
if (AnimFrame < 0 && TweenRate == 0)
	AnimFrame = 0; 


and so on.

However, I don't know how exactly LoopAnim works and whether the methods above can serve a suitable resolution. I presume, all this function does is changing some actor properties (AnimRate, AnimFrame, TweenRate, etc) based on the values of these actor properties right before the call to LoopAnim and the arguments passed to the function. If I knew the exact algorithm, I could think about a proper fix.

You should figure out how an execution of LoopAnim may lead to the condition AnimFrame < 0 && TweenRate == 0 in the first place. As far as I understand, negative values of AnimFrame are used for tweening, so in case of TweenRate == 0 (there is no tweening) AnimFrame should be set to have a non-negative value. Or maybe AnimFrame is set correctly, but TweenRate is not.

.:..: wrote on Jun 4th, 2018 at 6:37pm:
Well I would suggest a fix in FinishAnim code instead (sent PM to Smirf with the code).

Any changes in FinishAnim won't resolve the issue with missing animation after calling LoopAnim in general.
« Last Edit: Jun 5th, 2018 at 7:19am by Masterkent »  
Back to top
 
IP Logged
 
Smirftsch
Forum Administrator
*****
Offline



Posts: 7725
Location: at home
Joined: Apr 30th, 1998
Gender: Male
Re: Issue #64. LoopAnim fails to initiate an animation
Reply #5 - Jun 5th, 2018 at 5:19am
Print Post  
Thank you, this gives me indeed a lot of more insight.

I need to log some yet, but it appears that TweenRate is negative if TweenTime is negative, which is by default -1.0 if not set.
AnimFrame however is in almost any case: AnimFrame = -1.0f/Seq->NumFrames;
except if no other condition is met, then it is
TweenRate = 0.0f;
AnimFrame = 0.001f;

(really need to log some, I think there are some ways AnimFrame < 0 && TweenRate == 0 could happen)

But to fix FinishAnim (too) does make sense either way I suppose.

Edited:
It seems that the fix in FinishAnim is the way to go, every other change I tried interferes with tweening and causes weird movements. I couldn't observe any missing animations logs anymore after adding it either.
« Last Edit: Jun 5th, 2018 at 8:36am by Smirftsch »  

Sometimes you have to lose a fight to win the war.
Back to top
WWWICQ  
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo