How can I change max walkable floor angle to be relative to character capsule?

I’m just now familiarizing myself with the character movement component on the code side. I’m pretty new to c++. I think what would help if there was a breakdown about what all happens during the evaluation/ movement of a character. At first I tried finding the methods and members that evaluate a floor angle as false and making sure that they don’t (just return true) I thought it would break stuff pretty quickly and I would know a little more by doing so but it didn’t. Ultimately I want to set it up so that the max walkable floor angle is relative to the up vector of the character capsule.

How is the character actually moved (when using character movement component)? Is it through physics (X,Y forces?)? What is the general flow of events that happens? For instance:

-Sweep to find surfaces that could be collided with.
-Evaluate Hit and determine is angle allows it to be walkable
-If walkable apply physics velocity to achieve movement.

This seems like an easy thing to implement but with the incredibly large code base it’s a bit overwhelming rifling through it all. Is the CharacterMovementComponent where I would need to make changes to achieve this new walkable floor evaluation.


Okay So I’ve been all over the character Movement Component and I’ve still not had any success with allowing the character to move past 90 degrees. There are several areas that look like they would handle that. So I’ve gone through and changed the evaluations to transform the vectors being evaluated to my Capsules transform. I created a World To Component function which goes something like:

FVector UCharacterMovementComponent::hkvWorldToComponentConst(FVector myHit) const
	FTransform compToWorldTrans = CharacterOwner->CapsuleComponent->GetComponentTransform();
	FVector rotatedVector = compToWorldTrans.InverseTransformVectorNoScale(myHit);
	return rotatedVector;

Then most of the evaluations that look promising I transform the vector being checked, usually the Delta, or Hit.ImpactNormal. This was a recommendation, so that I can keep the Z is up logic throughout the component. Still no success. There are many areas in the CharacterMovementComponent, IsWalkable, PhysWalking, MaintainHorizontalGroundVelocity, PhysFalling, ComputeSlideVector, SlideAlongSurface, and SimulateMovement that look promising. Am I missing something? Is there another Area that is key in getting the character to walk past the world’s 90 degree? Even if I could just disable this it would be a good start. I would like to get it so that 90 degree’s ( or whatever my max walk angle set) is still the limit but relative to the character capsules up Vector and not the World Z.

Currently I’ve got the character jumping along it’s up Axis and Falling back along it. So I’ve had some success with rooting out the Z is up logic. Any help would be much appreciated. Thanks!

Looking into it further I ran across these Super:: calls to a function. So this is calling the parent class’s version of the function? If this is the case then I’ll likely need to modify those functions as well. The characterMovementComponent is a child of the MovementComponent correct? Do I need to go further up the chain? Like is there something behind Movement Component that would control the logic in this component chain?

The only behavior I think I’ve identified is that having IsWalkable always return true allows the character to hit the slope and slide past it, at this point it appears to go into a slide function. I’m not sure which one yet. When the character is sliding there is no control, so somewhere around there this function is being called.

Hi ,

I just wanted to clarify that your character’s “up” axis is not necessarily the same as the world’s Z axis, so you want to calculate the walkable surface based on the character’s orientation and not the World.

Yeah that’s what I’m trying to do. My characters up Axis is definitely not the worlds up. My character capsule’s upvector always points towards 0,0,0 - even if the character run’s 50000 unreal units in the X axis (Any axis). Because I manually MakeRotZX and point it towards the Vector 0,0,0. Because my world is an inverted sphere, so the Center of the world is 0,0,0. The character is constantly walking around on an inverted sphere ( a very large one). So his head always needs to point at 0,0,0. So you are correct, I’m not trying to use the character’s up vector because I think that is “Z” of the world. It’s because it actually does act as a Z relative to the character because it is Up to him (so long as his head always points directly at 0,0,0). I’ve already swapped the logic on IsWalkable to use InverseTransformVectorNoScale( Vector in Question).Z but it appears that there are other functions throughout the CharacterMovementComponent that also prohibit the character from passing 90 degrees in World Space. I’m trying to find the other parts that are doing this. Because I’m a noob I guess it could be that I didn’t mitigate the logic in IsWalkble correctly but, I’m not seeing anything in game yet that would indicate that IsWalkable is getting me even close. Currrently the closest I’ve gotten it is that the character hits this 90 degree barrier and then he starts sliding forward past it (which in my game is “Forward” because it’s an inverted sphere). This seems like at least the character doesn’t hardline right at the 90 degree spot but instead attempts to SlideAlongSurface. So it’s not a dead stop but the problem is that when he enters this sliding around mode - once his forward momentum is no longer enough to slide past it - he begins to start sliding back down it - at this point I have no control as it’s in Physics mode or something.

I’ve messed with every part of the CharacterMovementComponent and MovementComponent and Nothing I do allows the character to walk past the world’s 90 degree. Currently my character jump and falls along it’s UpVector. The character can walk up along the sphere’s slope until around 90 degrees. At this point the character will collide with an invisible wall and then continue to slide up the wall - but I no longer have control as the Physics simulation appears to be in control. So the character just skips along continuing up the sphere’s wall.

What in the CharacterMovementComponent (or elsewhere) prohibits the character from “walking” past 90 degrees?

I’ve gone through the entire characterMovementComponent and changed all the logic pertaining to HIT from the sweeps/ line trace to WorldToComponent(VectorToTransform).

The Character is able to walk all the way up to the 90 degree-ish area and then collide with this limit. But still the character continues going forward past it, so parts of the CharacterMovementComponent are allowing the character to slide past the limit, but what keeps the character in “Slide” mode or prohibits me from still having control past this angle limit?

Hey again !

IsWalkable() definitely needs to be changed since it enforces the 90 degree limit:

// Never walk up vertical surfaces.
if (Hit.ImpactNormal.Z < KINDA_SMALL_NUMBER)
	return false;

SlideAlongSurface handles the slide code, and in the CharacterMovement implementation there is a restriction to not slide upwards if the surface is not walkable:

	// We don't want to be pushed up an unwalkable surface.
	if (Normal.Z > 0.f)
		if (!IsWalkable(Hit))
			Normal = Normal.SafeNormal2D();

Normalizing in 2D removes the Z component.

I think you’re going to find (or have found out already!) that this is going to be a big change. That can be fun or frustrating… I would evaluate whether continuing with Character is the right thing, or whether using a Pawn and implementing movement from scratch would be the way to go.

Hey!, Hopefully I’m not driving everyone crazy. I’ve been trying to find a way to break it into chunks that just work even if not pretty. For instance, even though I think I know how to set the IsWalkable now to correctly compare, I’ve tried commenting out the guts of it and just have it always return true. Turning things off like this or minimizing them helps me figure out what is responsible for what.

So with the IsWalkable always returning true for the time being, I have now started looking at the SlideAlongSurface portion. Before I have been using SafeNormal() instead of the 2d version. I think I’ve also tried WorldToComp(Normal.SafeNormal2D()); There appear to be a handful of evaluations when using Vectors and slowly I’m figuring out how to handle each one. Often I see FVector( 0, 0, someValue) and I’ll try to ComponentToWorld() and because this worked for modifying DoJump to correctly use JumpZVelocity along the Capsules Local Z I assume it should work for similar circumstances.

Slowly I’m seeing more of this large file and knowing where things are located. I’m trying to find the order in which things are likely called and work backwards. I don’t mind it being a big challenge - it wouldn’t be as much fun if you guys had done all the work for us :wink:

And thanks again.

Finally some success, still not 100 percent yet but the character actually goes up to 90 degree’s before my new problem happens. I guess before it was only making it up the wall of the sphere to about 75 degrees. The cool part though is that I can turn the character upside down and stick up towards where the ceiling of the sphere would be, when I play he falls to that floor and can move around on the ceiling. More problems occur on this side of the sphere, can’t make it as far around the curve from this side yet but it’s progress.

The big thing that I did was change the FindFloor() / ComputeFloorDist(). They were looking for sweep results from only below the Character in World space (0, 0, 1) so I transformed those parts to be oriented to the characters Capsule. Several other tweaks throughout those two functions but finally something changed.

This presented me with a new problem though - as expected. When My character approaches the true 90 degree mark in world, The capsule starts to fall over and my controls become wonky. Currently the way I keep the Character capsule’s UpVector pointed at World Zero is in BP, attached to this. Not sure what is going on with it because the BP is supposed to be “Setting” this constantly so whatever is happening is doing it in the face of that.

Hi ,

I just wanted to check in and see if you are still making progress with this issue. I will mark it as resolved for now, but if you are still needing any help, please feel free to reopen the question.

I’ve made a great deal of progress. My character is walking around on the inside of the sphere. I should break it down on here so others might see. It wasn’t as hard as I thought.

The first thing I did was to create a set of functions that would handle vectors. Throughout the character Movement Component the logic is “Z” is up. So most vectors are handled in this sort of orthographic vector space. So it’s easy to zero out or add in a value to just the “z” of a vector when it’s identifiable as z. Additionally X, an Y are sometimes treated together by adding in a value or zeroing them out. So if you’re sticking to the logic already assembled in the component then you have to be able to handle those situations.

I created a handful of vector functions to handle the situations I came across in the component:

  1. Component to World ( this allowed me to compare a vector in a more unified orthographic vector state)

  2. World To Component ( This I used to rotate Orthographic vectors to be relative to what my character capsule was, falling, jumping, capsule extents, etc…)

  3. Back and Fourth (needed for
    modifying X,Y,Z values in World
    space. So in this function I first
    transform the relative vector to the
    world, modify the values, then
    return it to relative vector).

I get Orthographic is probably the wrong term, but it’s how I visualize it. Using variations of the three functions above I was able to handle situations like Vector.Z = thisvalue, or Velocity().2Dfunction.

I have a few little hiccups that I’m still rooting out but this got me to the point where I can run around and jump/ fall inside of the sphere. I can do aircontrol, and still rule angles out that the player shouldn’t walk over (only relative to the capsule)

As a last comment I would say that you basically have to do this across the entire CharacterMovementComponent - Head to Toe. Little things scattered everywhere in there. Thanks!