/// sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom private void GroundCheck() { previouslyGrounded = grounded; if (disableGroundCheck) { disableGroundCheck = false; grounded = false; jumping = true; } RaycastHit hitInfo; if (Physics.SphereCast(transform.position, capsule.radius * (1.0f - shellOffset), Vector3.down, out hitInfo, ((capsule.height / 2f) - capsule.radius) + groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore)) { grounded = true; groundContactNormal = hitInfo.normal; // move with moving object Vector3 move = Vector3.zero; foreach (MotionComponent motionComponent in hitInfo.transform.GetComponents <MotionComponent>()) { if (motionComponent.enabled) { move += motionComponent.GetTranslateFixed(); Vector3 relPos = transform.position - motionComponent.transform.position; move += (motionComponent.GetRotateFixed() * relPos) - relPos; } } move.y = 0; if (move != Vector3.zero) { rigidBody.MovePosition(rigidBody.position + move); } // determine footstep sound if (hitInfo.collider.gameObject.tag == "Voxel") { var voxelComponent = hitInfo.collider.GetComponent <VoxelComponent>(); Voxel voxel; int faceI; if (voxelComponent.GetSubstance() != null) { // substances use convex hulls which don't have submeshes // so just use the top face of the voxel voxel = voxelComponent.GetSingleBlock(); faceI = 3; } else { int hitVertexI = TouchListener.GetRaycastHitVertexIndex(hitInfo); voxelComponent.GetVoxelFaceForVertex(hitVertexI, out voxel, out faceI); } footstepSound = voxel.faces[faceI].GetSound(); } else { Renderer hitRender = hitInfo.collider.GetComponent <Renderer>(); if (hitRender != null) { // regular .material has (Instance) suffix footstepSound = ResourcesDirectory.GetMaterialSound(hitRender.sharedMaterial); } else { footstepSound = MaterialSound.GENERIC; } } } else { grounded = false; groundContactNormal = Vector3.up; } if (!previouslyGrounded && grounded && jumping) { jumping = false; } }