Climbing system

Hi. I trying to make climbing system for my world. And i gets problem with fact i cant just take speed from controllers and assign inversed value of it to VRCPlayer.SetVelocity. If i do this, player covers 5-10% of the distance that hand covered, and this process accompanied with jitter. What i can do to fix this?

Some code snippets:

public override void PostLateUpdate()
{
    LClimbSphereRigidbody.MovePosition(GetControllerPosition("Left"));
    RClimbSphereRigidbody.MovePosition(GetControllerPosition("Right"));
}

void ClimbAbility()
    {
        if((LGrip || RGrip) && (ClimbableChecker(GetControllerPosition("Left")) || ClimbableChecker(GetControllerPosition("Right"))) )
        {
            VRCPlayer.SetGravityStrength(0f);
            VRCPlayer.Immobilize(true);
            if(ClimbableChecker(GetControllerPosition("Left")) && LGrip)
            {
                VRCPlayer.SetVelocity(-LClimbSphereRigidbody.velocity);
            }
            else if(ClimbableChecker(GetControllerPosition("Right")) && RGrip)
            {
                VRCPlayer.SetVelocity(-LClimbSphereRigidbody.velocity);
            }
        }
        else
        {
            VRCPlayer.Immobilize(false);
            VRCPlayer.SetGravityStrength(gravityStrength);
        }
    }

    Vector3 GetControllerPosition(string arg)
    {
        switch(arg)
        {
            case ("Left"):
                return VRCPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.LeftHand).position;
            case ("Right"):
                return VRCPlayer.GetBonePosition(HumanBodyBones.RightHand);
            default:
                return Vector3.zero;
        }
    }

Well, I noticed a couple things with this snippet:

else if(ClimbableChecker(GetControllerPosition(“Right”)) && RGrip)
{
VRCPlayer.SetVelocity(-LClimbSphereRigidbody.velocity);
}
You’re setting the player velocity based off of the LClimbSpehereRigidbody for the Right hand grip - shouldn’t this be RClimbSphereRigidbody?

Why are you using different methods to return your Vector3 in the switch statement of GetControllerPosition?
One case is GetTrackingData and the other is GetBonePosition

I’m not sure if this is the actual logic you’re using or if these are just tests to see which methods works closest to the desired results you need.

I’m not sure if this is the actual logic you’re using or if these are just tests to see which methods works closest to the desired results you need.

Yes. It’s testing to get more stable method.

You’re setting the player velocity based off of the LClimbSpehereRigidbody for the Right hand grip - shouldn’t this be RClimbSphereRigidbody?

Sleep deprived mind, sorry. I fixed it just right now and… nothing changes. Not that slow, but still strange speed issue and jitter.

Maybe try outputting the velocity values into some debug UI and see what the actual speeds are doing. Maybe it has less to do with your code and more to do with the actual reported vectors of the spheres.

There could be something as well with the way the game physics are dealing with the rigidbody when you mess with the gravity.

There might also be a different method you could use to determine the player position in space, like getting the delta between the position of the hands and the position of the hip and adjusting the player in space based on that value.

I wish I could offer more insight. The code seems pretty straightforward. I would start by getting some debug output so that you can check that actual values of variables and compare them to the expected or anticipated values.

So. I did as recomended.

            {
                if(RHandLastPos == default)
                    RHandLastPos = GetControllerPosition("Right");
                Vector3 delta = RHandLastPos - (GetControllerPosition("Right") - VRCPlayer.GetPosition());
                VRCPlayer.SetVelocity((delta - VRCPlayer.GetPosition()) / Time.fixedDeltaTime);
            }

It works very well, but still have some jitterness.

1 Like