This days I’m trying to create a 2D character controller with unity (using phisics). I’m fairly new to physic engines and it is really hard to get the control feel I’m looking for. I would be really happy if anyone could suggest solution for a problem I’m finding:
I’m trying here to just move the rigid body applying a gravity and a linear force for left and right. I have setup a physic material that makes no bouncing and 0 friction when moving and 1 friction with stand still. The main problem is that I have colliders with slopes and the velocity changes from going up (slower) , going down the slope (faster) and walk on a straight collider (normal). How could this be fixed? As you see I’m applying allways same velocity for x axis. I supposed it is because of the restitution calculations but not sure.
For the player I have it setup with a sphere at feet position that is the rigidbody I’m applying forces to.
Any other tip that could make my life easier with this are welcomed :).
P.D. It would be nice to implement something like this in unity: Behind Boxboy… | Boxycraft but don’t know how to achieve the wheel motor thing, The only joint with a motor is the hinge one but it doesn’t seem like the one to use here
I’m resurrecting the thread because I wasn’t able to find a solution for this. If anyone could help with it (different velocities when going up/down/straight slopes) I would really appreciate it.
Maybe this subject arrive a little too soon for me, because right now I’m learning 2D Toolkit. But as soon as I master 2D toolkit my first work will be exactly what you are trying to achieve. A 2D character controler.
I too tried making a 2D character controller using the Boxyboy wheel method. I used a wheel collider and motor forces.
Doesn’t work well. The obvious downside is that it feels like a go-kart. You constantly have to be applying counter-forces to slow it down when you release movement, or just to keep the speed in check.
In the end, I ended up with a heavily-modified version of the RigidBody FPS Walker script that’s floating around. Most of the customizations are to get “air movement” and jumping to work right. I also used AddRelativeForce(ForceMode.VelocityChange) for all forces, rather than AddForce(ForceMode.Acceleration). Felt better.
The script monitors the current velocity then constantly applies forces necessary to get from the current velocity to a target velocity. When there’s no input, that target velocity is 0, so it will apply counter-forces to stop you fairly quickly without sliding around.
If you want air movement, you have to achieve a balance between air momentum and the amount of control you want in air. You want some more momentum in the air probably, so you definitely want the maximum forces that can be applied to bring you to 0 to be less than on the ground.
For ladders, have the controller enter a whole different mode. I engage kinematic, disable gravity, stop running the regular forces routine, and apply movement directly with transform.Translate rather than forces.
For moving platforms, the raycast which checks for ground gets a Hit component to check the velocity of the ground underneath the character. Then targetVelocity = (hitSpeed + targetVelocity). Easy. I found the usual method of parenting the character to the platform DOES NOT work well. The reason: Interpolation must be engaged on the character for it to move smoothly at all times. As soon as an Interpolated rigidbody is parented to something else, the interpolation causes it to move slower than its parent on some frames, and it will soon fall off.
There are a few instances in my game where I want to change the Drag on the character on-the-fly, and have it effect the controls. For this, get the current drag of the rigidbody every frame, clamp it within a certain range, then targetVelocity = (targetVelocity / normalizedDrag)
The sides of your character should have 0 friction. Otherwise, air-control means the player can push himself against a wall in mid-air and cling to it.
You didn’t mention whether you want the character to change speeds on different slopes or not. What are you aiming for?
The method I described will keep the velocity.x constant on any slope.
Otherwise, you can add two downward raycasts on the left and right of the character, get the difference in length between them (finding the angle of slope beneath the player), and use that information to increase or decrease target velocity. It may feel cheap, but avoids a host of problems with trying to control forces without a target velocity.
Hi, sorry for the delay answering to all the responses.
Thanks a lot for the ideas specially to dasbin. I’m curious how did you implemented the motor thing in unity :). Could you explain?. I haven’t seen any wheel motor.
I don’t want to change speed based on leader slope. I want always to have same speed. On the other hand it seems really difficult/too much tweaks to accomplish this using a rigid body (not kinetic).
Because all your comments I think it could be better to try to do everything using a kinematic rigid body (dasbin, I don’t know if switching from kinematic to non kinematic at runtime could invalidate things in the physic engine core and have to do a lot of recalculations). The only problem with this approach is that you have to do the response (fix rigid body position) when a collision ocurrs. Another prob would be the number of ray casts to make sure it is not trespassing platforms.
Thanks for all the feedback. If anyone can give some more ideas, etc… they are welcomed.
I’m not sure why you think this. At that point you might as well just forgo the rigidbody and use the standard character controller.
It doesn’t. In fact, the entire purpose of the kinematic is to switch in and out of it at runtime, in order to run an animation or directly transform when needed. Otherwise, you’d just remove the rigidbody component entirely.
Um, like I said, just add a Wheel Collider. Done. Look in the Unity reference docs for how to apply torque forces to it via scripts.
Like I said though, I really don’t recommend going this route. It will not feel right. Look at the Rigidbody FPS Walker script. It will get you started with a much better solution.
I got something now. So here are some news of the developement of my 2d character controller.
I choose to not using rigidbody and instead use a CharacterController.
For the jump, I use a AnimationCurve, this way my jumps are always the same, there is never a height difference.
Finally, I added a cube collider as a parent to be able to catch collision in a OnCollisionEnter function.