Thanks for the reply.
My character does stick to walls, and I’m trying to figure out how to implement the same sort of effect that adding a Physics Material to a collider would have but for a player that is controlled by ‘Character Controller’. Adding a physics material to the collider component on the player does nothing in this case. I’ll try again on the discord today, but I wanted to share what I’ve come up with since yesterday.
I implemented a raycast to check for wall collision, and then calculated a normal from where the ray hits, which when added to the ray vector3 produces a left or right Vector3 parallel to the wall:
Vector3 RaycastCalcs(Vector3 inputDirection)
{
RaycastHit hit;
Ray ray = new Ray(transform.position, inputDirection);
Vector3 slideVec = new Vector3();
Vector3 spherePosition = transform.position + (transform.forward * wallOffset) + transform.up;
wallCollision = Physics.CheckSphere(spherePosition, wallRadius, wallLayers, QueryTriggerInteraction.Ignore);
if (wallCollision)
{
if (Physics.Raycast(ray, out hit, 0.75f))
{
Vector3 incomingVec = hit.point - transform.position;
// Use the point's normal to calculate the reflection vector.
Vector3 reflectVec = Vector3.Reflect(incomingVec, hit.normal);
slideVec = incomingVec + reflectVec;
// Draw lines to show the incoming "beam" and the reflection.
Debug.DrawLine(transform.position, hit.point, Color.red);
Debug.DrawRay(hit.point, reflectVec, Color.green);
Debug.DrawRay(transform.position, slideVec, Color.blue);
}
}
return slideVec.normalized;
}
if(slideVec != Vector3.zero)
{
_controller.Move(slideVec * (_speed * Time.deltaTime) + new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
}
else
{
_controller.Move(inputDirection.normalized * (_speed * Time.deltaTime) + new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
}
This works somewhat, when the ray actually connects with the wall, but my problem now is when the character is still stuck on the edge of the wall, and the ray doesn’t hit it, the player gets stuck. I tried to use multiple raycasts but couldn’t figure out how to get the code to work.
Any input would be appreciated. I’ll continue trying to work through this.
Update: I think I’ve gotten a solution that works pretty well by expanding on my ideas from before. The only remaining issue I have is behavior on outside corners, which I’m fine with at this point.
Essentially, I added two more raycasts at the flank left & right of the player, added up all the slide vectors and normalized them so the player wouldn’t shoot off the wall in either direction.
Vector3 RaycastCalcs(Vector3 inputDirection)
{
RaycastHit hit;
Vector3 rotation = transform.eulerAngles;
Ray fwdRay = new Ray(transform.position, inputDirection);
Ray rightRay = new Ray(transform.position + (new Vector3(Mathf.Cos(Mathf.Deg2Rad * rotation.y), 0f, -Mathf.Sin(Mathf.Deg2Rad * rotation.y))) * _controller.radius, inputDirection);
Ray leftRay = new Ray(transform.position + (new Vector3(-Mathf.Cos(Mathf.Deg2Rad * rotation.y), 0f, Mathf.Sin(Mathf.Deg2Rad * rotation.y))) * _controller.radius, inputDirection);
Vector3 slideVec = new Vector3();
Vector3 fwdSlideVec = new Vector3();
Vector3 rightSlideVec = new Vector3();
Vector3 leftSlideVec = new Vector3();
Vector3 spherePosition = transform.position + (transform.forward * wallOffset) + transform.up;
wallCollision = Physics.CheckSphere(spherePosition, wallRadius, wallLayers, QueryTriggerInteraction.Ignore);
if (wallCollision)
{
if (Physics.Raycast(fwdRay, out hit, rayLength))
{
Vector3 incomingVec = hit.point - fwdRay.origin;
// Use the point's normal to calculate the reflection vector.
Vector3 reflectVec = Vector3.Reflect(incomingVec, hit.normal);
fwdSlideVec = incomingVec + reflectVec;
// Draw lines to show the incoming "beam" and the reflection.
Debug.DrawLine(fwdRay.origin, hit.point, Color.red);
Debug.DrawRay(hit.point, reflectVec, Color.green);
Debug.DrawRay(transform.position, slideVec, Color.blue);
}
if (Physics.Raycast(rightRay, out hit, rayLength))
{
Vector3 incomingVec = hit.point - rightRay.origin;
// Use the point's normal to calculate the reflection vector.
Vector3 reflectVec = Vector3.Reflect(incomingVec, hit.normal);
rightSlideVec = incomingVec + reflectVec;
// Draw lines to show the incoming "beam" and the reflection.
Debug.DrawLine(rightRay.origin, hit.point, Color.red);
Debug.DrawRay(hit.point, reflectVec, Color.green);
Debug.DrawRay(transform.position, slideVec, Color.blue);
}
if (Physics.Raycast(leftRay, out hit, rayLength))
{
Vector3 incomingVec = hit.point - leftRay.origin;
// Use the point's normal to calculate the reflection vector.
Vector3 reflectVec = Vector3.Reflect(incomingVec, hit.normal);
leftSlideVec = incomingVec + reflectVec;
// Draw lines to show the incoming "beam" and the reflection.
Debug.DrawLine(leftRay.origin, hit.point, Color.red);
Debug.DrawRay(hit.point, reflectVec, Color.green);
Debug.DrawRay(transform.position, slideVec, Color.blue);
}
slideVec = fwdSlideVec + rightSlideVec + leftSlideVec;
}
return slideVec.normalized;
}
I’m of course open to any suggestions on how to improve this code, but I thought I’d share what I had so future folks could use this as a workaround.