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?
using UnityEngine;
using System.Collections;
namespace DeadWorld.ControllerSystem
{
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(CharacterController))]
public class CharController : MonoBehaviour
{
[Header("Controller States")]
[SerializeField]
private LocomotionType _locomotionType = LocomotionType.Standard;
public LocomotionType LocomotionType
{
get => _locomotionType;
set => _locomotionType = value;
}
[SerializeField]
private ControllerState _controllerState = ControllerState.Locomotion;
public ControllerState ControllerState
{
get => _controllerState;
set => _controllerState = value;
}
[SerializeField]
private CharacterStance _characterStance = CharacterStance.Standing;
public CharacterStance CharacterStance
{
get => _characterStance;
set => _characterStance = value;
}
[Header("Movement Checks")]
[SerializeField]
private bool _isRunning = false;
public bool IsRunning
{
get => _isRunning;
set => _isRunning = value;
}
[SerializeField]
private bool _isJumping = false;
public bool IsJumping
{
get => _isJumping;
set => _isJumping = value;
}
[Header("Water Settings")]
public float maxDistanceToWater = 10;
[ReadOnly] public float actualDistanceToWater = 0f;
public LayerMask waterLayer;
[SerializeField]
private bool _inWater = false;
public bool InWater
{
get => _inWater;
set => _inWater = value;
}
private bool _wasWater = false;
[Header("Ground Settings")]
public float groundCheckDistance = .3f;
[ReadOnly] public float _actualDistanceToGround = 0f;
public LayerMask groundLayers;
[SerializeField]
private bool _isGrounded = true;
public bool IsGrounded
{
get => _isGrounded;
set => _isGrounded = value;
}
[Header("Movement Amounts")]
[SerializeField]
private float _forwardMovement = 0.0f;
public float ForwardMovement
{
get => _forwardMovement;
set => _forwardMovement = value;
}
[SerializeField]
private float _directionalMovement = 0.0f;
public float DirectionalMovement {
get => _directionalMovement;
set => _directionalMovement = value;
}
[SerializeField]
private float _updownMovement = 0.0f;
public float UpDownMovement {
get => _updownMovement;
set => _updownMovement = value;
}
[HideInInspector]
public Rigidbody rigidBody;
[HideInInspector]
public Animator animator;
[HideInInspector]
public CharacterController charCollider;
[HideInInspector]
public Transform leftFoot;
[HideInInspector]
public Transform rightFoot;
[HideInInspector]
public Transform hips;
[HideInInspector]
public Transform head;
[HideInInspector]
public Transform chest;
[Header("Miscellaneous Info")]
[ReadOnly] public float _originalCapsuleHeight;
[ReadOnly] public Vector3 _originalCapsuleCenter;
[ReadOnly] public bool _animatorInitialized = false;
public GameObject InteractionPoint;
private bool _halfColliderSet = false;
const float K_HALF = 0.5f;
void Start()
{
InitializeController();
CheckStates();
}
void InitializeController()
{
if (_animatorInitialized)
{
return;
}
//Get Components
rigidBody = GetComponent<Rigidbody>();
animator = GetComponent<Animator>();
charCollider = GetComponent<CharacterController>();
rigidBody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ | RigidbodyConstraints.FreezeRotationY;
_originalCapsuleHeight = charCollider.height;
_originalCapsuleCenter = charCollider.center;
////Get Animator Bones for collider, for later
leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
hips = animator.GetBoneTransform(HumanBodyBones.Hips);
chest = animator.GetBoneTransform(HumanBodyBones.Chest);
head = animator.GetBoneTransform(HumanBodyBones.Head);
_animatorInitialized = ValidateController();
animator.SetBool("Initialized", _animatorInitialized);
}
bool ValidateController()
{
return rigidBody != null && animator != null && charCollider != null && InteractionPoint != null;
}
void Test()
{
//CharacterController c;
}
private void Update()
{
//InitializeController();
}
void FixedUpdate()
{
CheckStates();
ScaleCapsule();
SetAnimatorOnUpdate();
MoveUpdown();
}
void SetAnimatorOnUpdate()
{
animator.SetInteger("ControllerState", (int)ControllerState);
animator.SetInteger("CharacterStance", (int)CharacterStance);
animator.SetBool("IsGrounded", IsGrounded);
animator.SetBool("IsRunning", IsRunning);
animator.SetBool("IsJumping", IsJumping);
animator.SetFloat(Inputs.FORWARD, ForwardMovement);
animator.SetFloat(Inputs.ROTATE, DirectionalMovement);
animator.SetFloat("Updown", UpDownMovement);
}
void CheckStates()
{
CheckIsSwimming();
CheckIsGrounded();
}
void MoveUpdown()
{
if (CharacterStance == CharacterStance.Swimming)
{
if (UpDownMovement < 0)
transform.position += Vector3.down * Mathf.Abs(UpDownMovement) * Time.deltaTime;
else if (UpDownMovement > 0)
transform.position += Vector3.up * Mathf.Abs(UpDownMovement) * Time.deltaTime;
else
{
//rigidBody.velocity = Vector3.zero;
//rigidBody.angularVelocity = Vector3.zero;
}
}
}
void ScaleCapsule()
{
if ((CharacterStance == CharacterStance.Crouching
|| IsJumping)
&& !_halfColliderSet)
{
charCollider.height = _originalCapsuleHeight / 2f;
charCollider.center = _originalCapsuleCenter / 2f;
}
else
{
charCollider.height = _originalCapsuleHeight;
charCollider.center = _originalCapsuleCenter;
_halfColliderSet = false;
}
}
void CheckIsSwimming()
{
Color waterRayColor = Color.blue;
Vector3 startPos = gameObject.transform.position + Vector3.up;
//Debug.DrawRay(startPos, Vector3.up * maxDistanceToWater, waterRayColor);
RaycastHit hit;
if (Physics.Raycast(startPos, Vector3.up, out hit, maxDistanceToWater, waterLayer))
{
if (hit.collider.tag == "Water")
{
InWater = true;
actualDistanceToWater = hit.distance;
}
else
{
InWater = false;
actualDistanceToWater = 0;
}
}
else
{
InWater = false;
}
if (InWater && CharacterStance != CharacterStance.Swimming && _wasWater == false)
{
CharacterStance = CharacterStance.Swimming;
rigidBody.useGravity = false;
}
else if (!InWater && CharacterStance == CharacterStance.Swimming && _wasWater == true)
{
CharacterStance = CharacterStance.Standing;
rigidBody.useGravity = true;
}
_wasWater = InWater;
}
void CheckIsGrounded()
{
Color groundRayColor = Color.green;
Vector3 startPos = transform.position;
Vector3 dir = transform.position + (Vector3.down * groundCheckDistance);
//Debug.DrawLine(startPos, dir, groundRayColor);
RaycastHit hit;
//Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * groundCheckDistance), Color.green);
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hit, groundCheckDistance, groundLayers))
{
IsGrounded = true;
_actualDistanceToGround = hit.distance;
}
else
{
IsGrounded = false;
_actualDistanceToGround = 0;
}
}
}
}