Search Unity

  1. Want to see 2020.1b in action? Sign up for our Beta 2020.1 Overview Webinar on April 20th for a live presentation from our evangelists and a Q&A session with guests from R&D.
    Dismiss Notice
  2. Interested in giving us feedback? Join our online research interviews on a broad range of topics and share your insights with us.
    Dismiss Notice
  3. We're hosting a webinar for the new Input System where you'll be able to get in touch with the devs. Sign up now and share your questions with us in preparation for the session on April 15.
    Dismiss Notice

[Samples Project for 0.2.5-preview]Character controller issue.

Discussion in 'DOTS Physics' started by linfuqing, Dec 18, 2019.

  1. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    CharacterControllerUtilities.cs:
    upload_2019-12-18_15-10-27.png
    Why CalculateDistance in the loop instead of calculate in CheckSupport same as previous version?
    I think this change do the same thing and lower performance.
    Did I miss something?
     
    Last edited: Dec 18, 2019
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Previous implementation was trying to get best performance, but unfortunately was incorrect - after the first iteration in the CollideAndIntegrate, it still used old results from CheckSupport, even though the character changed position, so the results are incorrect. I know it's a performance degradation, but it was necessary for stability and collision quality of the character. We have some new changes in the works already and will try to improve performance, while not degrading quality, for the next release.
     
  3. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    But the ColliderDistanceInput.Transform isn't modified per iteration,will it return the same result?
     
  4. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Yes, that's one of the things "in the works", it's a bug.
     
  5. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    And I want to handstand the character,like this:

    In the old version CheckSupport return Sliding or Supported if I set maxSlopeCos = -1, but the new version return Unsupported.
    Why?
     
  6. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    upload_2019-12-18_21-58-33.png
    Should this be "velAlongDownwardsDir < 1.0f"?
     
  7. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    I don't think so, it's a dot product along downwards direction, so it's positive if velocity is also downwards...
     
  8. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    I'll need to dig a bit deeper to answer this.
     
  9. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    I mean the point is "math.abs(velAlongDownwardsDir ) > 1.0f":
    Code (CSharp):
    1. float3 initialVelocity;
    2.             {
    3.                 float velAlongDownwardsDir = math.dot(currentVelocity, downwardsDirection);
    4.                 bool velocityIsAlongDownwardsDirection = velAlongDownwardsDir > 0.0f;
    5.                 if (velocityIsAlongDownwardsDirection)
    6.                 {
    7.                     float3 downwardsVelocity = velAlongDownwardsDir * downwardsDirection;
    8.                     initialVelocity =
    9.                         math.select(downwardsVelocity, downwardsDirection, velAlongDownwardsDir < 1.0f) +
    10.                         stepInput.Gravity * stepInput.DeltaTime;
    11.                 }
    12.                 else
    13.                 {
    14.                     initialVelocity = downwardsDirection;
    15.                 }
    16.             }
    17.  
    My character to climb has a suction toward to downward and maxSlopeCos = -1
    upload_2019-12-19_14-47-42.png
    it's work in previous version.

    But now math.select(downwardsVelocity, downwardsDirection, velAlongDownwardsDir > 1.0f) always less than stepInput.Gravity * stepInput.DeltaTime so that CheckSupport return Unsupported,character can't suspend.

    How can i do in new version to implement this functionality?
     

    Attached Files:

    Last edited: Dec 19, 2019
  10. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Can you provide an example input to CheckSupport call that I can use to reproduce your issue with maxSlopeCos = -1? I know it's a bit too much to ask, but it would really help me a lot to figure out what happened.
     
  11. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Actually, it might be as simple as this: find the line that calculates slopeAngleSin and subtract the value by k_SimplexSolverEpsilon. I think that would do it for now, it was there before. I'll try to remember why this got removed and if we can get it back. Let me know if it worked in the meantime!

    Edit: or even better, change the if 2 lines below to use <= check. That will do it for you.
     
    Last edited: Dec 19, 2019
  12. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    This is my modified version:
    Code (CSharp):
    1.         public static unsafe CharacterSupportState CheckSupport(
    2.             in CharacterControllerStepInput stepInput,
    3.             in float3 currentVelocity,
    4.             in NativeSlice<DistanceHit> distanceHits,
    5.             ref float3 position,
    6.             out float3 surfaceNormal,
    7.             out float3 surfaceVelocity)
    8.         {
    9.             surfaceNormal = float3.zero;
    10.             surfaceVelocity = float3.zero;
    11.            
    12.             // If no hits, proclaim unsupported state
    13.             if (distanceHits.Length == 0)
    14.                 return CharacterSupportState.Unsupported;
    15.  
    16.             /////////////////////////////////////////////////////////
    17.             ///Modify 1: Keep same results between client and server.
    18.             /////////////////////////////////////////////////////////
    19.             distanceHits.Sort(DistanceHitComparer.defaultValue);
    20.  
    21.             // Downwards direction must be normalized
    22.             float3 downwardsDirection = -stepInput.Up;
    23.             //Assert.IsTrue(Math.IsNormalized(downwardsDirection));
    24.            
    25.             // Iterate over distance hits and create constraints from them
    26.             NativeList<SurfaceConstraintInfo> constraints = new NativeList<SurfaceConstraintInfo>(k_DefaultConstraintsCapacity, Allocator.Temp);
    27.             for (int i = 0; i < distanceHits.Length; i++)
    28.             {
    29.                 DistanceHit hit = distanceHits[i];
    30.                 CreateConstraint(stepInput.World, stepInput.Up,
    31.                     hit.RigidBodyIndex, hit.ColliderKey, hit.Position, hit.SurfaceNormal, hit.Distance,
    32.                     stepInput.SkinWidth, stepInput.MaxSlope, ref constraints);
    33.             }
    34.  
    35.             float3 initialVelocity;
    36.             {
    37.                 float velAlongDownwardsDir = math.dot(currentVelocity, downwardsDirection);
    38.                 bool velocityIsAlongDownwardsDirection = velAlongDownwardsDir > 0.0f;
    39.                 if (velocityIsAlongDownwardsDirection)
    40.                 {
    41.                     float3 downwardsVelocity = velAlongDownwardsDir * downwardsDirection;
    42.                     initialVelocity =
    43.                     //////////////////////////////////////////////////////////////////////////////////////////////////////////
    44.                     ///Modify 2: When stepInput.Up = normalize(stepInput.Gravity)
    45.                     ///I need a downward(-stepInput.Up) section which value greater than stepInput.Gravity * stepInput.DeltaTime,
    46.                     ///So that SimplexSolver.Solve can give me some supporting planes to suspend.
    47.                     ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    48.                         math.select(downwardsDirection, downwardsVelocity, velAlongDownwardsDir > 1.0f) +
    49.                         stepInput.Gravity * stepInput.DeltaTime;
    50.                     /*math.select(downwardsVelocity, downwardsDirection, math.abs(velAlongDownwardsDir) > 1.0f) +
    51.                     stepInput.Gravity * stepInput.DeltaTime;*/
    52.                 }
    53.                 else
    54.                 {
    55.                     initialVelocity = downwardsDirection;
    56.                 }
    57.             }
    58.  
    59.             // Solve downwards (don't use min delta time, try to solve full step)
    60.             float3 outVelocity = initialVelocity;
    61.             SimplexSolver.Solve(stepInput.World, stepInput.DeltaTime, stepInput.DeltaTime, stepInput.Up, stepInput.MaxMovementSpeed,
    62.                 constraints, ref position, ref outVelocity, out float integratedTime, false);
    63.            
    64.             int numSupportingPlanes = 0;
    65.             // Get info on surface
    66.             {
    67.                 for (int j = 0; j < constraints.Length; j++)
    68.                 {
    69.                     var constraint = constraints[j];
    70.                     if (constraint.Touched && !constraint.IsTooSteep)
    71.                     {
    72.                         numSupportingPlanes++;
    73.                         surfaceNormal += constraint.Plane.Normal;
    74.                         surfaceVelocity += constraint.Velocity;
    75.                     }
    76.                 }
    77.  
    78.                 if (numSupportingPlanes > 0)
    79.                 {
    80.                     float invNumSupportingPlanes = 1.0f / numSupportingPlanes;
    81.                     surfaceNormal *= invNumSupportingPlanes;
    82.                     surfaceVelocity *= invNumSupportingPlanes;
    83.  
    84.                     surfaceNormal = math.normalize(surfaceNormal);
    85.                 }
    86.                 ///////////////////////////
    87.                 ///MODIFY 3: This is a bug.
    88.                 ///////////////////////////
    89.                 else
    90.                     return CharacterSupportState.Unsupported;
    91.             }
    92.  
    93.             // Check support state
    94.             {
    95.                 if (math.lengthsq(initialVelocity - outVelocity) < k_SimplexSolverEpsilonSq)
    96.                 {
    97.                     // If velocity hasn't changed significantly, declare unsupported state
    98.                     return CharacterSupportState.Unsupported;
    99.                 }
    100.                 else if (math.lengthsq(outVelocity) < k_SimplexSolverEpsilonSq)
    101.                 {
    102.                     // If velocity is very small, declare supported state
    103.                     return CharacterSupportState.Supported;
    104.                 }
    105.                 /////////////////////////////////////////////////////////
    106.                 ///MODIFY 4: The stepInput.MaxSlope is maxSlopeCos for me, and stepInput.MaxSlope < 0.0f always supported.
    107.                 /////////////////////////////////////////////////////////
    108.                 else if (stepInput.MaxSlope > 0.0f)
    109.                 {
    110.                     // Check if sliding or supported
    111.                     outVelocity = math.normalize(outVelocity);
    112.                     float slopeAngleSin = math.max(0.0f, math.dot(outVelocity, downwardsDirection));
    113.                     float slopeAngleCosSq = 1 - slopeAngleSin * slopeAngleSin;
    114.                     if (slopeAngleCosSq < stepInput.MaxSlope * stepInput.MaxSlope)
    115.                     {
    116.                         return CharacterSupportState.Sliding;
    117.                     }
    118.                     else
    119.                     {
    120.                         return CharacterSupportState.Supported;
    121.                     }
    122.                 }
    123.                 else
    124.                     return CharacterSupportState.Supported;
    125.  
    126.             }
    127.         }
    128.  
    For MODIFY 2 and 4:Is my understanding right?
     
  13. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Regarding MODIFY 4, it looks fine for your use case. I didn't know you've reconfigured what MaxSlope means, but it feels right for your character.

    Regarding MODIFY 2, that was the intention, I guess it somehow got mixed up with the order of math.select... As long as we're at it, I'd like to change this to something like:
    initialVelocity = - stepInput.ContactTolerance * stepInput.Up / stepInput.DeltaTime;

    This current approach feels a bit arbitrary and I'd like to see it simplified, and this is one attempt. Essentially, it's a velocity to overcome contact tolerance in one frame, since contact tolerance is what we use for query in the support check (if I remember correctly what was in this version).

    Could you please give it a go and let me know how it feels?

    Also, regarding MODIFY 3, having no support planes doesn't mean you are unsupported, you could be sliding, right?
     
  14. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    MODIFY 2,yes,I think the currentVelocity param is unnecessary too and the slope can make sure to supported or not.

    About MODIFY 3,surface normal = (0,0,0) If no support planes,than my surface rotation will be nan,and unity crash per time...
     
    Last edited: Dec 20, 2019
  15. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    To get things clear, you got Supported state and surface normal was (0,0,0)? If it's invalid and state is Supported, that's a bug for sure.
     
  16. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    Hi,I sure there is something wrong in SelfFilteringClosestHitCollector<T>.
    This is my modified version:
    Code (CSharp):
    1.  
    2.     public struct SelfFilteringClosestHitCollector<T> : ICollector<T> where T : struct, IQueryResult
    3.     {
    4.         public bool EarlyOutOnFirstHit => false;
    5.         public float MaxFraction { get; private set; }
    6.         public int NumHits { get; private set; }
    7.  
    8.         public T closestHit => __hit;
    9.  
    10.         private T __hit;
    11.         private T __oldHit;
    12.  
    13.         private float __fraction;
    14.  
    15.         private int __rigidBodyIndex;
    16.  
    17.         public SelfFilteringClosestHitCollector(int rigidBodyIndex, float maxFraction)
    18.         {
    19.             __hit = default;
    20.             __oldHit = default;
    21.             __fraction = maxFraction;
    22.             MaxFraction = maxFraction;
    23.             NumHits = 0;
    24.             __rigidBodyIndex = rigidBodyIndex;
    25.         }
    26.  
    27.         #region ICollector
    28.  
    29.         public bool AddHit(T hit)
    30.         {
    31.             MaxFraction = hit.Fraction;
    32.             __hit = hit;
    33.  
    34.             return true;
    35.         }
    36.  
    37.         public void TransformNewHits(int oldNumHits, float oldFraction, Math.MTransform transform, uint numSubKeyBits, uint subKey)
    38.         {
    39.             float fraction = __oldHit.Fraction;
    40.             if (fraction < oldFraction && NumHits > 0)
    41.                 __oldHit.Transform(transform, numSubKeyBits, subKey);
    42.  
    43.             __hit.Transform(transform, numSubKeyBits, subKey);
    44.         }
    45.  
    46.         public void TransformNewHits(int oldNumHits, float oldFraction, Math.MTransform transform, int rigidBodyIndex)
    47.         {
    48.             if (rigidBodyIndex == __rigidBodyIndex)
    49.             {
    50.                 float fraction = __oldHit.Fraction;
    51.                 if (fraction < oldFraction && NumHits > 0)
    52.                     __oldHit.Transform(transform, rigidBodyIndex);
    53.  
    54.                 __hit = __oldHit;
    55.  
    56.                 MaxFraction = __fraction;
    57.             }
    58.             else
    59.             {
    60.                 __hit.Transform(transform, rigidBodyIndex);
    61.  
    62.                 __oldHit = __hit;
    63.  
    64.                 __fraction = __hit.Fraction;
    65.  
    66.                 ++NumHits;
    67.             }
    68.         }
    69.  
    70.         #endregion
    71.     }
    72.  
     
    Last edited: Jan 20, 2020
  17. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    116
    I was experiencing NAN values when the character controller was on certain slopes. I was able to trace the origin of these NAN values to the CalculateMovement() method in CharacterControllerAuthoring.cs.

    The issue was due to the use of math.normalize() in CalculateMovement():

    Code (CSharp):
    1.        float3 binorm;
    2.             {
    3.                 binorm = math.cross(forward, up);
    4.                 binorm = math.normalize(binorm);
    5.  
    6.                 float3 tangent = math.cross(binorm, surfaceNormal);
    7.                 tangent = math.normalize(tangent);
    8.  
    9.                 binorm = math.cross(tangent, surfaceNormal);
    10.                 binorm = math.normalize(binorm);
    11.  
    12.                 surfaceFrame.Value = new quaternion(new float3x3(binorm, tangent, surfaceNormal));
    13.             }
    Simply replacing math.normalize() with math.normalizesafe() solved the NAN values issue for me:

    Code (CSharp):
    1.         float3 binorm;
    2.             {
    3.                 binorm = math.cross(forward, up);
    4.                 binorm = math.normalizesafe(binorm);
    5.  
    6.                 float3 tangent = math.cross(binorm, surfaceNormal);
    7.                 tangent = math.normalizesafe(tangent);
    8.  
    9.                 binorm = math.cross(tangent, surfaceNormal);
    10.                 binorm = math.normalizesafe(binorm);
    11.  
    12.                 surfaceFrame.Value = new quaternion(new float3x3(binorm, tangent, surfaceNormal));
    13.             }  
     
  18. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Before I get into comparing and analyzing what's the difference between the public version and your changes, can I ask if you observed any issue with the current implementation? If yes, what exactly went wrong?
     
  19. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Although math.normalizesafe() looks like a solution to your problem, the real question is why you are getting NANs in math.normalize(). Which call made these NANs? The first one shouldn't, maybe the second or the third one which is using a surfaceNormal? If so, I'm guessing the surfaceNormal was (0,0,0). If that's the case this function should never be called in the first place. Let's find out why exactly you are hitting this because introducing a safe method.
     
  20. Flipps

    Flipps

    Joined:
    Jul 30, 2019
    Posts:
    42
    I dont know if it is the same bug, but using normalizeSafe in the CalculateMovement also solves this bug.



    Easy to reproduce: Only run the Physics CharaterController Sample and move the character between the 2nd and 3rd slope -> character disappears (no exception only error thrown).
    (see video)

    With normalizeSafe everything works.
     
  21. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    116
    If you disable burst (or just comment it out for the character controller job) you will likely see a failed assert due to a NAN value.

    Yes the issue occurs when the surface normal is zero. This occurs when a character controller is on an extremely steep slope.

    character controller step slope.png

    I have replaced normalizesafe with normalize and done some more debugging. I have found that the CharacterControllerUtilities.CheckSupport() method can simultaneously create a supported state of supported and a surface normal of zero in certain conditions.

    Here is a debug output from a debug statement I added to check for this:

    Surface normal: float3(0f, 0f, 0f), SupportedState: Supported
    UnityEngine.Debug:Log(Object)
    CharacterControllerJob:Execute(ArchetypeChunk, Int32, Int32) (at Assets/Demos/6. Use Cases/CharacterController/Scripts/CharacterControllerAuthoring.cs:197)


    I also added debug statements to everywhere the surface normal value is altered in the CharacterControllerUtilities.CheckSupport() method, but they are not called in the case where the character controller is determined to be have a supported state with a surface normal of zero (the surface normal retains its default value of (0f,0f,0f)).

    A simple solution is to simply set the supported state of the character controller to unsupported (or sliding perhaps?) if the surface normal is (0,0,0) and the character supported state is supported, but I feel like this isn't the best solution.
     
    Last edited: Jan 22, 2020
    Flipps likes this.
  22. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    Current version is not return the closest hit sometime in my test.
    I guess when AddHit give 3 hit a,b,c, if b is self-rigidbody, a.Friction > c.Friction and c.Friction > b.Friction,c is discarded.
     
  23. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Ah, right, I've noticed this a while ago and fixed it, so when you get supported state the normal will always be valid. This will be available in the next release. Thanks for the detailed analysis!
     
    desertGhost_ likes this.
  24. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Thanks for the test case, I will look into it!
     
  25. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    I've just verified that all NANs are due to the same issue, surfaceNormal being (0,0,0) and support state being Supported. I've fixed the bug and it will be available soon.

    In the meantime, I suggest setting the support state to Unsupported if surfaceNormal is (0,0,0), that should get rid of all the NANs for now (CalculateMovement() will never be called with invalid input).
     
    Flipps likes this.
  26. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Can you try the following implementation of the collector and let me know if it works in your tests?

    Code (CSharp):
    1. public struct SelfFilteringClosestHitCollector<T> : ICollector<T> where T : struct, IQueryResult
    2. {
    3.     public bool EarlyOutOnFirstHit => false;
    4.     public float MaxFraction { get; private set; }
    5.     public int NumHits { get; private set; }
    6.  
    7.     private float m_prevMaxFraction;
    8.     private int m_prevNumHits;
    9.  
    10.     private T m_OldHit;
    11.     private T m_ClosestHit;
    12.     public T ClosestHit => m_ClosestHit;
    13.  
    14.     private int m_selfRBIndex;
    15.  
    16.     public SelfFilteringClosestHitCollector(int rbIndex, float maxFraction)
    17.     {
    18.         m_prevMaxFraction = 0;
    19.         MaxFraction = maxFraction;
    20.         m_OldHit = default(T);
    21.         m_ClosestHit = default(T);
    22.         m_prevNumHits = 0;
    23.         NumHits = 0;
    24.         m_selfRBIndex = rbIndex;
    25.     }
    26.  
    27.     #region ICollector
    28.  
    29.     public bool AddHit(T hit)
    30.     {
    31.         Assert.IsTrue(hit.Fraction <= MaxFraction);
    32.         m_prevMaxFraction = MaxFraction;
    33.         MaxFraction = hit.Fraction;
    34.         m_OldHit = m_ClosestHit;
    35.         m_ClosestHit = hit;
    36.         m_prevNumHits = NumHits;
    37.         NumHits = 1;
    38.         return true;
    39.     }
    40.  
    41.     public void TransformNewHits(int oldNumHits, float oldFraction, Unity.Physics.Math.MTransform transform, uint numSubKeyBits, uint subKey)
    42.     {
    43.         if (m_ClosestHit.Fraction < oldFraction)
    44.         {
    45.             m_ClosestHit.Transform(transform, numSubKeyBits, subKey);
    46.         }
    47.     }
    48.  
    49.     public void TransformNewHits(int oldNumHits, float oldFraction, Unity.Physics.Math.MTransform transform, int rigidBodyIndex)
    50.     {
    51.         if (rigidBodyIndex == m_selfRBIndex)
    52.         {
    53.             MaxFraction = m_prevMaxFraction;
    54.             m_prevMaxFraction = 0;
    55.             m_ClosestHit = m_OldHit;
    56.             m_OldHit = default(T);
    57.             NumHits = m_prevNumHits;
    58.             m_prevNumHits = 0;
    59.             return;
    60.         }
    61.  
    62.         if (m_ClosestHit.Fraction < oldFraction)
    63.         {
    64.             m_ClosestHit.Transform(transform, rigidBodyIndex);
    65.         }
    66.     }
    67.  
    68.     #endregion
    69. }
     
  27. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    It can get the correct results in my tests at hand.
    But is it correct if multiple hits inside the selfRB?
    For example,AddHit give me 3 hits A,B,C.
    B,C inside selfRB and A is not.
    Is A discarded in the implementation?
     
    Last edited: Jan 26, 2020
  28. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Well multiple hits inside the selfRB is not possible - you can get multiple hits inside a single body if that body is a composite collider, like mesh or a compound. Character is always a convex shape, therefore it can only produce one self hit. Your concern is valid in a general case, but it's completely safe to do this in the context of the character controller.
     
  29. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    hi,@petarmHavok ,can i get the new version this week?
    My game has a release plan this month,but cc tunnel through terrain sometime in current version.
    Or can give me some suggest or a single file to fix it?
     
  30. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    linfuqing and PhilSA like this.
  31. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    In Samples Project for 0.3.0-preview:
    upload_2020-3-14_16-3-34.png

    I think this is a bug in new version.
    And SelfAndTriggerFilteringClosestHitCollector have the #27 situation when the trigger in a CompoundCollider.
     
  32. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100

    The two issue in the video(Samples Project for 0.3.0-preview):
    1.If i set a large MaxMovementSpeed(10-50),it look like this video, or if i set the value less than 10,the desired velocity are changed in the same time.
    2.cc tunnel through terrain.
     
  33. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    I think the bug is because of SelfAndTriggerFilteringClosestHitCollector.
    I change the code line 458-495 in CharacterControllerUtilities.cs to:
    Code (CSharp):
    1.  
    2.                     SelfFilteringAllHitsCollector<ColliderCastHit> newCollector = new SelfFilteringAllHitsCollector<ColliderCastHit>(stepInput.RigidBodyIndex, 1.0f, ref castHits);
    3.  
    4.                     ColliderCastInput input = new ColliderCastInput()
    5.                     {
    6.                         Collider = Collider,
    7.                         Orientation = orientation,
    8.                         Start = prevPosition,
    9.                         End = prevPosition + newDisplacement
    10.                     };
    11.  
    12.                     stepInput.World.CastCollider(input, ref newCollector);
    13.                
    14.                     float minFraction = 1.0f, fraction, testFraction = 1.0f;
    15.                     for (int hitIndex = 0; hitIndex < newCollector.NumHits; hitIndex++)
    16.                     {
    17.                         ColliderCastHit hit = newCollector.AllHits[hitIndex];
    18.                         fraction = hit.Fraction;
    19.                         testFraction = math.min(testFraction, fraction);
    20.                         if (fraction < minFraction)
    21.                         {
    22.                             bool found = false;
    23.                             for (int constraintIndex = 0; constraintIndex < constraints.Length; constraintIndex++)
    24.                             {
    25.                                 SurfaceConstraintInfo constraint = constraints[constraintIndex];
    26.                                 if (constraint.RigidBodyIndex == hit.RigidBodyIndex &&
    27.                                     constraint.ColliderKey.Equals(hit.ColliderKey))
    28.                                 {
    29.                                     found = true;
    30.                                     break;
    31.                                 }
    32.                             }
    33.  
    34.                             if (!found)
    35.                                 minFraction = fraction;
    36.                         }
    37.                     }
    38.  
    39.                     if(minFraction < 1.0f)
    40.                     {
    41.                         ///////////////////////
    42.                         //But is false sometime,and no trigger
    43.                         ///////////////////////
    44.                         Assert.IsTrue(testFraction < minFraction);
    45.  
    46.                         Assert.IsTrue(minFraction >= 0.0f);
    47.  
    48.                         integratedTime *= minFraction;
    49.                         newPosition = prevPosition + newDisplacement * minFraction;
    50.                     }
    51.  
     
  34. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    So the GetLeaf() should always return a convex collider. I don't know if that debug display is correct, I see that MemorySize in it is 0, which is obviously invalid. If you look at the code of GetLeaf you'll see that it verifies that the leaf collider is convex when returning. Because of all the code to cast collider pointers around I believe that the VS display is wrong. If you want to verify this, add something like this in there:
    Assert.IsTrue(UnsafeUtilityEx.AsRef<ConvexColliderHeader>(leafCollider.Collider).CollisionType == CollisionType.Convex);

    If you get it to hit, we can try to repro it on our end.

    Regarding the #27 we talked about, I'll try to explain. Self RB index is only there to filter out the overlap of capsule with the capsule itself. So no triggers or compounds will be filtered out by this - already overlapping hits will be covered, it's only there so that we can avoid the capsule of the character colliding with itself.
     
  35. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    If this is your fix for the terrain tunneling issue, I think you are right, I'll try to verify on my end and see what happens.

    Regarding the max movement speed, I'll try to see what's going on there.
     
  36. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    vs is right.
    MemorySize is 0 because of i create the mesh collider from file.it look like:
    Code (CSharp):
    1.         string physicsPath = Path.Combine(Application.streamingAssetsPath, "Server/physics");
    2.         if (File.Exists(physicsPath))
    3.         {
    4.             var colliderBlobInstances = new Unity.Collections.NativeList<CompoundCollider.ColliderBlobInstance>(Unity.Collections.Allocator.Temp);
    5.             using (BinaryReader reader = new BinaryReader(File.OpenRead(physicsPath)))
    6.             {
    7.                 reader.Deserialize(colliderBlobInstances.Add);
    8.             }
    9.  
    10.             CompoundCollider.ColliderBlobInstance colliderBlobInstance;
    11.             colliderBlobInstance.Collider = CompoundCollider.Create(colliderBlobInstances);
    12.  
    13.             Debug.Log("Physics Memory Size(M): " + (colliderBlobInstance.Collider.Value.MemorySize >> 20));
    14.  
    15.             colliderBlobInstance.CompoundFromChild = Unity.Mathematics.RigidTransform.identity;
    16.             __CreateCompoundCollider(colliderBlobInstance);
    17.  
    18.             colliderBlobInstances.Dispose();
    19.         }
    I try to modify the SelfAndTriggerFilteringClosestHitCollector:
    Code (CSharp):
    1. public void TransformNewHits(int oldNumHits, float oldFraction, Math.MTransform transform, uint numSubKeyBits, uint subKey)
    2.         {
    3.             //m_lastColliderKey = ColliderKey.Empty;
    4.             m_lastColliderKey.PushSubKey(numSubKeyBits, subKey);
    5.             if (m_ClosestHit.Fraction < oldFraction)
    6.             {
    7.                 m_ClosestHit.Transform(transform, numSubKeyBits, subKey);
    8.             }
    9.         }
    it seem be fix.
     
  37. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    But this is the previous version, right? In the new version of the collector there should be no TransformNewHits at all...

    However, I did find the issue in the closest hit collector regarding the code where you changed it to use all hits collector... I'll figure out what's the best way to share it with you so you can give it a go.
     
  38. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    It's seem hard to tunnel,but i can't sure.the video 30s show what happen.
     
  39. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    https://github.com/Unity-Technologi...oller/Scripts/CharacterControllerUtilities.cs
    in line 163...
     
  40. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    Ah sorry, we have a fix for this in the pipeline, it will be available soon. It just didn't make it to this release and I forgot about that. So I'm pretty sure your tunneling issue and all this self rb and trigger filtering issue will be gone. Can't share the fixes though as the core of the code has been changed and it would require a lot of files...

    I'll take a look at the max movement speed in the meantime.
     
    linfuqing likes this.
  41. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    If your MaxMovementSpeed is smaller than the length of the desiredVelocity, it is expected that it clamps the desiredVelocity. That's the whole point, to always make sure character is not walking faster than some value.

    The issue you are seeing is most likely not related to MaxMovementSpeed, but some aggressive penetration recovery. I'd wait for the next release and the tunneling fixes before looking at this again.
     
  42. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    556
    Hi @petarmHavok. Can you port raycast based Character Controller from DOTSSample into this physics sample project that is compatible with DOTS Netcode? There are a lot of extra code I not really understand how it works.
     
  43. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    But the maxSpeed=walking speed+gravity*time.
    If I set the MaxMovementSpeed approximately walking speed,cc jump slowly, It looks strange.
    Can MaxMovementSpeed be only used for recovering?
     
  44. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    I am looking into this, but it might take some time. If we are talking about the same thing, I believe the missing piece is the "follow ground" system that currently uses ray casts. Is that correct?
     
  45. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    @linfuqing With the new release out since last night, please let me know if you are seeing more issues with your character. Be careful to follow the upgrade guide since custom collectors have been changed.
     
  46. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    556
    I guess not only "follow ground" system but also "check support" system and "step" system.
     
    petarmHavok likes this.
  47. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    Hi, @petarmHavok , tunneling issue in the new version have not be fix.
     
  48. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    My step time is a large value(0.25).Is it the reason of this issue?
     
  49. linfuqing

    linfuqing

    Joined:
    May 11, 2015
    Posts:
    100
    And I sure now the method #33 can't fix this issue too.
     
  50. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    73
    I doubt that matters. Just to check, are you using out-of-the-box character controller from latest release, or you have local changes? If you do, could you please share which changes you have so that I can verify none of the conflicts with the latest code?
     
unityunity