private void CheckOnGround() { // Assume not grounded, and only ground when raycast hit bool isGroundedFlag = false; float angle = Mathf.Atan2(_heading.x, _heading.z); foreach (Vector3 skinVertex in _groundSkinVertices) { float newXValue = Mathf.Cos(angle) * skinVertex.x - Mathf.Sin(angle) * skinVertex.z; float newZValue = Mathf.Cos(angle) * skinVertex.z + Mathf.Sin(angle) * skinVertex.x; RaycastHit hit; Debug.DrawRay(_boxCollider.bounds.center + new Vector3(newXValue, skinVertex.y, newZValue), Vector3.down, Color.magenta, DistToGround); if (Physics.Raycast(_boxCollider.bounds.center + new Vector3(newXValue, skinVertex.y, newZValue), Vector3.down, out hit, DistToGround + (Mathf.Abs(_rb.velocity.y) * Time.deltaTime * LandingPredictionMultiplier), Layer)) { BlockBehaviour hitBlock = hit.collider.GetComponent <BlockBehaviour>(); if (hitBlock.FireRaycastFromFace(BlockFace.Top)) { continue; } if (!_isGrounded && _animator != null) { _animator.Ground(); if (isGroundedFlag) { LandingSound.Play(); } } if (hit.distance <= DistToGround + (Mathf.Abs(_rb.velocity.y) * Time.deltaTime)) { isGroundedFlag = true; hitBlock.SetIsPlayerStandingOn(true); if (!_blockList.Contains(hitBlock)) { _blockList.Add(hitBlock); } } } } _isGrounded = isGroundedFlag; }