CharacterController.Move isn't setting collision flags

I have a function in a “LevitateMotor” class that levitates or swims my CharacterController. It is supposed to set a CollisionFlags variable by invoking CharacterController.Move method. But for some reason, no collisionFlags are set after the CharacterController moves and collides with walls. The character is being stopped by the walls but no CollisionFlag changes occur. Is there some limitation to the Move method I don’t know about?

The very same CharacterController uses a different “GroundMotor” class to make the character walk on the ground, and the collisionFlags variable in that class changes correctly according to what it collides with.

playerMotor.controller is the CharacterController, Look towards the bottom of the method below to find the collisionFlags assignment.

        // this is the member-level declaration reference to PlayerMotor inside LevitateMotor class
        public PlayerMotor playerMotor;

        // PlayerMotor is initialized like this in the Start method
        playerMotor = GetComponent<PlayerMotor>();

        void Move(Vector3 direction, bool upOrDown = false)
        {
            if (playerSwimming)
            {
                // Do not allow player to swim up out of water, as he would immediately be pulled back in, making jerky movement and playing the splash sound repeatedly
                if ((direction.y > 0) && (playerMotor.controller.transform.position.y + (50 * MeshReader.GlobalScale) - 0.93f) >=
                (GameManager.Instance.PlayerEnterExit.blockWaterLevel * -1 * MeshReader.GlobalScale) &&
                !playerLevitating)
                    direction.y = 0;

                Entity.PlayerEntity player = GameManager.Instance.PlayerEntity;
                float baseSpeed = speedChanger.GetBaseSpeed();
                moveSpeed = speedChanger.GetSwimSpeed(baseSpeed);
            }

            // There's a fixed speed for up/down movement
            if (upOrDown)
                moveSpeed = 80f / PlayerSpeedChanger.classicToUnitySpeedUnitRatio;

            collisionFlags = playerMotor.controller.Move(direction * moveSpeed * Time.deltaTime);
            // Reset to levitate speed in case it has been changed by swimming
            moveSpeed = 4.0f;
        }

Below is the assignment statement in the GroundMotor class that assigns to collisionFlags correctly. And the CharacterController moves properly too.

// this is the member level CharacterController declaration
        private CharacterController controller;

        // Initialized in start method
        controller = GetComponent<CharacterController>();

            // Called to move the controller via walking
            collisionFlags = controller.Move(moveDirection * Time.deltaTime);

Are you calling Move on the same character controller twice per frame? That’s not recommended, and probably why your flags are empty on the second move.

No sir. I have If statements that check to see if the player is swimming or levitating, and if so, it returns and doesn’t call the CharacterController.Move for walking.

Is the intrinsic collisionFlags field empty after the move too? Unity - Scripting API: CharacterController.collisionFlags

Debug.Log(characterController.collisionFlags); // not the one you get back from move

You’re talking about after executing this line, right?

            collisionFlags = playerMotor.controller.Move(direction * moveSpeed * Time.deltaTime);

Aha!. I tested it out and for some reason the CollidedSides, CollidedBelow, and/or CollidedAbove flags get set on the intrinsic CollisionFlag property, Not just sides or below, or above. Why add the word collided to the flag?

Thanks you helped me fix it. But do you know why it is the way it is? I’m curious.

I’m not really sure what you’re asking. Could you rephrase?

Certainly, why does the enumerable CollosionFlags have CollisionFlags.CollidedSides as well as CollisionFlags.sides. it seems redundant.

You’re right. That is weird.

If you look at the official source, you’ll see they’re duplicated and their values are shared too: UnityCsReference/Runtime/Dynamics/Managed/Dynamics.cs at 54dd67f09e090b1ad5ba1f55886f327106406b0c · Unity-Technologies/UnityCsReference · GitHub

Looks like it was something that was renamed between versions but they haven’t (or can’t because of the enum’s nature?) officially mark as deprecated.