Simple Character Controller

Mar 11, 2013 at 4:44 AM
First off - I must say this is a damn gorgeous engine, both in terms of visual appeal and engine architecture! Well done!

I'm an amateur game programmer, and I've been looking into using this engine to create a simple 3rd person physics/blocks puzzler (as part of a uni assignment with a couple other group members).

After looking through the examples, I thought I'd take the physics example as reference and try and create a simple 3rd person character controller. I started with a kinematic plane for the ground, and a dynamic box as the "player". I can get the camera attached to the box position no problems. The problem arises with actually controlling my "player".

I thought I'd try using the dynamic box, so that the character is affected by collisions and gravity (so he can jump around and be bounded by kinematic walls and floors). I can get linear movement sort-of working acceptably by altering the rigidbody entity's linearvelocity on each update. However, to turn the character, I resorted to altering angularvelocty or angularmomentum using the local Up vector multiplied by Mouse.DeltaX. This results in incredibly jerky and unnatural rotation. (I'm guessing this is due partly to the inertia tensor - and something to do with the angular velocity not being enough to overcome static friction?)

Implementing the same game character using a kinematic box and just altering position and orientation directly using transforms results in a much smoother experience. However the drawback to this is that it doesn't collide with the walls or floors, and also is not affected by gravity.

Basically my question is this: is there a straightforward, simple way to implement a character controller using a dynamic rigidbody object in XNA Final Engine?
Alternatively, how would I go about using a kinematic entity, yet restricting it from moving through the walls and somehow still being affected by gravity?

Sometimes I feel like I'm slightly out of my depth...
Thanks alot!

Sam
Apr 29, 2013 at 1:43 AM
Edited May 7, 2013 at 8:08 PM
Bepu (This engine uses Bepu) has a character controller, take a look at their demos. You can download it here. It even has a 3rd person mode, too. It's fairly easy but if you run into any problems, post here and I or someone else will help you.
Jul 7, 2013 at 7:13 PM
Edited Jul 7, 2013 at 7:13 PM
Trying to figure out how to implement simplecharactercontroller, because that robust character controller is no chance...
Jul 7, 2013 at 10:34 PM
Here, follow this. I just threw the character controller into the scene to get it working. There are some fixes that I can work on, but it works for now.

Download the latest version of BepuPhysics, open it up, so it looks like this:
Image

Add these files to your XNA Final Engine project, so it looks like this:
Image
Note: I added it under the "scripts" folder inside the Examples project.

Inside your PhysicsTestScene add the following to the Variables region:
        public CharacterControllerInput character;
Inside LoadContent add this:
            #region Character
            //Creates the player character
            character = new CharacterControllerInput(camera);
            //Changes the step height from 1f to .5f
            character.CharacterController.StepManager.MaximumStepHeight = .5f;
            //The character will be moved here
            camera.Transform.Position = new Vector3(10, 10, 0);
            character.Activate();
            #endregion
Inside UpdateTasks add this:
            #region Character controller update
            //Temp char stuff
            character.Update(Time.GameDeltaTime);
            #endregion
Now for fixing the errors inside CharacterControllerInput.cs. You need to change some of the things like:
Space.add(...);
to things like:
PhysicsManager.Scene.Add(...);
Some of the more noteworthy things are the camera, I changed it into a GameObject3D
        /// <summary>
        /// Camera to use for input.
        /// </summary>
        public GameObject3D Camera;
Again, I need to optimize this, it was just a quick test. Some things will need to be changed if you want to use a lot of character controllers.

These are just some of the changes I made, you'll need to go through your code and change all of Bepu's cameras to your own. Change the space to your own, and a few other misc things.
    public CharacterControllerInput(GameObject3D cameraToUse)
    {
        CharacterController = new CharacterController(/*Was blank before!*/);


        //Space = owningSpace;
        PhysicsManager.Scene.Add(CharacterController);


        Camera = cameraToUse;
        Deactivate();
    }

    /// <summary>
    /// Gives the character control over the Camera and movement input.
    /// </summary>
    public void Activate()
    {
        if (!IsActive)
        {
            IsActive = true;
            //Camera.UseMovementControls = false;
            PhysicsManager.Scene.Add(CharacterController);
            CharacterController.Body.Position = (Camera.Transform.Position - new Vector3(0, StandingCameraOffset, 0));
        }
    }
Jul 9, 2013 at 6:37 PM
You are awesome, got it working too. Now i will figure out character rotation and it is done :)
Jul 10, 2013 at 2:00 AM
Ascaria wrote:
You are awesome, got it working too. Now i will figure out character rotation and it is done :)
If you'll explain it a little better, I might already have what you need done. I'm not sure exactly what you mean by the rotation. Do you mean which direction he is facing?
Jul 10, 2013 at 8:37 AM
Yes i mean direction. I already figured out how to do it, but i dont know if it is correct way. :) I think movement seems to be framerate independent. Next step is to do framerate independent changing direction, because mouse delta tells us previous state and current state difference, but not elapsed time between these two. Multiplication of mouse delta by Time.GameDeltaTime seems to be not enough.
Jul 10, 2013 at 8:53 AM
Ascaria wrote:
Yes i mean direction. I already figured out how to do it, but i dont know if it is correct way. :) I think movement seems to be framerate independent. Next step is to do framerate independent changing direction, because mouse delta tells us previous state and current state difference, but not elapsed time between these two. Multiplication of mouse delta by Time.GameDeltaTime seems to be not enough.
I am using the character controller purely to test networking, so it is hacked together and not something I would be willing to put out in the wild until I clean it up. That being said, I let the script "ScriptCustomCameraScript" handle looking around while I do my tests.
                #region Looking around hack
                Yaw += Mouse.DeltaX * 0.005f;
                Pitch += Mouse.DeltaY * 0.005f;
                Mouse.Position = new Point(200, 200);
                #endregion
                #region Assign Camera Transform Rotation
                // Calculate Rotation //
                Quaternion rotation = Quaternion.Identity;
                rotation *= Quaternion.CreateFromYawPitchRoll(0, Pitch, 0);
                rotation *= Quaternion.CreateFromYawPitchRoll(Yaw, 0, 0);
                // Its actually the invert...
                ((GameObject3D)Owner).Transform.Rotation = Quaternion.Inverse(rotation);
                #endregion
Depending on how you want to handle the Character Controller, you could add it as a component for a GameObject3D or a stand alone thing. I will be using it for AI and the player, so it will probably be a component. It would probably be best to have the camera and controller remain two different systems. I also add non-controller physical entities to the camera (I add a simple primitive to my test free camera to prevent players from clipping through objects).

Anyways, I'll end this before it turns into a rant. Let me know if you need anything else, I'll be glad to help.