Walking/moving parallel to every surface of a part/model

Hi! I’ve been working for a little while on a solution to this issue and would like to hear if anyone has any ideas on how to approach this, all of my solutions have felt clunky or inconsistent.

Essentially, I’m trying to make it so you can walk on the outside of a model or part, as if that surface is the ground. When you reach an edge of that surface (which is often a 90 degree corner, one of the biggest challenges) your character should reorient to be parallel to the new surface. This is essentially supposed to be like wall climbing, but in 0 gravity so everything goes and can be walked on.

The first approach I tried was anchoring the character parallel to the surface of the “floor” (using a raycast normal to orient the character parallel) and updating the character CFrame with RenderStepped for any user WASD input. When they reached an edge of a current floor, a raycast is sent to the origin of the part. That collides with any surface between the character and the part’s origin, which is the way I grab the nearest surface to orient yourself based on. This solution isn’t terrible, and it’s the closest to consistent I’ve got. It does, however, look very “choppy” as transitions from one surface to another are instantaneous. The biggest issue here is that every time I anchor onto a new surface, the character’s relative orientation completely changes. This means you might be climbing over a corner and when the player is switched to the new orientation, their head is now where their feet would be if you were climbing over a corner. Here’s a picture showing what happens when the character moves in the direction indicated by the arrow, with the resulting transformation in the image below.

My assumption here is that the raycastResult.Normal has a rotation component based on the surface that I don’t know about, or that the character always tries to place its feet at the lowest possible point in the world reference frame given the required orientation. Does anyone know why this is happening, or what orientation a raycastResult.Normal returns? Or is it literally just returning a vector with no CFrame component, so the character orientation is reset to whatever is default? Is it possible for me to retain the character orientation around corners like this? It is worth noting some transitions from wall to wall DO seem to work nearly as intended, which is what is confusing me. The behavior seems a little random. This is basically what the script looks like, oldOrientation is what I’m trying to figure out how to utilize

function Movement:checkOrientation(humanoidRootPart, part, oldRayCastNormal)
local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = {humanoidRootPart.Parent}
	local rayDirection = CFrame.new(humanoidRootPart.Position, part.Position)
	local raycastResult = workspace:Raycast(humanoidRootPart.Position, rayDirection.LookVector*5, raycastParams)
	if ((raycastResult.Normal - oldRayCastNormal).Magnitude > .05) then
		local oldOrientation = ??
		humanoidRootPart.CFrame = CFrame.new(raycastResult.Position + raycastResult.Normal*2, raycastResult.Position + raycastResult.Normal*3)
end
	return raycastResult.Normal
1 Like

Something like EgoMoose’s Wall stick/Gravity Controller?

Something pretty similar to that, but the reason I wasn’t using EgoMoose’s module was because I was under the impression walking off “edges” of a floor would cause the player to fall in the direction of their new artificial gravity, and I don’t want any forces in play pushing the character when they aren’t in contact with a part. I also need to be able to handle the case of walking off a 90 degree corner without falling.

With a little more testing, I’m pretty sure the orientation is just snapping to (0,0,0) every time the CFrame is updated to account for a new surface with the only adjustment made being to make the character parallel to the surface, so I’m just trying to figure out how to keep my rotation the same way it was before a 90 degree transformation was made.