Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
 /// <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;
 }
Esempio n. 3
0
        /// <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;
 }
Esempio n. 5
0
 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();
 }
Esempio n. 6
0
        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));
        }
Esempio n. 7
0
 /// <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));
 }
Esempio n. 8
0
 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);
 }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 10
0
        /// <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);
        }
Esempio n. 13
0
        /// <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;
 }
Esempio n. 16
0
        /// <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();
 }
Esempio n. 18
0
 /// <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();
 }
Esempio n. 19
0
 /// <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 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;
 }