Advertisement

Interpolating movement based on character turning speed

Started by March 18, 2018 08:54 PM
4 comments, last by MarcusAseth 6 years, 9 months ago

Hi guys, as the title says I'm trying to interpolate movement based on character turning speed, I first put my tought process on paper but I'm getting some odd behaviour I am not sure about in the code, so before trying and debug it I would like to submit the math to you to be sure I am doing it right in the first place :P

In the image below, my reasoning. So the orange vector is what I am trying to obtain.

The code inside the unreal engine is this 


CurrentMovingDirection = CurrentMovingDirection + ((DesiredMovingDirection - (-CurrentMovingDirection)) * MovementTurnRate);

But I am also assuming that `(-CurrentMovingDirection)` is returning me the vector with the components with a flipped sign, and if that is not the case, that's already a mistake I think :\

Also I wrote "NewVelocity" but I meant "NewPosition", and T is assumed to me 0.5 in the image

EU1VxFH.png

Well, I found my bug... Apparently, if you do this  in UnrealEngine  


FVector DesiredMovingDirection{};

You are not getting a vector with the elements zeroed out, I was getting a vector with X = -223476324987etc....  impossible number :|

so the right way is:


FVector DesiredMovingDirection = FVector::ZeroVector;

Why Epic?! x_x

Advertisement

Oh my bad, it has nothing to do with Epic, is C++. That zero initialization syntax doesn't work on class, and I think I once knew and forgot :\

Also in the image below I'm getting smooth movement so I think it is working, only problem is if I apply an input 180° opposite to the red arrow in the image below, the direction won't change...I'll try figuring this out on paper (even though I think that could be because the resulting vector on two 180° apart vectors is just a scalad down version of the current direction vector, which then get normalized back to 1, so it never gets to actually rotate toward the second) but if you guys have any tips, I'll appreciate :P

JeyMhzA.png

Well, now I'm thinking would be smarter if my TurnRate is expressed in Degree/second and I can just add a degree rotation to the current direction vector as to bring it closer toward the input vector from the gamepad.

Though I am not quite sure of how I can achieve that, on the math side x_x  Can someone point me toward some useful page? :P

Nevermind guys, I think I've got it right now. 

The solution was to get away from the keyboard and just scrible on paper, so now I got this (code below)

Though I'm always calculating two vectors (one that goes toward the target clockwise, the other counterclockwise) and picking the one with the smaller dot product with the desired moving direction, so I wonder if there is some better way to do it in a single calculation :\


FVector AShooterPawn::CalculateNewMovingAngle(FVector const & MovingDirection, FVector const & DesiredDirection, float const TurnRate)
{
	//exit early if no input was passed, keep going in the same direction of the last frame
	if (DesiredDirection.IsNearlyZero())
	{
		return MovingDirection;
	}

	float CurrAngle = FMath::Atan2(MovingDirection.Y, MovingDirection.X);
	float DesiredAngle = FMath::Atan2(DesiredDirection.Y, DesiredDirection.X);
	
	//avoid calculation if current TurnRate allows us to reach the DesiredDirection this frame in a single sweep
	if (FMath::Abs(DesiredAngle - CurrAngle) <= FMath::DegreesToRadians(TurnRate))
	{
		return DesiredDirection;
	}

	//find the two vector such that one is TurnRate degree bigger than the MovingDirection
	//and the other is TurnRate degree smaller than the MovingDirection
	float AngleARad = CurrAngle + FMath::DegreesToRadians(TurnRate);
	float AngleBRad = CurrAngle - FMath::DegreesToRadians(TurnRate);
	FVector AngleA(FMath::Cos(AngleARad), FMath::Sin(AngleARad), 0.f);
	FVector AngleB(FMath::Cos(AngleBRad), FMath::Sin(AngleBRad), 0.f);

	//return the angle wich has the highest DotProduct with the current moving direction
	return (Dot(AngleA, DesiredDirection) > Dot(AngleB, DesiredDirection))? AngleA : AngleB;
}

 

This topic is closed to new replies.

Advertisement