0 votes

When player climbs on a wall, the forward direction may not be perpendicular to the wall plane, which will result in weired animation. I want adjust the character's rotation at the moment FSM changes to climb state. I tried a few ways but none of them works including:

  1. change the basis.z with -1 * collision normal

  2. look at the collision point (I know why this fails because if the forward direction is not perpendicular to the wall the look_at won't work. If it is perpendicular there's no need to look at)

I'm new here and a newbie to gamedev. I'm very grateful if you are willing to offer some help.

Godot version 3.5.beta
in Engine by (37 points)

enter image description here

this works perfect when climbing on a cube whose faces are not bevel.

What about bevel cases where the y component is no longer Vector3.UP

2 Answers

0 votes
Best answer

Someone on Reddit gives me the solution, here is the code:


var z = -1 * normal
var x = normal.cross(Vector3.UP).normalized()
var y = z.rotated(x, -PI/2)
character.rotation_helper.transform.basis = Basis(x, y, z)

The point is getting x by z-up plane
and getting y axis by rotating z around x by -90 degree
by (37 points)
edited by
0 votes

using this function it returns a new transform

func align_with_y(xform, new_y):
    xform.basis.y = new_y
    xform.basis.x = -xform.basis.z.cross(new_y)
    xform.basis = xform.basis.orthonormalized()
    return xform

xfrom is the current transform and new_y is the normal (i suggest using a raycast normal) you want to be oriented at

global_transform = align_with_y(global_transform, $raycast.get_collision_normal())
by (458 points)

It turns out to be this:

before hit the wall:
enter image description here

after hit the wall:
enter image description here

Here is how I use this snippet:

func activated(_message := {}) -> void:
    var normal = character.climber.get_chest_collision_normal()
    var global_transform = character.rotation_helper.global_transform
    character.rotation_helper.global_transform = align_with_y(global_transform, normal)

func align_with_y(xform, new_y):
    xform.basis.y = new_y
    xform.basis.x = -xform.basis.z.cross(new_y)
    xform.basis = xform.basis.orthonormalized()
    return xform

the only thing i can suggest because your images are not showing is to change

character.rotation_helper.global_transform = align_with_y(global_transform, normal)

to

character.rotation_helper.global_transform = align_with_y(character.rotation_helper.global_transform, normal)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.