You’re right, my apologies. I should clarify that I’m looking for an explanation regarding how this is done rather than just being redirected to something else.
I’ve not experimented much with wall climbing, but recently I have been trying to learn how to do it.
I find walls by raycasting. When a valid wall is found, I position the character’s primary part CFrame to the intersection point of the ray + the surface normal. Then, I change the humanoid state to PlatformStanding, zero the HumanoidRootPart’s velocity, and parent the necessary BodyMovers or constraints.
To align characters to walls, I usually use a BodyGyro. I set the CFrame property to the LookAt matrix constructed from the position of the HumanoidRootPart and the surface normal of the wall.
I handle movement using a BodyVelocity object. You can use different BodyMovers or Constraint objects depending on what exactly you are doing. To find the axes for movement for a BodyVelocity object, I find two vectors orthogonal to the surface normal of the wall. Then, based on value of the humanoid’s MoveDirection property I update the BodyVelocity to move the character accordingly along the wall.
If you want to keep them directly against the wall even with resistance, you can change the BodyVelocity for something like an AlignPosition object or something else, but if my character is getting pushed out of their state by an external force (like a moving part or other player), I cancel the state instead of trying to force them to remain aligned.
Would you mind elaborating on this a bit more? I understand the use of gyros and stuff but the part I’m more confused about is “set the CFrame property to the LookAt matrix constructed from the position of the HumanoidRootPart and the surface normal of the wall.”
It would also be much appreciated if you sent a gif or video of how this works out, and if it resembles the result I’d like.
You can use the CFrame constructor to create a rotation that is aligned with the wall. When you raycast, the third result is called the surface normal which will tell you the direction the surface you hit with the raycast is facing. If you set the BodyGyro’s CFrame property to CFrame.new(Vector3.new(), -normal) it would rotate to face the wall or surface you hit. Here is an example in action. (I didn’t have time to make animations for my character.)
Thanks for explaining it, however, how would you make it so the climb is able to swap sides of an object when it reaches the end of one side as displayed in the video?
I really appreciate the help and patience, I’m sorry if I’m asking you to explain too much.
The simplest way I can think of right now is to check for different surfaces using raycasting when you update the player’s movement. As a more complex alternative (imo), you can get the adjacent surfaces of the wall or part and keeping track of the player’s position relative to the wall so that you can swap to the next adjacent surface when you reach the edge.
If you were going to use raycasting, however, I would suggest casting two rays pointing inward from the HumanoidRootPart’s sides, and updating the gyro / velocity / movement vectors to reflect the new surface the player moved to.
Here’s how that looks like:
Hey, I’ve attempted this using a bodyposition and it appears that when the character latches on the characters bodyposition slowly shifts downwards.
External MediaI think it has something to do with how the ray is casted based on the rootpart’s lookvector, but I even tried using an attachment as the baseline for the raycast and it came up with the same result.
How exactly did you calculate where to position the character? (I likely missed it in an earlier reply and am just stupid but)
Code:
hum.PlatformStand = true
local bodypos = Instance.new("BodyPosition")
bodypos.Name = "ClimbPosition"
bodypos.D = 600
bodypos.P = 10000
bodypos.MaxForce = Vector3.new(10000,10000,10000)
bodypos.Parent = root
local bodygyro = Instance.new("BodyGyro")
bodygyro.Name = "ClimbGyro"
bodygyro.D = 600
bodygyro.P = 100000
bodygyro.MaxTorque = Vector3.new(30000,30000,30000)
bodygyro.Parent = root
repeat
local start1 = root.CFrame
local end1 = CFrame.new(attach.WorldPosition)
local ray1 = Ray.new(start1.p, (end1.p - start1.p).unit * 2)
local part1, position1,normal1 = workspace:FindPartOnRayWithIgnoreList(ray1, {char,workspace:WaitForChild("Effects")}, false, true)
if part1 then
if normal1 then
bodypos.Position = position1 + normal1
bodygyro.CFrame = CFrame.new(position1 + normal1,position1)
end
end
wait(0.1)
until climbing.Value == false or hum.Health == 0
Sorry for asking for help once again.
Hey
https://gyazo.com/a2d4914c5397d3bec980fc38acf8ec10.gif
The way I did the movement was to use a BodyVelocity. I would then use UserInputService to assign 1 and -1 to some variables in a dictionary.
local controls = {up = 0, down = 0, left = 0, right = 0}
Pressing W would be 1.
Pressing A would be -1 and S and D would be opposites of W and A.
Then I could just set the velocity of the BodyVelocity in a loop like this:
local Speed = 0.5
local movement = HumanoidRootPart.CFrame:VectorToWorldSpace(Vector3.new(controls.left + controls.right, controls.up + controls.down, 0)) * Speed
Which gave me this result:
https://gyazo.com/80a45b94f720cd435e26bb7f7d300118.gif
Whenever the player isn’t pressing WASD, you just gotta set BodyVelocity.Velocity = Vector3.new(0,0,0) to have the Player “stand still”.
https://gyazo.com/2c46bf9b2e8a998f403fac3403e1b594.gif
Credit, props and thanks to @JimmyChance for helping me out as well
Thanks for the help, that definitely looks great. However, a bodyvelocity is too “flimsy” and unresponsive compared to the result I want. It seems to skid along the wall rather than actually sternly climb. However, how did you keep the player on the wall whilst only using a bodyvelocity? That part confuses me.
If you use BodyVelocity, make sure that it has a high enough MaxForce property. At a high enough MaxForce, the object that the BodyVelocity is parented to will instantaneously accelerate to match the BodyVelocity’s Velocity property. (If BodyVelocity’s Velocity property is the zero vector, the object will be stationary.)
Yes, I realized that now. However, again, how are you keeping the player against the wall while they move?
In my case, after initially positioning the character, I make sure the BodyVelocity’s Velocity property is applied parallel to the wall so they maintain their distance from it.
That’s one of my issues right now. I actually don’t keep the player against the wall. The way I’ve been doing it is to rotate the player accordingly to the surface normal of the current part of the wall, which would make the player go parallel with the wall, however this is not optimal. Since the rotation takes some time, this will overtime make the player get further and further away from the wall, as you can see here:
https://gyazo.com/2c46bf9b2e8a998f403fac3403e1b594.gif
Notice how the player is up against the wall in the beginning, but by the end, is like 1-2 studs away from the wall.
As @JimmyChance has confirmed, positioning/CFraming the player first and then applying the velocity afterwards is a way to go about this issue, which is something I’ll try to apply to my system today. I’ll probably tween the CFrame so it seems smooth
Hey how were you able to do that wall climbing thing because I really wanted to learn how, thanks!
I made something like this a while ago, and also shared it on an identical post.
Feel free to copy.
can you help me about RayCasting? when pressing WASD mine is buggy.
Ill try this out thanks alot this will def help!
It’s still really hard to understand the code and everything thats going on could you explain it?
It’s Been 7 months but I need help for the BodyGyro Position to go to different surfaces.
Can you give us the script or uncopylock a game? Just a question.