Hello everyone, so, I needed an advanced 3rd person character controller, I couldn’t find any, so I’m on a adventure to built my own, but, the way I’m doing acceleration the character seems to be trying to run on Ice, I’ll explain what and how my code does:
First I get my input direction based off the camera direction (booth right and forward vectors have the .y component set as 0 and then are normalized)
vTargetDirection= (horizontalAxis * right + verticalAxis * forward).normalized;
Then, after saving my Direction on a Vector3 I check if it is not Vector3.zero, and the apply some acceleration on Vector3 that stores my Velocity
if (vTargetDirection != Vector3.zero)
vVelocity+=((fAcceleration+fDeAcceleration)*fDelta.deltaTime)*vTargetDirection; //Accelerate
I had an attempt trying to fix it that way, where tMesh2 is a child of transform, and only receives local rotation
tMesh2.localRotation=Quaternion.LookRotation(vTargetDirection);
vForward= tMesh2.forward;
vForward.y = 0;
vForward = vForward.normalized;
fAngleDiff=Vector3.Angle(vForward, vVelocity.normalized)*0.015f;
if(fAngleDiff<0.009f)
fAngleDiff=0.0f;
vVelocity+=((fAcceleration+fDeAcceleration+fAngleDiff)*fDelta.deltaTime)*vTargetDirection; //Accelerate
Then, I apply the ground normal contribution to my Velocity, so that going Uphills decrease my velocity (untill It sends me Downhill), and going Downhill gives an speed boost
vVelocity.x+=fXInverseNormal*fDelta.deltaTime;
vVelocity.z+=fZInverseNormal*fDelta.deltaTime;
And after this, I do my Deacceleration, where the ToZero function returns fDeAcceleration as positive if vVelocity(x,y,z) is lower than 0 and a negative value If it is higher than 0
vVelocity.x+=ToZero(vVelocity.x, fDeAcceleration)*fDelta.deltaTime;
vVelocity.y+=ToZero(vVelocity.y, fDeAcceleration)*fDelta.deltaTime;
vVelocity.z+=ToZero(vVelocity.z, fDeAcceleration)*fDelta.deltaTime;
And then, vVelocity is applied to rigidbody.velocity, where the TrasnformVec3 function returns, vec.xtransform.right, vec.ytransform.up and vec.z*transform.forward
rigidbody.velocity=TransformVec3(vVelocity, transform);
rigidbody.velocity+=transform.up*-fGravity*fDelta.deltaTime;//Apply Gravity
In the end, rotate transform to always align to the ground
Vector3 myForward = Vector3.Cross(transform.right, m_raycastMiddle.normal);
Quaternion qTargetRotation1 = Quaternion.LookRotation(myForward, m_raycastMiddle.normal);
transform.rotation = new Quaternion(transform.rotation.x, 0, transform.rotation.z, transform.rotation.w);
transform.rotation = Quaternion.Lerp(transform.rotation, qTargetRotation1, Time.deltaTime*20);
fDelta.deltaTime is my own delta, where it returns 1.0 when at 60 fps and 2.0 at 30 fps (just an approximation), the rigidbody have all rotations locked, thanks for the attention.