- Home /
Capsule casting for custom character controller
I am making a game with Mario Galaxy style physics, using capsule casting to snap to the surface of the planet. I'm not sure whether it is my use of CapsuleCast or another part of the controller that is causing this so I am try to post relevant bits of code. The script is run from a player object, which has child containing all the graphics. What I want to happen is for the the distance to the ground to be calculated from the CapsuleCast and for one of two things to then happen: 1. Within a certain distance to the ground, automatically move to contact 2. If the ground is further away, go into free fall. (I haven't got this far yet)
Here is the capsule cast code:
//Check for stuff below us
capsuleTop = transform.position - transform.TransformDirection(Vector3.up * capsuleHeight * 0.5);
capsuleBottom = transform.position + transform.TransformDirection(Vector3.up * capsuleHeight * 0.5);
if (Physics.CapsuleCast(capsuleTop, capsuleBottom, capsuleRadius, transform.TransformDirection(Vector3.up), hitInfo, maxGroundSnapDist + (capsuleHeight * 0.5))) {
//If we're close--move to contact //NEEDS DEBUGGING--> WHY DO I SINK INTO THE FLOOR?
if (hitInfo.distance * 2 > capsuleHeight) {
transform.Translate(Vector3.ClampMagnitude(hitInfo.point - transform.position, hitInfo.distance * 0.5), Space.World);
grounded = true;
}
}
else { //If we're not close--freefall
grounded = false;
//Freefall coming soon
}
Here is the code that aligns the player to the surface normal:
function AlignToSurface () {
//Align to surface normal
transform.rotation = Quaternion.FromToRotation(transform.up, (gravitySource - transform.position.normalized)) * transform.rotation;
//(all the objects are circular, so alignment based on source of gravity instead)
}
And the code that rotates the graphics to the current direction of travel:
function RotateGraphics () {
var angleDifference = AngleSigned(graphics.InverseTransformDirection((previousPos - transform.position).normalized), -Vector3.forward, -Vector3.up);
if (angleDifference > 90) {
angleDifference -= 360; //A little angle fudging
}
var lerped = Mathf.LerpAngle(0, angleDifference, 0.1); //Smooth rotation
graphics.Rotate(0, lerped, 0);
}
However two things happen: ONE. I don't snap to the surface
TWO. If I run at full speed, the player works fine. Just staying at the original height above the planet. However if I move in little steps, by tapping the keys. The player sinks into the ground. BUT it is only the graphics object that sinks!! As far as I can tell, the parent stays in the same place. The graphics object is only modified in the scripts I have uploaded.
Can anyone tell me what I'm doing wrong? Or know a better way of doing it?
Thanks
I have solved the sinking problem by brute force, by just setting the graphics' localPosition to zero every frame. Seems to do the trick though :)