Announcement

Collapse
No announcement yet.

Wall collision problem

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Wall collision problem

    I have this problem from the beginning of time.

    I have recorded a video to show the problem:



    As you can see in the video, if the wall is totally perpendicular to floor, all works as expected, the engine uses the "movesmooth" command, and the pawn tries to move to the left or right to go around the obstacle.

    But when the wall is not totally perpendicular, the pawn tries to jump. Seems that engine does a trace at the bottom, and / or another trace a bit higher, so if the last are free, the pawn jumps.

    Tried to set "maxstepheight=1" but don't resolve the problem (and adds some aditional problems...)

    "bCanStepUpOn" property on Static meshes set to false it's a partial solution, solve the problem in some cases, but then the pawn can't climb little stairs.


    Somebody have find a solution for this thing?

    #2
    I tried this asset & character, and aligned the mesh as close to the clip as possible...
    Code:
    StaticMesh'LT_Buildings2.SM.Mesh.S_LT_Buildings_SM_BunkerWallC_STR'
    
    SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
    Gametype: utgame.
    UDK Build: Feb 2013

    No joy! Couldn't repro the problem. I tried both a clean project and my own game.
    In the latter I use a low WalkablefloorZ to increase the slope characters can walk up.
    But there's no ground offset or other special character tweaks used.

    Have you already tried to repro this using a bare bones clean-project?
    WalkableFloorZ may help with the other problem regarding stair climbing...

    Comment


      #3
      I have used the same static mesh than you, in a UTgame map, and the same problem:



      Seems that the engine does a trace at the cylinder base and other at the top, and if the top one finds more free space, the pawn tries to jump. One solution would be to do larger traces, but it's native code, so I don't know how to fix.

      Only setting "bCanStepUpOn" to false on the staticmesh seems to minimize the problem sometimes.

      Comment


        #4
        Took another look.. bCanStepUpOn seems like the best solution as it works with every mesh I tried!
        Can you say why it only works sometimes? Tweaking WalkablefloorZ should help with the stairs problem btw.

        Plan B, if you disable bCanJump, the futile jump attempts and animation-switching stops, and the character stays facing the wall dead on.
        If you then angle the camera left / right the character strafes as before, although not as gracefully. Players must also hit the spacebar to avoid hanging on ledges...
        Tweaking Pawn 'ledge' bools may fix that, and using a low WalkablefloorZ 0.4-0.6 should allow walking over hard-angled meshes @ 28-52 degrees. But not sure about Bots???

        The 'Trace' seems to operate at the bottom only because if you use a large mesh height (multiple times character height), the problem still occurs (with this mesh anyway). What's key is the angle of the mesh, as you showed in the clip. If the mesh is leaning towards the player, the problem doesn't happen at all. But why?

        In a related thread (unsolved) UnrealEverything didn't think the code to slide along the walls was in uscript... So where then?
        In a separate post someone suggested looking in the anim tree. Had a quick peek but didn't see much. So is it exposed to UDK? Seems strange not to be...

        Comment


          #5
          Even disabling bCanJump (and bJumpCapable), the pawn continues flickering, going backbards a bit, then forwarding, and doing little jumps. Not the same behavior than when the wall is totally vertical.

          I think that the engine does two traces when collide, one at the base of the collision cylinder, and other over the MaxStepheight. If this last trace finds free space, the Pawn tries to jump over the obstacle, or climb it. For that when the wall inclination towards the pawn, all works perfectly.

          The solution would be to do the second trace, the MaxStepHeight one, more larger. But this is in native code, I haven't access to native code and Epic... well they are in others things...

          In my video the Pawn falls into ragdoll at the end, this is from my code, a solution to avoid falling loops. I have modified a bit to set bCanJump = false instead the ragdoll, with a timer of 0.5 secs. to restore. And in the HitWall event the same when the hit mesh are the same.

          The best solution (apart than Epic can fix it) is to use totally vertical collision meshes when possible. But for example the trees have randoms pitch & roll...

          Comment


            #6
            Another method is to set MaxStepHeight = 1 for 0.5 secs. in the HitWall event, minimize the little jumps.

            Comment


              #7
              I almost didn't see this thread. As I said before, CanOnStepOn off in mesh properties solved the problem to me, but after I tweaked in Playermove in my player walking state. And, as I don't have fancy movements yet, maybe it isn't creating this problem for me until now. Part of my player walking state:
              Code:
              	function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
              	{
              	        local float		VelSize;
              		local Vector	NewVelocity;
              		local bool		bMove;
              
               	if ( DoubleClickMove == DCLICK_Forward && !IsInState( 'Covering' ) )
              			GotoState( 'Sprinting' );
              
                              Super.ProcessMove( DeltaTime, NewAccel, DoubleClickMove, DeltaRot );
              
                              	if( Pawn == None )
              		{
              			return;
              		}
              
              
                    P = DIA_Pawn(Pawn);
              
               	if ( DoubleClickMove == DCLICK_Forward && !IsInState( 'Covering' ) )
              			GotoState( 'Sprinting' );
              
                              Super.ProcessMove( DeltaTime, NewAccel, DoubleClickMove, DeltaRot );
                              
                              	if( Pawn == None )
              		{
              			return;
              		}
              
              if(Role == ROLE_Authority)
              {
              P.SetRemoteViewPitch(Rotation.Pitch);
              
              }
              Pawn.Acceleration = NewAccel;
              
                    CheckJumpOrDuck();
                    //bPressedJump = true;
                    bCanCrouch=true;
              
               	VelSize = VSize(Pawn.Velocity);
              		if( VelSize > 0 )
              		{
              			//The value plus DeltaTime was 8 before:
                                      NewVelocity = Pawn.Velocity - (Pawn.Velocity - Normal(NewAccel) * VelSize) * FMin(DeltaTime * 50, 1.0);
              		}
              
              		NewVelocity = NewVelocity + NewAccel * DeltaTime;
              		if( VSize(NewVelocity) > Pawn.GroundSpeed )
              		{
              			NewVelocity = Normal(NewVelocity) * Pawn.GroundSpeed;
              		}
              
              		if( VSize(NewVelocity) > 0 )
              		{
              			bMove = Pawn.Move(NewVelocity * DeltaTime);
              			if(bMove)
              			{
              				Pawn.Acceleration = NewAccel;
              			}
              			else
              			{
              				//Pawn.ZeroMovementVariables();
              			}
              		}
              	}
              
              function PlayerMove( float DeltaTime )
              {
              local vector X,Y,Z,NewAccel;
              local eDoubleClickDir DoubleClickMove;
              local bool bSaveJump;
              local Rotator DeltaRot,ViewRotation, OldRot, NewRot;
              
              P=DIA_Pawn(Pawn);
              
              GroundPitch = 0;
              
              if(Pawn == None)
              {
              GoToState('Dead');
              }
              
              else
              {
              GetAxes(Rotation,X,Y,Z);
              
              ViewRotation = Rotation;
              DeltaRot.Yaw = PlayerInput.aTurn;
              DeltaRot.Pitch = PlayerInput.aLookUp;
              ProcessViewRotation(DeltaTime,ViewRotation,DeltaRot);
              SetRotation(ViewRotation);
              
              NewAccel = PlayerInput.aForward*X + PlayerInput.aStrafe*Y;
              NewAccel.Z=0;
              
              OldRot = Pawn.Rotation;
              
              if(Pawn != none)
              {
              if (NewAccel.X > 0.0 || NewAccel.X < 0.0 || NewAccel.Y > 0.0 || NewAccel.Y < 0.0)
              
              NewRot = Rotator(NewAccel);
              else
              NewRot=Pawn.Rotation;
              
              }
              Pawn.FaceRotation(RInterpTo(OldRot,NewRot,DeltaTime,9000000,true),DeltaTime);
              
              NewAccel = Pawn.AccelRate*Normal(NewAccel);
              
              ///////NO DOUBLE JUMPING///////////
              DoubleClickMove = PlayerInput.CheckForDoubleClickMove(DeltaTime/WorldInfo.TimeDilation);
              /////////////
              
              if( bPressedJump && Pawn.CannotJumpNow() )
                          {
                              bSaveJump = true;
                              bPressedJump = false;
                          }
                          else
                          {
                              bSaveJump = false;
                          }
              ProcessMove(DeltaTime, NewAccel, DoubleClickMove,Rotation);
              
              bPressedJump = bSaveJump;
              
              }
              
              }
              function UpdateRotation( float DeltaTime )
              {
                 local Rotator   DeltaRot, NewRotation, ViewRotation;
              
                 ViewRotation = Rotation;
                 if (Pawn!=none)
                 {
                    Pawn.SetDesiredRotation(ViewRotation);
                 }
              
                 // Calculate Delta to be applied on ViewRotation
                 DeltaRot.Yaw   = PlayerInput.aTurn;
                 DeltaRot.Pitch   = PlayerInput.aLookUp;
              
                 ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot );
                 SetRotation(ViewRotation);
              
                 NewRotation = ViewRotation;
                 NewRotation.Roll = Rotation.Roll;
              
                 self.viewRotationPitch = ViewRotation.Pitch;
                 
                 ViewShake(DeltaTime);
                 
                 NewRotation = ViewRotation;
                 NewRotation.Roll = Rotation.Roll;
              
                 if ( Pawn != None && PlayerInput.RawJoyRight != 0.0 || PlayerInput.RawJoyUp != 0.0)
                    Pawn.FaceRotation(NewRotation, deltatime);
                    //Pawn.FaceRotation(RLerp(Pawn.Rotation, NewRotation, 0.6, true), deltatime);
                      }
              function Rotator GetAdjustedAimFor( Weapon W, vector StartFireLoc )
              {
              
              local Rotator Rot;
              	local Vector Vec;
              	local Vector HitLocation, HitNormal, TraceEnd;
              
              	// by default, return Rotation. This is the standard aim for controllers
              	// see implementation for PlayerController.
              	if ( Pawn != None )
              	{
              		TraceEnd = PlayerCamera.ViewTarget.POV.Location + Normal(vector(PlayerCamera.ViewTarget.POV.Rotation))*32768;
              		Trace(HitLocation, HitNormal, TraceEnd, PlayerCamera.ViewTarget.POV.Location, false);
              
              		if (HitLocation == vect(0,0,0))
              			return Rotation;
              
              		Vec = HitLocation - StartFireLoc;
              
                      //Cast our Vector to a Rotator
              		Rot = Rotator(Vec);
              
                      //Return our adjusted aim Rotator
              		return Rot;		
              	}
              	return Rotation;
              
              }
              I put the complicated movements in other states or functions, trying to affect as minimum as possible the playerwalking state. I'm extending from UTPawn class...I'm almost sorry for my decision.

              Comment


                #8
                It's a good option. In my bots I have something similar, but it works before the hitwall, to avoid obstacles.

                Comment

                Working...
                X