public void UpdateLedgeDetectorState(Vector3 pos) { const float bodyRadius = PlayerConstants.BODY_RADIUS; const float distance = 0.13f; // TODO: Add comments, some of them clever. RaycastHit?ceilingHit = CylinderPhysics.CircleCast( pos, bodyRadius, BIG_NUMBER, Vector3.up ); float ceilingHeight = ceilingHit?.distance ?? BIG_NUMBER; Vector3 echoStart = pos + (Vector3.up * ceilingHeight); RaycastHit?echoHit = CylinderPhysics.CircleCast( echoStart, bodyRadius + distance, BIG_NUMBER, Vector3.down ); LedgePresent = echoHit.HasValue; if (LedgePresent) { DebugDisplay.DrawPoint(Color.green, echoHit.Value.point); LastLedgeHeight = echoHit.Value.point.y - pos.y; } }
public void UpdateWallState(Vector3 pos) { // Do a capsule overlap to see if we're touching a wall var wallHits = CylinderPhysics.OverlapCylinder( pos, PlayerConstants.BODY_RADIUS + WALL_CHECK_DIST, PlayerConstants.BODY_HEIGHT ); IsTouchingWall = wallHits.Any(c => c.transform != this.transform); if (!IsTouchingWall) { return; } // Do some cheaty box-casting to find the normal of the wall we're touching. var lastNormal = FindWallNormal(pos); if (!lastNormal.HasValue) { IsTouchingWall = false; return; } LastWallNormal = lastNormal.Value; }
/// <summary> /// Returns a raycast hit for the ground we're above, /// or null if we're in the air. /// </summary> /// <returns></returns> private RaycastHit?GetGround(Vector3 pos) { return(CylinderPhysics.CircleCast( pos + (Vector3.up * RAYCAST_OFFSET), PlayerConstants.BODY_RADIUS, RAYCAST_DISTANCE, Vector3.down, QueryTriggerInteraction.Ignore )); }
public bool CheckBonkingHead(Vector3 pos) { return(CylinderPhysics.CylinderCast( pos + (Vector3.up * PlayerConstants.BODY_HEIGHT), PlayerConstants.BODY_RADIUS, GROUND_DETECTOR_THICKNESS, Vector3.up, GROUND_DETECTOR_THICKNESS / 2 )); }
public static void VisualizeCylinderCast( Vector3 origin, float radius, float height, Vector3 direction, float maxDistance = Mathf.Infinity ) { Vector3 visualizationSize = Vector3.one * 1; Vector3 start = origin - (visualizationSize / 2); Vector3 end = origin + (visualizationSize / 2); // Create a bunch of voxels. They'll act as "probes". Vector3 voxelSize = Vector3.one * 0.1f; var voxels = new HashSet <GameObject>(); for (float x = start.x; x < end.x; x += voxelSize.x) { for (float y = start.y; y < end.y; y += voxelSize.y) { for (float z = start.z; z < end.z; z += voxelSize.z) { var pos = new Vector3(x, y, z); // Skip the positions that are obviously deep inside float distance = Vector3.Cross(direction, pos - origin).magnitude; if (distance < radius) { continue; } // Either create the voxel, or get one from the pool. GameObject voxel; int i = voxels.Count; if (i < _voxelPool.Count) { voxel = _voxelPool[i]; } else { voxel = GameObject.CreatePrimitive(PrimitiveType.Cube); GameObject.Destroy(voxel.GetComponent <Renderer>()); _voxelPool.Add(voxel); } // Move it to the correct place voxel.transform.position = pos; voxel.transform.localScale = voxelSize; var collider = voxel.GetComponent <BoxCollider>(); collider.isTrigger = true; voxels.Add(voxel); } } } // Destroy all voxels in the pool that aren't being used. while (_voxelPool.Count > voxels.Count) { int i = _voxelPool.Count - 1; GameObject.Destroy(_voxelPool[i]); _voxelPool.RemoveAt(i); } // Do the cylinder cast var hits = CylinderPhysics.CylinderCastAll(origin, radius, height, direction, maxDistance); // Draw a gizmo for every voxel that's in the cylinder cast foreach (var h in hits) { if (!voxels.Contains(h.collider.gameObject)) { continue; } DebugDrawCube(Color.blue, h.collider.gameObject.transform.position, voxelSize); } }