1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

Cat-like pawns

Discussion in 'Programming' started by dataangel, Aug 4, 2004.

  1. dataangel

    dataangel New Member

    Joined:
    Apr 11, 2004
    Messages:
    184
    Likes Received:
    0
    For my mod pawns can spin in the air alot and bounce when they hit the ground, but when they finally land I want them to always land on their feet, like a cat.

    I've checked this code exhaustively and can't figure out what's wrong. Half the time when the pawn lands it just instantaneously snaps into upright position, the other half of the time it does some very quick rotating right before it lands, like it's attempting to rotate to upright position at the last second.

    Any help is much appreciated. I've tried to comment as much as possible. The code applies a motion equation from basic physics, but on rotators. My (lack of) understanding rotator maths maybe the problem, but nothing on the wiki sticks out. Here is the relevant code:

    Code:
    event ModifyVelocity(float DeltaTime, vector OldVelocity)
    {
    	//Where custom rotation system is implemented because DesiredRotation
    	//doesn't work with PHYS_Falling
    	if(bIsSpinning)
    	{
    		//Drag, always wins out, notice how it's always opposite rotational velocity
    		rotAcceleration += InvertRot(rotVelocity, true) * rotDeAccelFactor;
    
    		//Dynamic Gravity, so you'll land on your feet
                    //Not sure if DeltaTime should be commented out but tried both ways and niether works.
    		rotAcceleration += GetCurrentRotGravity();// * DeltaTime;
    
    		//Update rotational velocity
    		rotVelocity += rotAcceleration * DeltaTime;
    
    		//Put the changes ingame
    		SetRotation(Rotation + (rotVelocity * DeltaTime));
    	}
    }
    
    //As pawn falls, roll and pitch approach 0, so player
    //always lands on their feet. (in theory)
    function rotator GetCurrentRotGravity()
    {
    	local rotator rotGravity;
    	local vector HitLocation;
    	local vector HitNormal;
    	local float Displacement;
    	local float TimeToImpact;
    	local vector headPos;
    	local rotator standingRot;
    
    	rotGravity = rot(0,0,0);
    
    	//This is only for when pawns are falling
    	if(Velocity.Z >= 0)
    	{
    		return rot(0,0,0);
    	}
    
    	//Find how far away we are from the ground
    	Trace(HitLocation, HitNormal, Location + vect(0,0,-100000),, false);
    
    	//Location is just the center of the pawn. This is not the most likely
    	//part of the pawn to hit the ground first. So we subtract the collision
    	//height. If landing on head or feet, will work perfectly, if landing on
    	//side will get to standingRot a little early, insignificant.
    	headPos = vect(0,0,0);
    	headPos.Z = -CollisionHeight;
    
    	//Negative because the sign indicates the direction (down)
    	Displacement = -VSize(HitLocation - (Location+headPos));
    
    	//Test if the pawn will be going fast enough when it lands to trigger
    	//bouncing. If so hold off, we don't want them to land on their feet yet.
    	if(ShouldBounce(Displacement))
    	{
    		return rot(0,0,0);
    	}
    
    	//Rearranging of x=vi*t + .5*a*t^2, solving for x
    	//So it solves the quadratic: .5*PhysicsVolume.Gravity.Z*t^2 + Velocity.Z*t - Displacement
    	//It automatically throws out imaginary and negative answers and returns the one left.
    	//The log reports if both answers are negative or imaginary, but that never happens
    	TimeToImpact = PositiveRealQuadraticSolver(0.5*(PhysicsVolume.Gravity.Z), Velocity.Z, -Displacement);
    
    	//Standing just means pitch and roll have to be zero. Yaw could be anything
    	//so we make sure standingRot and Rotation's yaw are equal so it's ignored
    	standingRot = rot(0,0,0);
    	standingRot.Yaw = Rotation.Yaw;
    
    	//Based on rearranging x=vi*t + .5*a*t^2 where a = rotAcceleration + rotGravity
    	//So: Ag = 2*((xf-xi) - Vi*t)/(t^2) - A
    	rotGravity = (2*(standingRot - Rotation - rotVelocity*TimeToImpact)/(TimeToImpact ** 2)) - rotAcceleration;
    
    	return rotGravity;
    }
    
    P.S. I'm aware the code hasn't been optimized. It will be in the final version :)
     
    Last edited: Aug 4, 2004

Share This Page