Search Unity

Physics.SphereCast() Returns Invalid Normal & No Contact Point

Discussion in 'Physics' started by Cygon4, Sep 6, 2017.

  1. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Hi!

    In the past I tried to rely on Unity's physics engine for player movement, but this caused heaps of trouble (player can't move over small height differences, inconsistent horizontal speed on slopes, being able to reduce falling speed by using air control to move into walls...).

    So now I'm trying to do my own character movement using Physics.SphereCastAll(), Physics.CapsuleCastAll() and Physics.BoxCastAll() (or rather, their ...NonAlloc variants).


    Everything is fine when /moving/ into a collider (i.e. contact happened along the shape cast sweep but there was no contact at the beginning)

    However, if the shape cast begins already in contact with a collider, it returns the contact point as (0,0,0) and a normal that has nothing to do with the touched surface. Thus I am left unable to tell if a movement would lead the character deeper into a collider (bad!) or away from / parallel to the collider (good!).

    I've seen other users with this problem:
    Analyzing and Optimizing unity Sphere/Capsule Casts
    SphereCast & CapsuleCast RaycastHit.normal is not the surface normal as the documentation states...

    So if my CapsuleCollider touches an arbitrary BoxCollider, how can I get the point of contact or the surface normal? Currently I'm ignoring the contact if the shape cast's sweep direction is away from the center of the offending collider, but that is of course incorrect for non-axis-aligned box colliders.
     
  2. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Attached is an Unity project (w/complete source) where I use Physics.SphereCastNonAlloc() exclusively to provide typical character movement physics (climb stairs, slide along walls).

    Intended for both 2.5D platformers and first/third person games.

    test-platformer.jpg

    It spectacularly fails if you enable gravity (G key) since, as soon as there is perpetual contact between the sphere and the ground, the normals returned by Physics.SphereCastNonAlloc() stop making any sense.

    If there's no way to obtain the point of contact (or the /center/ of a standing contact) or its normal, I'll have to either return to physics-based character movement or hack something together like the stacked spheres method in Roystan Ross' "Super Character Controller."
     

    Attached Files:

    Last edited: Sep 7, 2017
  3. Cygon4

    Cygon4

    Joined:
    Sep 17, 2012
    Posts:
    382
    Alright, I discarded this attempt.

    If anyone reaches this thread in the future, my experience so far is that you have these three options for decent character physics:

    a) Use the built-in CharacterController
    b) Use built-in 'rigidbody' physics
    c) Use only spheres / use raycasts and hope for the best / roll your own intersection checks
     
  4. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Some update ago unity release Physics.ClosestPoint and Physics.ComputePenetration. Have a look at those, you can avoid using stacked spheres in many situations.
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I use this for my own character controller so I am quoting HiddenMonk for truth :)
     
    HiddenMonk likes this.