I am trying to adapt the FPS microgame (FPS Microgame - Unity Learn) to my own game because it has a nice feel to it and the scripts are not overloaded with bloat and mechanics I don’t need like a lot of the asset store FPS controllers.
I have one problem however which is that the player collision handling seems to be handled in a weirdly idiosyncratic way. Instead of having a capsule collider on the player, it seems that a capsule is created at runtime when needed to handle collision. At least I think that is what is happening because I don’t fully understand the code. I think this is the relevant excerpt:
// apply the final calculated velocity value as a character movement
Vector3 capsuleBottomBeforeMove = GetCapsuleBottomHemisphere();
Vector3 capsuleTopBeforeMove = GetCapsuleTopHemisphere(m_Controller.height);
m_Controller.Move(characterVelocity * Time.deltaTime);
// detect obstructions to adjust velocity accordingly
m_LatestImpactSpeed = Vector3.zero;
if (Physics.CapsuleCast(capsuleBottomBeforeMove, capsuleTopBeforeMove, m_Controller.radius, characterVelocity.normalized, out RaycastHit hit, characterVelocity.magnitude * Time.deltaTime, -1, QueryTriggerInteraction.Ignore))
{
// We remember the last impact speed because the fall damage logic might need it
m_LatestImpactSpeed = characterVelocity;
characterVelocity = Vector3.ProjectOnPlane(characterVelocity, hit.normal);
}
}
// Returns true if the slope angle represented by the given normal is under the slope angle limit of the character controller
bool IsNormalUnderSlopeLimit(Vector3 normal)
{
return Vector3.Angle(transform.up, normal) <= m_Controller.slopeLimit;
}
// Gets the center point of the bottom hemisphere of the character controller capsule
Vector3 GetCapsuleBottomHemisphere()
{
return transform.position + (transform.up * m_Controller.radius);
}
// Gets the center point of the top hemisphere of the character controller capsule
Vector3 GetCapsuleTopHemisphere(float atHeight)
{
return transform.position + (transform.up * (atHeight - m_Controller.radius));
}
// Gets a reoriented direction that is tangent to a given slope
public Vector3 GetDirectionReorientedOnSlope(Vector3 direction, Vector3 slopeNormal)
{
Vector3 directionRight = Vector3.Cross(direction, transform.up);
return Vector3.Cross(slopeNormal, directionRight).normalized;
}
void UpdateCharacterHeight(bool force)
{
// Update height instantly
if (force)
{
m_Controller.height = m_TargetCharacterHeight;
m_Controller.center = Vector3.up * m_Controller.height * 0.5f;
playerCamera.transform.localPosition = Vector3.up * m_TargetCharacterHeight * cameraHeightRatio;
m_Actor.aimPoint.transform.localPosition = m_Controller.center;
}
// Update smooth height
else if (m_Controller.height != m_TargetCharacterHeight)
{
// resize the capsule and adjust camera position
m_Controller.height = Mathf.Lerp(m_Controller.height, m_TargetCharacterHeight, crouchingSharpness * Time.deltaTime);
m_Controller.center = Vector3.up * m_Controller.height * 0.5f;
playerCamera.transform.localPosition = Vector3.Lerp(playerCamera.transform.localPosition, Vector3.up * m_TargetCharacterHeight * cameraHeightRatio, crouchingSharpness * Time.deltaTime);
m_Actor.aimPoint.transform.localPosition = m_Controller.center;
}
}
// returns false if there was an obstruction
bool SetCrouchingState(bool crouched, bool ignoreObstructions)
{
// set appropriate heights
if (crouched)
{
m_TargetCharacterHeight = capsuleHeightCrouching;
}
else
{
// Detect obstructions
if (!ignoreObstructions)
{
Collider[] standingOverlaps = Physics.OverlapCapsule(
GetCapsuleBottomHemisphere(),
GetCapsuleTopHemisphere(capsuleHeightStanding),
m_Controller.radius,
-1,
QueryTriggerInteraction.Ignore);
foreach (Collider c in standingOverlaps)
{
if (c != m_Controller)
{
return false;
}
}
}
m_TargetCharacterHeight = capsuleHeightStanding;
}
if (onStanceChanged != null)
{
onStanceChanged.Invoke(crouched);
}
isCrouching = crouched;
return true;
}
The problem is that I am trying to use Behavior Designer’s line of sight mechanics that depend on a collider to be able for an object to see another object and adding a collider to the player on top of the above code breaks jumping and crouching.
Is there some elegant or simple way to fix this? Or what exactly do I need to change to have the player use a standard collider instead?