Search Unity

Custom Controller Gravity Woes, It weighs heavy...

Discussion in 'Physics' started by adamnorton, Jan 7, 2020.

  1. adamnorton

    adamnorton

    Joined:
    Oct 17, 2012
    Posts:
    39
    On this controller I am making, and everything seems to be progressing.
    But no matter what I do gravity is pulling me down.
    I noticed it fully when I am swimming.

    I explicitly turn it off but it still seems to pull me down. Even if it is off.
    Messing with mass/drag seems to have no effect.
    Messing with isKinematic of course makes me fall.

    I am using a mechanim controller with 2d motion, overridden with swim / crouch blendtrees
    apply root motion is on.

    Any ideas as to what I am not getting/understanding here?

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. namespace DeadWorld.ControllerSystem
    6. {
    7.     [DisallowMultipleComponent]
    8.     [RequireComponent(typeof(Rigidbody))]
    9.     [RequireComponent(typeof(Animator))]
    10.     [RequireComponent(typeof(CharacterController))]
    11.     public class CharController : MonoBehaviour
    12.     {
    13.  
    14.         [Header("Controller States")]
    15.         [SerializeField]
    16.         private LocomotionType _locomotionType = LocomotionType.Standard;
    17.         public LocomotionType LocomotionType
    18.         {
    19.             get => _locomotionType;
    20.             set => _locomotionType = value;
    21.         }
    22.         [SerializeField]
    23.         private ControllerState _controllerState = ControllerState.Locomotion;
    24.         public ControllerState ControllerState
    25.         {
    26.             get => _controllerState;
    27.             set => _controllerState = value;
    28.         }
    29.         [SerializeField]
    30.         private CharacterStance _characterStance = CharacterStance.Standing;
    31.         public CharacterStance CharacterStance
    32.         {
    33.             get => _characterStance;
    34.             set => _characterStance = value;
    35.         }
    36.  
    37.         [Header("Movement Checks")]
    38.         [SerializeField]
    39.         private bool _isRunning = false;
    40.         public bool IsRunning
    41.         {
    42.             get => _isRunning;
    43.             set => _isRunning = value;
    44.         }
    45.  
    46.         [SerializeField]
    47.         private bool _isJumping = false;
    48.         public bool IsJumping
    49.         {
    50.             get => _isJumping;
    51.             set => _isJumping = value;
    52.         }
    53.  
    54.         [Header("Water Settings")]
    55.         public float maxDistanceToWater = 10;
    56.         [ReadOnly] public float actualDistanceToWater = 0f;
    57.         public LayerMask waterLayer;
    58.         [SerializeField]
    59.         private bool _inWater = false;
    60.         public bool InWater
    61.         {
    62.             get => _inWater;
    63.             set => _inWater = value;
    64.         }
    65.         private bool _wasWater = false;
    66.  
    67.         [Header("Ground Settings")]
    68.         public float groundCheckDistance = .3f;
    69.         [ReadOnly] public float _actualDistanceToGround = 0f;
    70.         public LayerMask groundLayers;
    71.         [SerializeField]
    72.         private bool _isGrounded = true;
    73.         public bool IsGrounded
    74.         {
    75.             get => _isGrounded;
    76.             set => _isGrounded = value;
    77.         }
    78.  
    79.         [Header("Movement Amounts")]
    80.         [SerializeField]
    81.         private float _forwardMovement = 0.0f;
    82.         public float ForwardMovement
    83.         {
    84.             get => _forwardMovement;
    85.             set => _forwardMovement = value;
    86.         }
    87.         [SerializeField]
    88.         private float _directionalMovement = 0.0f;
    89.         public float DirectionalMovement {
    90.             get => _directionalMovement;
    91.             set => _directionalMovement = value;
    92.         }
    93.         [SerializeField]
    94.         private float _updownMovement = 0.0f;
    95.         public float UpDownMovement {
    96.             get => _updownMovement;
    97.             set => _updownMovement = value;
    98.         }
    99.  
    100.         [HideInInspector]
    101.         public Rigidbody rigidBody;
    102.         [HideInInspector]
    103.         public Animator animator;
    104.         [HideInInspector]
    105.         public CharacterController charCollider;
    106.         [HideInInspector]
    107.         public Transform leftFoot;
    108.         [HideInInspector]
    109.         public Transform rightFoot;
    110.         [HideInInspector]
    111.         public Transform hips;
    112.         [HideInInspector]
    113.         public Transform head;
    114.         [HideInInspector]
    115.         public Transform chest;
    116.  
    117.  
    118.         [Header("Miscellaneous Info")]
    119.         [ReadOnly] public float _originalCapsuleHeight;
    120.         [ReadOnly] public Vector3 _originalCapsuleCenter;
    121.         [ReadOnly] public bool _animatorInitialized = false;
    122.  
    123.         public GameObject InteractionPoint;
    124.         private bool _halfColliderSet = false;
    125.  
    126.         const float K_HALF = 0.5f;
    127.  
    128.         void Start()
    129.         {
    130.  
    131.             InitializeController();
    132.             CheckStates();
    133.  
    134.         }
    135.  
    136.         void InitializeController()
    137.         {
    138.             if (_animatorInitialized)
    139.             {
    140.                 return;
    141.             }
    142.  
    143.             //Get Components
    144.             rigidBody = GetComponent<Rigidbody>();
    145.             animator = GetComponent<Animator>();
    146.             charCollider = GetComponent<CharacterController>();
    147.  
    148.             rigidBody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationY;
    149.  
    150.             _originalCapsuleHeight = charCollider.height;
    151.             _originalCapsuleCenter = charCollider.center;
    152.  
    153.             ////Get Animator Bones for collider, for later
    154.             leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
    155.             rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
    156.             hips = animator.GetBoneTransform(HumanBodyBones.Hips);
    157.             chest = animator.GetBoneTransform(HumanBodyBones.Chest);
    158.             head = animator.GetBoneTransform(HumanBodyBones.Head);
    159.  
    160.             _animatorInitialized = ValidateController();
    161.             animator.SetBool("Initialized", _animatorInitialized);
    162.  
    163.         }
    164.  
    165.         bool ValidateController()
    166.         {
    167.             return rigidBody != null && animator != null && charCollider != null && InteractionPoint != null;
    168.         }
    169.         void Test()
    170.         {
    171.             //CharacterController c;
    172.  
    173.         }
    174.  
    175.         private void Update()
    176.         {
    177.             //InitializeController();
    178.         }
    179.  
    180.         void FixedUpdate()
    181.         {
    182.             CheckStates();
    183.             ScaleCapsule();
    184.             SetAnimatorOnUpdate();
    185.             MoveUpdown();
    186.         }
    187.  
    188.         void SetAnimatorOnUpdate()
    189.         {
    190.             animator.SetInteger("ControllerState", (int)ControllerState);
    191.             animator.SetInteger("CharacterStance", (int)CharacterStance);
    192.  
    193.             animator.SetBool("IsGrounded", IsGrounded);
    194.             animator.SetBool("IsRunning", IsRunning);
    195.             animator.SetBool("IsJumping", IsJumping);
    196.  
    197.             animator.SetFloat(Inputs.FORWARD, ForwardMovement);
    198.             animator.SetFloat(Inputs.ROTATE, DirectionalMovement);
    199.             animator.SetFloat("Updown", UpDownMovement);
    200.         }
    201.  
    202.         void CheckStates()
    203.         {
    204.             CheckIsSwimming();
    205.             CheckIsGrounded();
    206.         }
    207.  
    208.  
    209.         void MoveUpdown()
    210.         {
    211.             if (CharacterStance == CharacterStance.Swimming)
    212.             {
    213.                 if (UpDownMovement < 0)
    214.                     transform.position += Vector3.down * Mathf.Abs(UpDownMovement) * Time.deltaTime;
    215.                 else if (UpDownMovement > 0)
    216.                     transform.position += Vector3.up * Mathf.Abs(UpDownMovement) * Time.deltaTime;
    217.                 else
    218.                 {
    219.                     //rigidBody.velocity = Vector3.zero;
    220.                     //rigidBody.angularVelocity = Vector3.zero;
    221.                 }
    222.             }
    223.  
    224.         }
    225.  
    226.         void ScaleCapsule()
    227.         {
    228.             if ((CharacterStance == CharacterStance.Crouching
    229.                 || IsJumping)
    230.                 && !_halfColliderSet)
    231.             {
    232.                 charCollider.height = _originalCapsuleHeight / 2f;
    233.                 charCollider.center = _originalCapsuleCenter / 2f;
    234.             }
    235.             else
    236.             {
    237.                 charCollider.height = _originalCapsuleHeight;
    238.                 charCollider.center = _originalCapsuleCenter;
    239.                 _halfColliderSet = false;
    240.             }
    241.         }
    242.  
    243.         void CheckIsSwimming()
    244.         {
    245.             Color waterRayColor = Color.blue;
    246.  
    247.             Vector3 startPos = gameObject.transform.position + Vector3.up;
    248.  
    249.             //Debug.DrawRay(startPos, Vector3.up * maxDistanceToWater, waterRayColor);
    250.  
    251.             RaycastHit hit;
    252.             if (Physics.Raycast(startPos, Vector3.up, out hit, maxDistanceToWater, waterLayer))
    253.             {
    254.                 if (hit.collider.tag == "Water")
    255.                 {
    256.                     InWater = true;
    257.                     actualDistanceToWater = hit.distance;
    258.                 }
    259.                 else
    260.                 {
    261.                     InWater = false;
    262.                     actualDistanceToWater = 0;
    263.                 }
    264.             }
    265.             else
    266.             {
    267.                 InWater = false;
    268.             }
    269.  
    270.  
    271.             if (InWater && CharacterStance != CharacterStance.Swimming && _wasWater == false)
    272.             {
    273.                 CharacterStance = CharacterStance.Swimming;
    274.                 rigidBody.useGravity = false;
    275.             }
    276.             else if (!InWater && CharacterStance == CharacterStance.Swimming && _wasWater == true)
    277.             {
    278.                 CharacterStance = CharacterStance.Standing;
    279.                 rigidBody.useGravity = true;
    280.             }
    281.  
    282.             _wasWater = InWater;
    283.         }
    284.  
    285.         void CheckIsGrounded()
    286.         {
    287.  
    288.             Color groundRayColor = Color.green;
    289.             Vector3 startPos = transform.position;
    290.             Vector3 dir = transform.position + (Vector3.down * groundCheckDistance);
    291.  
    292.             //Debug.DrawLine(startPos, dir, groundRayColor);
    293.  
    294.             RaycastHit hit;
    295.  
    296.             //Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * groundCheckDistance), Color.green);
    297.  
    298.             if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hit, groundCheckDistance, groundLayers))
    299.             {
    300.                 IsGrounded = true;
    301.                 _actualDistanceToGround = hit.distance;
    302.             }
    303.             else
    304.             {
    305.                 IsGrounded = false;
    306.                 _actualDistanceToGround = 0;
    307.             }
    308.         }
    309.     }
    310. }
    311.  
     
    Last edited: Jan 7, 2020
  2. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Hello,
    I'm not quite sure and haven't tested, but here are a few observations

    • Try putting _wasWater above the if checking its value.

    • It seems you're checking water above your character (Vector3.Up)
    Code (CSharp):
    1. if (Physics.Raycast(startPos, Vector3.up, out hit, maxDistanceToWater, waterLayer))
    • Is there a parent RigidBody with useGravity = true?

    Sorry I don't help you more, I'm testing it better as soon as friday if nobody else found your issue.
     
  3. adamnorton

    adamnorton

    Joined:
    Oct 17, 2012
    Posts:
    39
    I believe that what I have accurately detects water. The problem is gravity. even when that is off it sinks. And the only place I am turning it of is where and when I detect the water.

    The water plane AQUAS has a collider which is above the character at this point.

    upload_2020-1-7_23-54-23.png
     
  4. adamnorton

    adamnorton

    Joined:
    Oct 17, 2012
    Posts:
    39
  5. adamnorton

    adamnorton

    Joined:
    Oct 17, 2012
    Posts:
    39
    It was the CharacterController, switched back to RigidBody and CapsuleCollider and gravity works fine. I'll have to rework the Step Climber script but hey. Gravity > Steps so... progress? :p
     
  6. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Aah Gravity. Always pulling you down.
    In a sense I'm reassured it comes from somewhere else because I couldn't find anything wrong with your script.
    Now, even if gravity is a simple force vector pointing down in the perspective of the ground, your RigidBody may help you with other things. I hope fixing your StepClimber won't be too much of a hassle :) Good job so far so I believe you'll be fine ;)