/// <summary> /// Constructs a new character controller with the most common configuration options. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="height">Height of the character body while standing.</param> /// <param name="crouchingHeight">Height of the character body while crouching.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="mass">Mass of the character body.</param> public CharacterController(Vector3 position, float height, float crouchingHeight, float radius, float mass) { Body = new Cylinder(position, height, radius, mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur when crouching and such. Body.CollisionInformation.Shape.CollisionMargin = .1f; //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3X3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = 0; SupportFinder = new SupportFinder(this); HorizontalMotionConstraint = new HorizontalMotionConstraint(this); VerticalMotionConstraint = new VerticalMotionConstraint(this); StepManager = new StepManager(this); StanceManager = new StanceManager(this, crouchingHeight); QueryManager = new QueryManager(this); //Enable multithreading for the characters. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new horizontal motion constraint. /// </summary> /// <param name="characterBody">Character body to be governed by this constraint.</param> /// <param name="supportFinder">Helper used to find supports for the character.</param> public HorizontalMotionConstraint(Entity characterBody, SupportFinder supportFinder) { this.characterBody = characterBody; this.supportFinder = supportFinder; CollectInvolvedEntities(); MaximumAccelerationForce = Fix64.MaxValue; }
/// <summary> /// Constructs a stance manager for a character. /// </summary> /// <param name="characterBody">The character's body entity.</param> /// <param name="crouchingHeight">Crouching height of the character.</param> /// <param name="proneHeight">Prone height of the character.</param> /// <param name="queryManager">Provider of queries used by the stance manager to test if it is okay to change stances.</param> /// <param name="supportFinder">Support finder used by the character.</param> public StanceManager(Cylinder characterBody, float crouchingHeight, float proneHeight, QueryManager queryManager, SupportFinder supportFinder) { this.QueryManager = queryManager; this.SupportFinder = supportFinder; this.characterBody = characterBody; standingHeight = characterBody.Height; if (crouchingHeight < standingHeight) this.crouchingHeight = crouchingHeight; else throw new ArgumentException("Crouching height must be less than standing height."); if (proneHeight < crouchingHeight) this.proneHeight = proneHeight; else throw new ArgumentException("Prone height must be less than crouching height."); //We can share the real shape with the query objects. currentQueryObject = new ConvexCollidable<CylinderShape>(characterBody.CollisionInformation.Shape); standingQueryObject = new ConvexCollidable<CylinderShape>(new CylinderShape(StandingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); crouchingQueryObject = new ConvexCollidable<CylinderShape>(new CylinderShape(CrouchingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); proneQueryObject = new ConvexCollidable<CylinderShape>(new CylinderShape(proneHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); //Share the collision rules between the main body and its query objects. That way, the character's queries return valid results. currentQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; standingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; crouchingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; proneQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; }
/// <summary> /// Constructs a new horizontal motion constraint. /// </summary> /// <param name="characterBody">Character body to be governed by this constraint.</param> /// <param name="supportFinder">Helper used to find supports for the character.</param> public HorizontalMotionConstraint(Entity characterBody, SupportFinder supportFinder) { this.characterBody = characterBody; this.supportFinder = supportFinder; CollectInvolvedEntities(); MaximumAccelerationForce = float.MaxValue; }
public override void OnRemovalFromSpace(Space oldSpace) { //Remove any supplements from the space too. oldSpace.Remove(Body); oldSpace.Remove(HorizontalMotionConstraint); oldSpace.Remove(VerticalMotionConstraint); //This character controller requires the standard implementation of Space. oldSpace.BoundingBoxUpdater.Finishing -= ExpandBoundingBox; SupportFinder.ClearSupportData(); Body.AngularVelocity = new Vector3(); Body.LinearVelocity = new Vector3(); }
float upStepMargin = .1f; //There's a little extra space above the maximum step height to start the obstruction and downcast test rays. Helps when a step is very close to the max step height. #endregion Fields #region Constructors /// <summary> /// Constructs a new step manager for a character. /// </summary> /// <param name="characterBody">The character's body.</param> /// <param name="contactCategorizer">Contact categorizer used by the character.</param> /// <param name="supportFinder">Support finder used by the character.</param> /// <param name="queryManager">Query provider to use in checking for obstructions.</param> /// <param name="horizontalMotionConstraint">Horizontal motion constraint used by the character. Source of 3d movement direction.</param> public StepManager(Cylinder characterBody, CharacterContactCategorizer contactCategorizer, SupportFinder supportFinder, QueryManager queryManager, HorizontalMotionConstraint horizontalMotionConstraint) { this.characterBody = characterBody; currentQueryObject = new ConvexCollidable<CylinderShape>(characterBody.CollisionInformation.Shape); ContactCategorizer = contactCategorizer; SupportFinder = supportFinder; QueryManager = queryManager; HorizontalMotionConstraint = horizontalMotionConstraint; //The minimum step height is just barely above where the character would generally find the ground. //This helps avoid excess tests. minimumUpStepHeight = CollisionDetectionSettings.AllowedPenetration * 1.1f;// Math.Max(0, -.01f + character.Body.CollisionInformation.Shape.CollisionMargin * (1 - character.SupportFinder.sinMaximumSlope)); }
/// <summary> /// Constructs a new step manager for a character. /// </summary> /// <param name="characterBody">The character's body.</param> /// <param name="contactCategorizer">Contact categorizer used by the character.</param> /// <param name="supportFinder">Support finder used by the character.</param> /// <param name="queryManager">Query provider to use in checking for obstructions.</param> /// <param name="horizontalMotionConstraint">Horizontal motion constraint used by the character. Source of 3d movement direction.</param> public StepManager(Cylinder characterBody, CharacterContactCategorizer contactCategorizer, SupportFinder supportFinder, QueryManager queryManager, HorizontalMotionConstraint horizontalMotionConstraint) { this.characterBody = characterBody; currentQueryObject = new ConvexCollidable <CylinderShape>(characterBody.CollisionInformation.Shape); ContactCategorizer = contactCategorizer; SupportFinder = supportFinder; QueryManager = queryManager; HorizontalMotionConstraint = horizontalMotionConstraint; //The minimum step height is just barely above where the character would generally find the ground. //This helps avoid excess tests. minimumUpStepHeight = CollisionDetectionSettings.AllowedPenetration * 1.1f;// Math.Max(0, -.01f + character.Body.CollisionInformation.Shape.CollisionMargin * (1 - character.SupportFinder.sinMaximumSlope)); }
bool IsDownStepObstructed(ref QuickList <CharacterContact> sideContacts) { //A contact is considered obstructive if its projected depth is deeper than any existing contact along the existing contacts' normals. for (int i = 0; i < sideContacts.Count; i++) { if (SupportFinder.IsSideContactObstructive(ref sideContacts.Elements[i].Contact)) { return(true); } } return(false); }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="height">Height of the character body while standing.</param> /// <param name="crouchingHeight">Height of the character body while crouching.</param> /// <param name="proneHeight">Height of the character body while prone.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="margin">Radius of 'rounding' applied to the cylindrical body. Higher values make the cylinder's edges more rounded. /// The margin is contained within the cylinder's height and radius, so it must not exceed the radius or height of the cylinder. /// To change the collision margin later, use the CharacterController.CollisionMargin property.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="standingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="crouchingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="proneSpeed">Speed at which the character will try to move while prone with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public CharacterController( Vector3 position = new Vector3(), float height = 1.7f, float crouchingHeight = 1.7f * .7f, float proneHeight = 1.7f * 0.3f, float radius = 0.6f, float margin = 0.1f, float mass = 10f, float maximumTractionSlope = 0.8f, float maximumSupportSlope = 1.3f, float standingSpeed = 8f, float crouchingSpeed = 3f, float proneSpeed = 1.5f, float tractionForce = 1000, float slidingSpeed = 6, float slidingForce = 50, float airSpeed = 1, float airForce = 250, float jumpSpeed = 4.5f, float slidingJumpSpeed = 3, float maximumGlueForce = 5000 ) { if (margin > radius || margin > crouchingHeight || margin > height) { throw new ArgumentException("Margin must not be larger than the character's radius or height."); } Body = new Cylinder(position, height, radius, mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur when crouching and such. Body.CollisionInformation.Shape.CollisionMargin = margin; //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = 0; ContactCategorizer = new CharacterContactCategorizer(maximumTractionSlope, maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = radius * 0.25f; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, maximumGlueForce); StepManager = new StepManager(Body, ContactCategorizer, SupportFinder, QueryManager, HorizontalMotionConstraint); StanceManager = new StanceManager(Body, crouchingHeight, proneHeight, QueryManager, SupportFinder); PairLocker = new CharacterPairLocker(Body); StandingSpeed = standingSpeed; CrouchingSpeed = crouchingSpeed; ProneSpeed = proneSpeed; TractionForce = tractionForce; SlidingSpeed = slidingSpeed; SlidingForce = slidingForce; AirSpeed = airSpeed; AirForce = airForce; JumpSpeed = jumpSpeed; SlidingJumpSpeed = slidingJumpSpeed; //Enable multithreading for the characters. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a stance manager for a character. /// </summary> /// <param name="characterBody">The character's body entity.</param> /// <param name="crouchingHeight">Crouching height of the character.</param> /// <param name="proneHeight">Prone height of the character.</param> /// <param name="queryManager">Provider of queries used by the stance manager to test if it is okay to change stances.</param> /// <param name="supportFinder">Support finder used by the character.</param> public StanceManager(Cylinder characterBody, Fix64 crouchingHeight, Fix64 proneHeight, QueryManager queryManager, SupportFinder supportFinder) { this.QueryManager = queryManager; this.SupportFinder = supportFinder; this.characterBody = characterBody; standingHeight = characterBody.Height; if (crouchingHeight < standingHeight) { this.crouchingHeight = crouchingHeight; } else { throw new ArgumentException("Crouching height must be less than standing height."); } if (proneHeight < crouchingHeight) { this.proneHeight = proneHeight; } else { throw new ArgumentException("Prone height must be less than crouching height."); } //We can share the real shape with the query objects. currentQueryObject = new ConvexCollidable <CylinderShape>(characterBody.CollisionInformation.Shape); standingQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(StandingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); crouchingQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(CrouchingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); proneQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(proneHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); //Share the collision rules between the main body and its query objects. That way, the character's queries return valid results. currentQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; standingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; crouchingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; proneQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="speed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public SphereCharacterController( Vector3 position = new Vector3(), float radius = .85f, float mass = 10f, float maximumTractionSlope = 0.8f, float maximumSupportSlope = 1.3f, float speed = 8f, float tractionForce = 1000, float slidingSpeed = 6, float slidingForce = 50, float airSpeed = 1, float airForce = 250, float jumpSpeed = 4.5f, float slidingJumpSpeed = 3, float maximumGlueForce = 5000) { Body = new Sphere(position, radius, mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur if the shape changes. //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = 0; ContactCategorizer = new CharacterContactCategorizer(maximumTractionSlope, maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = (3f / 17f) * radius; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, maximumGlueForce); PairLocker = new CharacterPairLocker(Body); Speed = speed; TractionForce = tractionForce; SlidingSpeed = slidingSpeed; SlidingForce = slidingForce; AirSpeed = airSpeed; AirForce = airForce; JumpSpeed = jumpSpeed; SlidingJumpSpeed = slidingJumpSpeed; //Enable multithreading for the sphere characters. //See the bottom of the Update method for more information about using multithreading with this character. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="speed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public SphereCharacterController( System.Numerics.Vector3 position = new System.Numerics.Vector3(), float radius = .85f, float mass = 10f, float maximumTractionSlope = 0.8f, float maximumSupportSlope = 1.3f, float speed = 8f, float tractionForce = 1000, float slidingSpeed = 6, float slidingForce = 50, float airSpeed = 1, float airForce = 250, float jumpSpeed = 4.5f, float slidingJumpSpeed = 3, float maximumGlueForce = 5000) { Body = new Sphere(position, radius, mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur if the shape changes. //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = 0; ContactCategorizer = new CharacterContactCategorizer(maximumTractionSlope, maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = (3f / 17f) * radius; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, maximumGlueForce); PairLocker = new CharacterPairLocker(Body); Speed = speed; TractionForce = tractionForce; SlidingSpeed = slidingSpeed; SlidingForce = slidingForce; AirSpeed = airSpeed; AirForce = airForce; JumpSpeed = jumpSpeed; SlidingJumpSpeed = slidingJumpSpeed; //Enable multithreading for the sphere characters. //See the bottom of the Update method for more information about using multithreading with this character. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="height">Height of the character body while standing.</param> /// <param name="crouchingHeight">Height of the character body while crouching.</param> /// <param name="proneHeight">Height of the character body while prone.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="margin">Radius of 'rounding' applied to the cylindrical body. Higher values make the cylinder's edges more rounded. /// The margin is contained within the cylinder's height and radius, so it must not exceed the radius or height of the cylinder. /// To change the collision margin later, use the CharacterController.CollisionMargin property.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="standingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="crouchingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="proneSpeed">Speed at which the character will try to move while prone with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public CharacterController( Vector3 position = new Vector3(), float height = 1.7f, float crouchingHeight = 1.7f * .7f, float proneHeight = 1.7f * 0.3f, float radius = 0.6f, float margin = 0.1f, float mass = 10f, float maximumTractionSlope = 0.8f, float maximumSupportSlope = 1.3f, float standingSpeed = 8f, float crouchingSpeed = 3f, float proneSpeed = 1.5f, float tractionForce = 1000, float slidingSpeed = 6, float slidingForce = 50, float airSpeed = 1, float airForce = 250, float jumpSpeed = 4.5f, float slidingJumpSpeed = 3, float maximumGlueForce = 5000 ) { if (margin > radius || margin > crouchingHeight || margin > height) throw new ArgumentException("Margin must not be larger than the character's radius or height."); Body = new Cylinder(position, height, radius, mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur when crouching and such. Body.CollisionInformation.Shape.CollisionMargin = margin; //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = 0; ContactCategorizer = new CharacterContactCategorizer(maximumTractionSlope, maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = radius * 0.25f; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, maximumGlueForce); StepManager = new StepManager(Body, ContactCategorizer, SupportFinder, QueryManager, HorizontalMotionConstraint); StanceManager = new StanceManager(Body, crouchingHeight, proneHeight, QueryManager, SupportFinder); PairLocker = new CharacterPairLocker(Body); StandingSpeed = standingSpeed; CrouchingSpeed = crouchingSpeed; ProneSpeed = proneSpeed; TractionForce = tractionForce; SlidingSpeed = slidingSpeed; SlidingForce = slidingForce; AirSpeed = airSpeed; AirForce = airForce; JumpSpeed = jumpSpeed; SlidingJumpSpeed = slidingJumpSpeed; //Enable multithreading for the characters. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="speed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public SphereCharacterController( // Fix64 cannot be used for default parameters. As a workaround, make all parameters nullable and assign default values inside the constructor Vector3 position = new Vector3(), Fix64?radius = null, Fix64?mass = null, Fix64?maximumTractionSlope = null, Fix64?maximumSupportSlope = null, Fix64?speed = null, Fix64?tractionForce = null, Fix64?slidingSpeed = null, Fix64?slidingForce = null, Fix64?airSpeed = null, Fix64?airForce = null, Fix64?jumpSpeed = null, Fix64?slidingJumpSpeed = null, Fix64?maximumGlueForce = null) { if (radius == null) { radius = (Fix64).85m; } if (mass == null) { mass = 10; } if (maximumTractionSlope == null) { maximumTractionSlope = (Fix64)0.8m; } if (maximumSupportSlope == null) { maximumSupportSlope = (Fix64)1.3m; } if (speed == null) { speed = 8; } if (tractionForce == null) { tractionForce = 1000; } if (slidingSpeed == null) { slidingSpeed = 6; } if (slidingForce == null) { slidingForce = 50; } if (airSpeed == null) { airSpeed = 1; } if (airForce == null) { airForce = 250; } if (jumpSpeed == 0) { jumpSpeed = (Fix64)4.5m; } if (slidingJumpSpeed == null) { slidingJumpSpeed = 3; } if (maximumGlueForce == null) { maximumGlueForce = 5000; } Body = new Sphere(position, (Fix64)radius, (Fix64)mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur if the shape changes. //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = F64.C0; ContactCategorizer = new CharacterContactCategorizer((Fix64)maximumTractionSlope, (Fix64)maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = (Fix64)(3m / 17m) * (Fix64)radius; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, (Fix64)maximumGlueForce); PairLocker = new CharacterPairLocker(Body); Speed = (Fix64)speed; TractionForce = (Fix64)tractionForce; SlidingSpeed = (Fix64)slidingSpeed; SlidingForce = (Fix64)slidingForce; AirSpeed = (Fix64)airSpeed; AirForce = (Fix64)airForce; JumpSpeed = (Fix64)jumpSpeed; SlidingJumpSpeed = (Fix64)slidingJumpSpeed; //Enable multithreading for the sphere characters. //See the bottom of the Update method for more information about using multithreading with this character. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new vertical motion constraint. /// </summary> /// <param name="characterBody">Character body governed by the constraint.</param> /// <param name="supportFinder">Support finder used by the character.</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public VerticalMotionConstraint(Entity characterBody, SupportFinder supportFinder, float maximumGlueForce = 5000) { this.characterBody = characterBody; this.supportFinder = supportFinder; MaximumGlueForce = maximumGlueForce; }
/// <summary> /// Constructs a new character controller. /// </summary> /// <param name="position">Initial position of the character.</param> /// <param name="height">Height of the character body while standing.</param> /// <param name="crouchingHeight">Height of the character body while crouching.</param> /// <param name="proneHeight">Height of the character body while prone.</param> /// <param name="radius">Radius of the character body.</param> /// <param name="margin">Radius of 'rounding' applied to the cylindrical body. Higher values make the cylinder's edges more rounded. /// The margin is contained within the cylinder's height and radius, so it must not exceed the radius or height of the cylinder. /// To change the collision margin later, use the CharacterController.CollisionMargin property.</param> /// <param name="mass">Mass of the character body.</param> /// <param name="maximumTractionSlope">Steepest slope, in radians, that the character can maintain traction on.</param> /// <param name="maximumSupportSlope">Steepest slope, in radians, that the character can consider a support.</param> /// <param name="standingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="crouchingSpeed">Speed at which the character will try to move while crouching with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="proneSpeed">Speed at which the character will try to move while prone with a support that provides traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="tractionForce">Maximum force that the character can apply while on a support which provides traction.</param> /// <param name="slidingSpeed">Speed at which the character will try to move while on a support that does not provide traction. /// Relative velocities with a greater magnitude will be decelerated.</param> /// <param name="slidingForce">Maximum force that the character can apply while on a support which does not provide traction</param> /// <param name="airSpeed">Speed at which the character will try to move with no support. /// The character will not be decelerated while airborne.</param> /// <param name="airForce">Maximum force that the character can apply with no support.</param> /// <param name="jumpSpeed">Speed at which the character leaves the ground when it jumps</param> /// <param name="slidingJumpSpeed">Speed at which the character leaves the ground when it jumps without traction</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public CharacterController( // Fix64 cannot be used for default parameters. As a workaround, make all parameters nullable and assign default values inside the constructor Vector3 position = new Vector3(), Fix64?height = null, Fix64?crouchingHeight = null, Fix64?proneHeight = null, Fix64?radius = null, Fix64?margin = null, Fix64?mass = null, Fix64?maximumTractionSlope = null, Fix64?maximumSupportSlope = null, Fix64?standingSpeed = null, Fix64?crouchingSpeed = null, Fix64?proneSpeed = null, Fix64?tractionForce = null, Fix64?slidingSpeed = null, Fix64?slidingForce = null, Fix64?airSpeed = null, Fix64?airForce = null, Fix64?jumpSpeed = null, Fix64?slidingJumpSpeed = null, Fix64?maximumGlueForce = null ) { if (height == null) { height = (Fix64)1.7m; } if (crouchingHeight == null) { crouchingHeight = (Fix64)(1.7m * .7m); } if (proneHeight == null) { proneHeight = (Fix64)(1.7m * 0.3m); } if (radius == null) { radius = (Fix64)0.6m; } if (margin == null) { margin = (Fix64)0.1m; } if (mass == null) { mass = 10; } if (maximumTractionSlope == null) { maximumTractionSlope = (Fix64)0.8m; } if (maximumSupportSlope == null) { maximumSupportSlope = (Fix64)1.3m; } if (standingSpeed == null) { standingSpeed = 8; } if (crouchingSpeed == null) { crouchingSpeed = 3; } if (proneSpeed == null) { proneSpeed = (Fix64)1.5m; } if (tractionForce == null) { tractionForce = 1000; } if (slidingSpeed == null) { slidingSpeed = 6; } if (slidingForce == null) { slidingForce = 50; } if (airSpeed == null) { airSpeed = 1; } if (airForce == null) { airForce = 250; } if (jumpSpeed == null) { jumpSpeed = (Fix64)4.5m; } if (slidingJumpSpeed == null) { slidingJumpSpeed = 3; } if (maximumGlueForce == null) { maximumGlueForce = 5000; } if (margin > radius || margin > crouchingHeight || margin > height) { throw new ArgumentException("Margin must not be larger than the character's radius or height."); } Body = new Cylinder(position, (Fix64)height, (Fix64)radius, (Fix64)mass); Body.IgnoreShapeChanges = true; //Wouldn't want inertia tensor recomputations to occur when crouching and such. Body.CollisionInformation.Shape.CollisionMargin = (Fix64)margin; //Making the character a continuous object prevents it from flying through walls which would be pretty jarring from a player's perspective. Body.PositionUpdateMode = PositionUpdateMode.Continuous; Body.LocalInertiaTensorInverse = new Matrix3x3(); //TODO: In v0.16.2, compound bodies would override the material properties that get set in the CreatingPair event handler. //In a future version where this is changed, change this to conceptually minimally required CreatingPair. Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction; Body.LinearDamping = F64.C0; ContactCategorizer = new CharacterContactCategorizer((Fix64)maximumTractionSlope, (Fix64)maximumSupportSlope); QueryManager = new QueryManager(Body, ContactCategorizer); SupportFinder = new SupportFinder(Body, QueryManager, ContactCategorizer); HorizontalMotionConstraint = new HorizontalMotionConstraint(Body, SupportFinder); HorizontalMotionConstraint.PositionAnchorDistanceThreshold = (Fix64)radius * F64.C0p25; VerticalMotionConstraint = new VerticalMotionConstraint(Body, SupportFinder, (Fix64)maximumGlueForce); StepManager = new StepManager(Body, ContactCategorizer, SupportFinder, QueryManager, HorizontalMotionConstraint); StanceManager = new StanceManager(Body, (Fix64)crouchingHeight, (Fix64)proneHeight, QueryManager, SupportFinder); PairLocker = new CharacterPairLocker(Body); StandingSpeed = (Fix64)standingSpeed; CrouchingSpeed = (Fix64)crouchingSpeed; ProneSpeed = (Fix64)proneSpeed; TractionForce = (Fix64)tractionForce; SlidingSpeed = (Fix64)slidingSpeed; SlidingForce = (Fix64)slidingForce; AirSpeed = (Fix64)airSpeed; AirForce = (Fix64)airForce; JumpSpeed = (Fix64)jumpSpeed; SlidingJumpSpeed = (Fix64)slidingJumpSpeed; //Enable multithreading for the characters. IsUpdatedSequentially = false; //Link the character body to the character controller so that it can be identified by the locker. //Any object which replaces this must implement the ICharacterTag for locking to work properly. Body.CollisionInformation.Tag = new CharacterSynchronizer(Body); }
/// <summary> /// Constructs a new horizontal motion constraint. /// </summary> /// <param name="characterBody">Character body to be governed by this constraint.</param> /// <param name="supportFinder">Helper used to find supports for the character.</param> public HorizontalMotionConstraint(Entity characterBody, SupportFinder supportFinder) { this.characterBody = characterBody; this.supportFinder = supportFinder; CollectInvolvedEntities(); }
/// <summary> /// Constructs a new vertical motion constraint. /// </summary> /// <param name="characterBody">Character body governed by the constraint.</param> /// <param name="supportFinder">Support finder used by the character.</param> /// <param name="maximumGlueForce">Maximum force the vertical motion constraint is allowed to apply in an attempt to keep the character on the ground.</param> public VerticalMotionConstraint(Entity characterBody, SupportFinder supportFinder) { this.characterBody = characterBody; this.supportFinder = supportFinder; MaximumGlueForce = (Fix64)5000; }