Je continue mes recherches sur les Characters Controller, et notamment ceux sans Rigidbody, et je cherche plus ou moins à reproduire la fonction move du character controller, notamment sa gestion des collisions où le personnage se bloque s'il est face à un mur, sinon il glisse à droite ou à gauche le long de celui-ci.
Je trouve pas mal choses à propos de la détection des collisions, mais presque rien sur leur résolution, et le problème me semble bien compliqué. Après quelques essais, j'ai trouvé comme solution de réinitialiser la vélocité à zéro en cas de contact, cela ignore l'angle de contact et bloque le personnage pendant que la direction forward ne pointe plus vers le mur. J'aimerais pouvoir en fonction de l'angle de contact, glissé le long du mur comme cela se produit avec le character controller de Unity.
J'ai trouvé une demi solution en calculant deux vectors à partir de la normale renvoyer par le raycasthit, mais le glissement s'effectue que dans un sens, parfois avec des sautillements, et cela ne fonctionne pas dans toutes les directions.
Voici le code de ma fonction update :
Voici le code de ma fonction qui détectent les collisions avant d'appliquer le nouveau déplacement :void Update()
{
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
if (input.magnitude > 1)
input.Normalize();
if (input != Vector2.zero)
{
angle = Mathf.Atan2(input.x, input.y) * Mathf.Rad2Deg;
targetRotation = Quaternion.AngleAxis(angle, Vector3.up);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, smoothRotationSpeed);
}
direction = Vector3.forward * input.magnitude * walkSpeed * Time.deltaTime;
HandleHorizontalCollisions(ref direction);
transform.Translate(direction);
}
Si vous avez des pistes de réflexions, des solutions, des suggestions, c'est à vous !!void HandleHorizontalCollisions(ref Vector3 velocity)
{
RaycastHit hit;
Vector3 p1 = transform.position + CapColl.center + transform.up * (CapColl.height/2 - CapColl.radius);
Vector3 p2 = transform.position + CapColl.center - transform.up * (CapColl.height / 2 - CapColl.radius);
Vector3 dir = Vector3.forward;
dir = transform.TransformDirection(dir);
float distance = Mathf.Abs(velocity.magnitude);
bool collision = false;
collision = Physics.CapsuleCast(p1, p2, CapColl.radius - skinWidth, dir, out hit, distance);
if (collision)
{
Debug.DrawRay(hit.point, hit.normal, Color.blue);
float theta = Vector3.Angle(hit.normal, Vector3.up) * Mathf.Deg2Rad;
Vector3 parallel = Vector3.forward * Mathf.Cos(theta) + Vector3.up * Mathf.Sin(theta);
Debug.DrawRay(hit.point, parallel, Color.cyan);
Vector3 perpendicular = Vector3.Cross(hit.normal, parallel);
perpendicular *= Mathf.Sign(Input.GetAxisRaw("Horizontal"));
Debug.DrawRay(hit.point, perpendicular, Color.magenta);
perpendicular = transform.TransformDirection(perpendicular);
velocity = perpendicular * velocity.z;
//velocity += Vector3.back * velocity.z;
}
}