Exemple #1
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }
            if (movementData[LoopUntilInterruptedIndex] == null)
            {
                movementData[LoopUntilInterruptedIndex] = new MovementVariable();
            }
            movementData[LoopUntilInterruptedIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Loop Forever", "If true animation will loop and maintain control until the StopAnimation() function is called."), movementData[LoopUntilInterruptedIndex].BoolValue);

            if (movementData[ShouldApplyGravityIndex] == null)
            {
                movementData[ShouldApplyGravityIndex] = new MovementVariable();
            }
            movementData[ShouldApplyGravityIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Should Apply Gravity", "If true gravity will be applied during the animation."), movementData[ShouldApplyGravityIndex].BoolValue);

            if (movementData[FallAnimationStateIndex] == null)
            {
                movementData[FallAnimationStateIndex] = new MovementVariable((int)AnimationState.FALL);
            }
            if (movementData [ShouldApplyGravityIndex].BoolValue)
            {
                movementData [FallAnimationStateIndex].IntValue = (int)(AnimationState)EditorGUILayout.EnumPopup(new GUIContent("Fall Animation State", "If gravity is enabled this is the animation state to send while falling "), (AnimationState)movementData [FallAnimationStateIndex].IntValue);
            }
            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air acceleration
            if (movementData[AirSpeedAccelerationIndex] == null)
            {
                movementData[AirSpeedAccelerationIndex] = new MovementVariable(DefaultAirSpeedAcceleration);
            }
            movementData[AirSpeedAccelerationIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed Acceleration(x)", "Rate at which the character moves to the desired air speed."), movementData[AirSpeedAccelerationIndex].FloatValue);
            if (movementData[AirSpeedAccelerationIndex].FloatValue < 0)
            {
                movementData[AirSpeedAccelerationIndex].FloatValue = 0.0f;
            }

            // Run speed
            if (movementData[AirSpeedRunIndex] == null)
            {
                movementData[AirSpeedRunIndex] = new MovementVariable(DefaultAirSpeedRun);
            }
            movementData[AirSpeedRunIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed Run(x)", "How fast the character moves in the X direction whle in the air when run is depressed."), movementData[AirSpeedRunIndex].FloatValue);
            if (movementData[AirSpeedRunIndex].FloatValue < 0)
            {
                movementData[AirSpeedRunIndex].FloatValue = 0.0f;
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = AirMovement_Variable.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            return(movementData);
        }
Exemple #3
0
        /// <summary>
        /// Draws an inspector with the standard jump details settings.
        /// </summary>
        /// <param name="movementData">Movement data.</param>
        /// <param name="jumpGravityIndex">Jump gravity index.</param>
        /// <param name="groundedLeewayIndex">Grounded leeway index.</param>
        /// <param name="jumpWhenButtonHeldIndex">Jump when button held index.</param>
        public static MovementVariable[] DrawStandardJumpDetails(MovementVariable[] movementData, int jumpRelativeGravityIndex, int groundedLeewayIndex, int jumpWhenButtonHeldIndex)
        {
            // Relative jump gravity
            if (movementData[jumpRelativeGravityIndex] == null || movementData[jumpRelativeGravityIndex].FloatValue <0.01f || movementData[jumpRelativeGravityIndex].FloatValue> 2.0f)
            {
                movementData[jumpRelativeGravityIndex] = new MovementVariable(1.0f);
            }
            movementData[jumpRelativeGravityIndex].FloatValue = EditorGUILayout.Slider(new GUIContent("Jump Gravity", "Set a value lower than 1 to make the jump floatier as seen in games like Super Mario Bros."), movementData[jumpRelativeGravityIndex].FloatValue, 0.01f, 2.0f);

            // Grounded Leeway
            if (movementData[groundedLeewayIndex] == null)
            {
                movementData[groundedLeewayIndex] = new MovementVariable(0.1f);
            }
            movementData[groundedLeewayIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Grounded Leeway", "After the character leaves the ground it will still be able to jump if you press jump within this timeframe."), movementData[groundedLeewayIndex].FloatValue);

            // Jump When Button Held Index
            if (movementData[jumpWhenButtonHeldIndex] == null)
            {
                movementData[jumpWhenButtonHeldIndex] = new MovementVariable();
            }
            movementData[jumpWhenButtonHeldIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Jump When Button Held", "Does holding the jump button jump automatically or does the user need to press it each time."), movementData[jumpWhenButtonHeldIndex].BoolValue);

            return(movementData);
        }
Exemple #4
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Halt movement
            if (movementData[HaltMovementIndex] == null)
            {
                movementData[HaltMovementIndex] = new MovementVariable();
            }
            movementData[HaltMovementIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Halt Movement", "If true the movement will not allow user to run off an edge. If false balanace animation will only show if velocity = 0"), movementData[HaltMovementIndex].BoolValue);

            // Number of Colliders
            if (movementData[NumberOfCollidersIndex] == null)
            {
                movementData[NumberOfCollidersIndex] = new MovementVariable(DefaultColliders);
            }
            movementData[NumberOfCollidersIndex].IntValue = EditorGUILayout.IntField(new GUIContent("Number of Colliders", "The number of colliders that should be hitting the ground in order for balance to be played."), movementData[NumberOfCollidersIndex].IntValue);
            if (movementData [NumberOfCollidersIndex].IntValue < 1)
            {
                movementData [NumberOfCollidersIndex].IntValue = 1;
            }
            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Roll speed
            if (movementData[LandTimeIndex] == null)
            {
                movementData[LandTimeIndex] = new MovementVariable(0);
            }
            movementData[LandTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Land Time", "How long we play landing animation for."), movementData[LandTimeIndex].FloatValue);
            if (movementData[LandTimeIndex].FloatValue < 0)
            {
                movementData[LandTimeIndex].FloatValue = 0.0f;
            }

            // Y velocity for roll
            if (movementData[AllowWalkIndex] == null)
            {
                movementData[AllowWalkIndex] = new MovementVariable();
            }
            movementData[AllowWalkIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Allow Walk", "If true character can still move using default ground movement while landing animation is played."), movementData[AllowWalkIndex].BoolValue);

            return(movementData);
        }
Exemple #6
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_Digital.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            // Friction
            if (movementData[FrictionIndex] == null)
            {
                movementData[FrictionIndex] = new MovementVariable(DefaultFriction);
            }
            movementData[FrictionIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Friction", "Controls how quickly the character comes to a stop."), movementData[FrictionIndex].FloatValue);

            // Quiesce Speed
            if (movementData[QuiesceSpeedIndex] == null)
            {
                movementData[QuiesceSpeedIndex] = new MovementVariable(DefaultQuiesceSpeed);
            }
            movementData[QuiesceSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Quiesce Speed", "Speed at which slide turns to stop."), movementData[QuiesceSpeedIndex].FloatValue);
            if (movementData[QuiesceSpeedIndex].FloatValue < 0)
            {
                movementData[QuiesceSpeedIndex].FloatValue = 0.0f;
            }


            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Animation Length
            if (movementData[AnimationLengthIndex] == null)
            {
                movementData[AnimationLengthIndex] = new MovementVariable();
            }
            movementData[AnimationLengthIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Animation Length", "How long to play the damage animation for."), movementData[AnimationLengthIndex].FloatValue);
            if (movementData[AnimationLengthIndex].FloatValue < 0)
            {
                movementData[AnimationLengthIndex].FloatValue = 0.0f;
            }

            // Apply Gravity Length
            if (movementData[ApplyGravityIndex] == null)
            {
                movementData[ApplyGravityIndex] = new MovementVariable();
            }
            movementData[ApplyGravityIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Apply Gravity", "Should we still apply gravity and base collisions while the animatino plays?"), movementData[ApplyGravityIndex].BoolValue);

            return(movementData);
        }
Exemple #8
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_Physics.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            if (showDetails)
            {
                // Loop Speed
                if (movementData[LoopSpeedIndex] == null)
                {
                    movementData[LoopSpeedIndex] = new MovementVariable(DefaultLoopSpeed);
                }
                movementData[LoopSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Loop Speed", "Speed required to be able to run the loop."), movementData[LoopSpeedIndex].FloatValue);
                if (movementData[LoopSpeedIndex].FloatValue < 0)
                {
                    movementData[LoopSpeedIndex].FloatValue = 0;
                }

                // Slide Time
                if (movementData[SlideTimeIndex] == null)
                {
                    movementData[SlideTimeIndex] = new MovementVariable(DefaultSlideTime);
                }
                movementData[SlideTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("SlideTime", "How long will the character slide down a slope if they get to 90 degrees without required speed."), movementData[SlideTimeIndex].FloatValue);
                if (movementData[SlideTimeIndex].FloatValue < 0)
                {
                    movementData[SlideTimeIndex].FloatValue = 0;
                }
            }

            // Not rotate warning
            if (!target.rotateToSlopes)
            {
                EditorGUILayout.HelpBox("A character with a Loop movement must use rotate to slopes.", MessageType.Error);
            }
            else if (target.maxSlopeRotation < 90)
            {
                EditorGUILayout.HelpBox("If your character cannot rotate to an angle of 90 degrees you don't need a Loop movement.", MessageType.Warning);
            }
            if (!target.rotateToSlopes || target.maxSlopeRotation < 90)
            {
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Fix Now"))
                {
                    target.rotateToSlopes   = true;
                    target.maxSlopeRotation = 180;
                }
                GUILayout.EndHorizontal();
            }


            return(movementData);
        }
Exemple #9
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Walk speed
            if (movementData[SpeedIndex] == null)
            {
                movementData[SpeedIndex] = new MovementVariable();
            }
            movementData[SpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Speed", "How fast the character walks."), movementData[SpeedIndex].FloatValue);
            if (movementData[SpeedIndex].FloatValue < 0)
            {
                movementData[SpeedIndex].FloatValue = 0.0f;
            }

            // Must Release Keys After Aiming
            if (movementData[MustReleaseKeysAfterAimingIndex] == null)
            {
                movementData[MustReleaseKeysAfterAimingIndex] = new MovementVariable(true);
            }
            movementData[MustReleaseKeysAfterAimingIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Must Release After Aiming", "If the user starts aiming with up and down and this is true the user must let go of the arrows/d-pad in order to start running again."), movementData[MustReleaseKeysAfterAimingIndex].BoolValue);

            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Walk speed
            if (movementData[SpeedIndex] == null)
            {
                movementData[SpeedIndex] = new MovementVariable();
            }
            movementData[SpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Speed", "How fast the character walks."), movementData[SpeedIndex].FloatValue);
            if (movementData[SpeedIndex].FloatValue < 0)
            {
                movementData[SpeedIndex].FloatValue = 0.0f;
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_Crouch.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);


            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air speed
            if (movementData[AirSpeedIndex] == null)
            {
                movementData[AirSpeedIndex] = new MovementVariable(DefaultAirSpeed);
            }
            movementData[AirSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed (x)", "How fast the character moves in the X direction whle in the air."), movementData[AirSpeedIndex].FloatValue);
            if (movementData[AirSpeedIndex].FloatValue < 0)
            {
                movementData[AirSpeedIndex].FloatValue = 0.0f;
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");
            if (showDetails)
            {
                movementData = AirMovement.DrawStandardJumpDetails(movementData, JumpRelativeGravityIndex, GroundedLeewayIndex, JumpWhenButtonHeldIndex);
            }

            return(movementData);
        }
Exemple #12
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air speed
            if (movementData[JumpDelayIndex] == null)
            {
                movementData[JumpDelayIndex] = new MovementVariable(0);
            }
            movementData[JumpDelayIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Jump Delay", "How long to wait before jumping."), movementData[JumpDelayIndex].FloatValue);
            if (movementData[JumpDelayIndex].FloatValue < 0)
            {
                movementData[JumpDelayIndex].FloatValue = 0.0f;
            }

            // Animation
            if (movementData[JumpAnimationOnlyIndex] == null)
            {
                movementData[JumpAnimationOnlyIndex] = new MovementVariable();
            }
            movementData[JumpAnimationOnlyIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Jump Animation Only", "Should we always set JUMP as the animation state or should we set the underlying animation state from the default air movement."), movementData[JumpAnimationOnlyIndex].BoolValue);

            return(movementData);
        }
 /// <summary>
 /// Draws the inspector.
 /// </summary>
 public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
 {
     if (movementData == null || movementData.Length < MovementVariableCount)
     {
         movementData = new MovementVariable[MovementVariableCount];
     }
     return(movementData);
 }
Exemple #14
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Max Speed
            if (movementData[MaxSpeedIndex] == null)
            {
                movementData[MaxSpeedIndex] = new MovementVariable();
            }
            movementData[MaxSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Maximum Speed", "The characters peak speed."), movementData[MaxSpeedIndex].FloatValue);
            if (movementData[MaxSpeedIndex].FloatValue < 0)
            {
                movementData[MaxSpeedIndex].FloatValue = 0.0f;
            }

            // Walk Speed
            if (movementData[WalkSpeedIndex] == null)
            {
                movementData[WalkSpeedIndex] = new MovementVariable();
            }
            movementData[WalkSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Walk Speed", "The characters walk speed."), movementData[WalkSpeedIndex].FloatValue);
            if (movementData[WalkSpeedIndex].FloatValue < 0)
            {
                movementData[WalkSpeedIndex].FloatValue = 0.0f;
            }

            // Acceleration
            if (movementData[AccelerationIndex] == null)
            {
                movementData[AccelerationIndex] = new MovementVariable();
            }
            movementData[AccelerationIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Acceleration", "How fast the character accelerates."), movementData[AccelerationIndex].FloatValue);
            if (movementData[AccelerationIndex].FloatValue < 0)
            {
                movementData[AccelerationIndex].FloatValue = 0.0f;
            }

            // Stick to ground
            if (movementData[StickToGroundIndex] == null)
            {
                movementData[StickToGroundIndex] = new MovementVariable(false);
            }
            movementData[StickToGroundIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Stick to Ground", "Should the character stick to the ground when running on slopes?"), movementData[StickToGroundIndex].BoolValue);

            // Stick to ground warning
            if (!target.rotateToSlopes && !movementData[StickToGroundIndex].BoolValue)
            {
                EditorGUILayout.HelpBox("If your Character doesn't rotate to slopes you may want to enable stick to ground. If these settings are both off your cahracter will be able to 'run' off the slope.", MessageType.Info);
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Advanced Settings");
            DrawStandardPhysicsSettings(movementData, 0, showDetails);

            return(movementData);
        }
Exemple #15
0
 /// <summary>
 /// Clone constructor. Initializes a new instance of the <see cref="PlatformerPro.MovementVariable"/> class.
 /// </summary>
 /// <param name="originalVariable">Variable to clone values from.</param>
 public SavableMovementVariable(MovementVariable originalVariable)
 {
     this.floatValue      = originalVariable.FloatValue;
     this.intValue        = originalVariable.IntValue;
     this.stringValue     = originalVariable.StringValue;
     this.boolValue       = originalVariable.BoolValue;
     this.vector2Value    = originalVariable.Vector2Value;
     this.gameObjectValue = originalVariable.GameObjectValue;
 }
 /// <summary>
 /// Draws the inspector.
 /// </summary>
 public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
 {
     if (movementData == null || movementData.Length != 0)
     {
         movementData = new MovementVariable[0];
     }
     EditorGUILayout.HelpBox("Movement settings are controlled by the Rail Platform", MessageType.Info);
     return(movementData);
 }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }
            else if (movementData.Length == MovementVariableCount - 1)
            {
                Debug.Log("Upgading movement data for passdown.");
                MovementVariable[] tmpMovementData = movementData;
                movementData = new MovementVariable[MovementVariableCount];
                System.Array.Copy(tmpMovementData, movementData, MovementVariableCount - 1);
            }
            else if (movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Require Jump
            if (movementData[RequireJumpIndex] == null)
            {
                movementData[RequireJumpIndex] = new MovementVariable();
            }
            movementData[RequireJumpIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Use Jump Button", "If false, pressing downwards will passthrough, if true you need to press both down and jump."), movementData[RequireJumpIndex].BoolValue);

            // Bobble Height
            if (movementData[BobbleHeightIndex] == null)
            {
                movementData[BobbleHeightIndex] = new MovementVariable(0);
            }
            movementData[BobbleHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Bobble Height", "How high should the character bobble before moving downwards."), movementData[BobbleHeightIndex].FloatValue);
            if (movementData[BobbleHeightIndex].FloatValue < 0)
            {
                movementData[BobbleHeightIndex].FloatValue = 0.0f;
            }

            // Clearance Timer
            if (movementData[ClearanceTimeIndex] == null)
            {
                movementData[ClearanceTimeIndex] = new MovementVariable(DefaultClearanceTime);
            }
            movementData[ClearanceTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Clearance Time", "How long should this movement maintain control before giving it back to the normal air movement."), movementData[ClearanceTimeIndex].FloatValue);
            if (movementData[ClearanceTimeIndex].FloatValue < 0)
            {
                movementData[ClearanceTimeIndex].FloatValue = 0.0f;
            }

            // Support Tiles Jump
            if (movementData[SupportTilesIndex] == null)
            {
                movementData[SupportTilesIndex] = new MovementVariable();
            }
            movementData[SupportTilesIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Support Tiles", "If true all feet colliders will be ignored, if false only the middle ground collider."), movementData[SupportTilesIndex].BoolValue);

            return(movementData);
        }
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Damage amount
            if (movementData[DamageAmountIndex] == null)
            {
                movementData[DamageAmountIndex] = new MovementVariable(1);
            }
            movementData[DamageAmountIndex].IntValue = EditorGUILayout.IntField(new GUIContent("Damage Amount", "How much damage jumping on head does."), movementData[DamageAmountIndex].IntValue);
            if (movementData [DamageAmountIndex].IntValue < 0)
            {
                movementData [DamageAmountIndex].IntValue = 0;
            }


            // Bobble Height
            if (movementData[BobbleHeightIndex] == null)
            {
                movementData[BobbleHeightIndex] = new MovementVariable(1.0f);
            }
            movementData[BobbleHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Bobble Height", "How high to bobble (bounce)."), movementData[BobbleHeightIndex].FloatValue);
            if (movementData [BobbleHeightIndex].FloatValue < 0)
            {
                movementData [BobbleHeightIndex].FloatValue = 0;
            }


            // Kick Hiding Enemies
            if (movementData[KickHidingEnemiesIndex] == null)
            {
                movementData[KickHidingEnemiesIndex] = new MovementVariable();
            }
            movementData[KickHidingEnemiesIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Kick Hiding Enemies", "If true enemies in the HIDING state will be 'kicked' even if the character isn't jumping."), movementData[KickHidingEnemiesIndex].BoolValue);

            // Layer Mask
            if (movementData[EnemyLayermaskIndex] == null)
            {
                movementData[EnemyLayermaskIndex] = new MovementVariable();
            }
            movementData[EnemyLayermaskIndex].IntValue = EditorGUILayout.LayerField(new GUIContent("Enemy Layer Mask", "Layers to check for enemies, these layers MUST also be in the character layer mask."), movementData[EnemyLayermaskIndex].IntValue);

            // Check for correct layer
            if (target != null)
            {
                if (((1 << movementData[EnemyLayermaskIndex].IntValue) & target.layerMask) != (1 << movementData[EnemyLayermaskIndex].IntValue))
                {
                    EditorGUILayout.HelpBox("Enemy layer MUST be in the overall layer mask. Update the character.", MessageType.Error);
                }
            }

            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air speed
            if (movementData[AirSpeedIndex] == null)
            {
                movementData[AirSpeedIndex] = new MovementVariable(DefaultAirSpeed);
            }
            movementData[AirSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed (x)", "How fast the character moves in the X direction whle in the air."), movementData[AirSpeedIndex].FloatValue);
            if (movementData[AirSpeedIndex].FloatValue < 0)
            {
                movementData[AirSpeedIndex].FloatValue = 0.0f;
            }

            // Jump height
            if (movementData[JumpHeightIndex] == null)
            {
                movementData[JumpHeightIndex] = new MovementVariable(DefaultJumpHeight);
            }
            movementData[JumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Jump Height", "How high the character jumps"), movementData[JumpHeightIndex].FloatValue);
            if (movementData[JumpHeightIndex].FloatValue < 0)
            {
                movementData[JumpHeightIndex].FloatValue = 0.0f;
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");

            // Make sure we set defaults regardless of showDetails
            if (movementData[JumpRelativeGravityIndex] == null || movementData[JumpRelativeGravityIndex].FloatValue <0.01f || movementData[JumpRelativeGravityIndex].FloatValue> 2.0f)
            {
                movementData[JumpRelativeGravityIndex] = new MovementVariable(DefaultRelativeJumpGravity);
            }
            if (movementData[GroundedLeewayIndex] == null)
            {
                movementData[GroundedLeewayIndex] = new MovementVariable(DefaultGroundedLeeway);
            }
            if (movementData[JumpWhenButtonHeldIndex] == null)
            {
                movementData[JumpWhenButtonHeldIndex] = new MovementVariable();
            }



            if (showDetails)
            {
                movementData = AirMovement.DrawStandardJumpDetails(movementData, JumpRelativeGravityIndex, GroundedLeewayIndex, JumpWhenButtonHeldIndex);
            }

            return(movementData);
        }
Exemple #20
0
 /// <summary>
 /// Clone constructor. Initializes a new instance of the <see cref="PlatformerPro.MovementVariable"/> class.
 /// </summary>
 /// <param name="originalVariable">Variable to clone values from.</param>
 public MovementVariable(MovementVariable originalVariable)
 {
     if (originalVariable != null)
     {
         this.floatValue      = originalVariable.floatValue;
         this.intValue        = originalVariable.intValue;
         this.stringValue     = originalVariable.stringValue;
         this.boolValue       = originalVariable.boolValue;
         this.vector2Value    = originalVariable.vector2Value;
         this.gameObjectValue = originalVariable.gameObjectValue;
     }
 }
Exemple #21
0
        public MovementVariable Convert()
        {
            MovementVariable result = new MovementVariable();

            result.FloatValue      = this.floatValue;
            result.IntValue        = this.intValue;
            result.StringValue     = this.stringValue;
            result.BoolValue       = this.boolValue;
            result.Vector2Value    = this.vector2Value;
            result.GameObjectValue = this.gameObjectValue;
            return(result);
        }
Exemple #22
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Max Air speed
            if (movementData[MaxAirSpeedIndex] == null)
            {
                movementData[MaxAirSpeedIndex] = new MovementVariable(DefaultMaxAirSpeed);
            }
            movementData[MaxAirSpeedIndex].Vector2Value = EditorGUILayout.Vector2Field(new GUIContent("Max Air Speed", "How fast the character can move in the air (x and y)."), movementData[MaxAirSpeedIndex].Vector2Value);

            // Acceleration
            if (movementData[AirAccelerationIndex] == null)
            {
                movementData[AirAccelerationIndex] = new MovementVariable(DefaultAirAcceleration);
            }
            movementData[AirAccelerationIndex].Vector2Value = EditorGUILayout.Vector2Field(new GUIContent("Acceleration", "How fast the character accelerates (x and y)."), movementData[AirAccelerationIndex].Vector2Value);

            // DragAir
            if (movementData[AirDragIndex] == null)
            {
                movementData[AirDragIndex] = new MovementVariable(DefaultAirDrag);
            }
            movementData[AirDragIndex].Vector2Value = EditorGUILayout.Vector2Field(new GUIContent("Drag", "Controls how fast the cahracter slows down (x and y)."), movementData[AirDragIndex].Vector2Value);

            // Item
            if (movementData[ItemIndex] == null)
            {
                movementData[ItemIndex] = new MovementVariable();
            }
            movementData[ItemIndex].StringValue = EditorGUILayout.TextField(new GUIContent("Item", "If not-empty the character requires the given item in order to be able to fly."), movementData[ItemIndex].StringValue);

            // Item consumption
            if (movementData[ItemConsumptionRateIndex] == null)
            {
                movementData[ItemConsumptionRateIndex] = new MovementVariable(0);
            }
            if (movementData[ItemIndex].StringValue != null && movementData[ItemIndex].StringValue != "")
            {
                // Item consumption rate
                movementData[ItemConsumptionRateIndex].IntValue = EditorGUILayout.IntField(new GUIContent("Consumption Rate", "If non zero the item will be treated like fuel or energy, and consumed at this rate per second."), movementData[ItemConsumptionRateIndex].IntValue);
                if (movementData[ItemConsumptionRateIndex].IntValue < 0)
                {
                    movementData[ItemConsumptionRateIndex].IntValue = 0;
                }
            }

            return(movementData);
        }
        /// <summary>
        /// Draws the standard physics settings (used by many movements).
        /// </summary>
        /// <param name="movementData">Movement data.</param>
        /// <param name="movementDataIndexOffset">Movement data index offset. Because different movements might place this in different places
        /// in the movement data array we need to offset the array position.</param>
        public static void DrawStandardPhysicsSettings(MovementVariable[] movementData, int movementDataIndexOffset, bool showDetails)
        {
            // Reset values if null
            if (movementData[FrictionIndex + movementDataIndexOffset] == null)
            {
                movementData[FrictionIndex + movementDataIndexOffset] = new MovementVariable(DefaultFriction);
            }
            if (movementData[SlopeAccelerationIndex + movementDataIndexOffset] == null)
            {
                movementData[SlopeAccelerationIndex + movementDataIndexOffset] = new MovementVariable(DefaultSlopeAcceleration);
            }
            if (movementData[QuiesceSpeedIndex + movementDataIndexOffset] == null)
            {
                movementData[QuiesceSpeedIndex + movementDataIndexOffset] = new MovementVariable(DefaultQuiesceSpeed);
            }
            if (movementData[IgnoreForceIndex + movementDataIndexOffset] == null)
            {
                movementData[IgnoreForceIndex + movementDataIndexOffset] = new MovementVariable(DefaultIgnoreForce);
            }

            // Do we need to draw, if so draw.
            if (showDetails)
            {
                GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
                GUILayout.Label("Physics Settings", EditorStyles.boldLabel);

                // Friction
                movementData[FrictionIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("FrictionCoefficient", "Default coefficient of friction. Platforms can override this."), movementData[FrictionIndex + movementDataIndexOffset].FloatValue);
                if (movementData[FrictionIndex + movementDataIndexOffset].FloatValue < 0)
                {
                    movementData[FrictionIndex].FloatValue = 0.0f;
                }

                // Slope Acceleration
                movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.Slider(new GUIContent("Slope Acceleration", "If the character is standing on a slope should they start to slide down it?"), movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue, 0, 2);

                // Quiesce
                movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("QuiesceSpeed", "At what velocity should we sleep if no acceleration is applied?"), movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue);

                // Ignore Force
                movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("Max Ignored Force", "Forces smaller than this will be ignored. Use this to ignore slight slopes or very small input values."), movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue);

                // Reset button
                if (GUILayout.Button(new GUIContent("Reset Physics To Defaults", "Resets all physics settings to default values.")))
                {
                    movementData[FrictionIndex + movementDataIndexOffset].FloatValue          = DefaultFriction;
                    movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue = DefaultSlopeAcceleration;
                    movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue      = DefaultQuiesceSpeed;
                    movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue       = DefaultIgnoreForce;
                }
            }
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Min Speed for Damage
            if (movementData[MinSpeedForDamageIndex] == null)
            {
                movementData[MinSpeedForDamageIndex] = new MovementVariable(MinSpeedForLand);
            }
            movementData[MinSpeedForDamageIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Min Speed for Damage", "How fast character has to be falling before damage occurs."), movementData[MinSpeedForDamageIndex].FloatValue);
            if (movementData [MinSpeedForDamageIndex].FloatValue > MinSpeedForLand)
            {
                movementData [MinSpeedForDamageIndex].FloatValue = MinSpeedForLand;
            }

            // Y velocity for roll
            if (movementData[ConstantDamageIndex] == null)
            {
                movementData[ConstantDamageIndex] = new MovementVariable(true);
            }
            movementData[ConstantDamageIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Constant Damage", "If true fixed damage amount will be used. If false we multiple speed by damage."), movementData[ConstantDamageIndex].BoolValue);

            // Min Speed for Damage
            if (movementData[DamageAmountIndex] == null)
            {
                movementData[DamageAmountIndex] = new MovementVariable(1);
            }
            if (movementData [ConstantDamageIndex].BoolValue)
            {
                movementData[DamageAmountIndex].FloatValue = (float)EditorGUILayout.IntField(new GUIContent("Damage Amount", "Amount of damage."), (int)(movementData[DamageAmountIndex].FloatValue + 0.499f));
            }
            else
            {
                movementData[DamageAmountIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Damage Multiplier", "Multiplier applied to damage."), movementData[DamageAmountIndex].FloatValue);
            }

            if (movementData [DamageAmountIndex].FloatValue < 0)
            {
                movementData [DamageAmountIndex].FloatValue = 0;
            }


            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_SimpleLand.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            return(movementData);
        }
Exemple #25
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_Physics.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);


            return(movementData);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Climb speed
            if (movementData[ClimbUpSpeedIndex] == null)
            {
                movementData[ClimbUpSpeedIndex] = new MovementVariable(DefaultClimbUpSpeed);
            }
            movementData[ClimbUpSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Climb Up Speed", "How fast the character climbs up the wall when the user presses up."), movementData[ClimbUpSpeedIndex].FloatValue);
            if (movementData[ClimbUpSpeedIndex].FloatValue < 0)
            {
                movementData[ClimbUpSpeedIndex].FloatValue = 0;
            }

            // Climb speed
            if (movementData[SlideDownSpeedIndex] == null)
            {
                movementData[SlideDownSpeedIndex] = new MovementVariable(DefaultSlideDownSpeed);
            }
            movementData[SlideDownSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Slide Down Speed", "How fast the character slides down the wall (negative)."), movementData[SlideDownSpeedIndex].FloatValue);
            if (movementData[SlideDownSpeedIndex].FloatValue > 0)
            {
                movementData[SlideDownSpeedIndex].FloatValue = 0;
            }

            // Cling drag
            if (movementData[ClingDragIndex] == null)
            {
                movementData[ClingDragIndex] = new MovementVariable(DefaultClingDrag);
            }
            movementData[ClingDragIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Cling Drag", "How quickly we come to a halt when the user is not pressing down."), movementData[ClingDragIndex].FloatValue);
            if (movementData[ClingDragIndex].FloatValue < 0)
            {
                movementData[ClingDragIndex].FloatValue = 0;
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = WallMovement_WallCling.DrawInspectorWithOptions(movementData, ref showDetails, target, false, false);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            return(movementData);
        }
Exemple #27
0
        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="PlatformerPro.MovementVariable"/>.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="PlatformerPro.MovementVariable"/>.</param>
        /// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current
        /// <see cref="PlatformerPro.MovementVariable"/>; otherwise, <c>false</c>.</returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (ReferenceEquals(this, obj))
            {
                return(true);
            }
            if (obj.GetType() != typeof(MovementVariable))
            {
                return(false);
            }
            MovementVariable other = (MovementVariable)obj;

            return(floatValue == other.floatValue && intValue == other.intValue && stringValue == other.stringValue && boolValue == other.boolValue && vector2Value.x == other.vector2Value.x && vector2Value.y == other.vector2Value.y);
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            if (movementData[FloatGravityIndex] == null)
            {
                movementData[FloatGravityIndex] = new MovementVariable(DefaultFloatGravity);
            }
            movementData[FloatGravityIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Float Gravity", "Gravity to apply while floating."), movementData[FloatGravityIndex].FloatValue);
            if (movementData[FloatGravityIndex].FloatValue > 0)
            {
                movementData[FloatGravityIndex].FloatValue = 0.0f;
            }
            return(movementData);
        }
Exemple #29
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        new public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = SpecialMovement_HangFromCeiling.DrawInspector(movementData, ref showDetails, target);
            System.Array.Copy(baseMovementData, movementData, baseMovementData.Length);

            // Horizontal Climb Speed
            if (movementData [HorizontalClimbSpeedIndex] == null)
            {
                movementData [HorizontalClimbSpeedIndex] = new MovementVariable();
            }
            movementData [HorizontalClimbSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Horizontal Climb Speed", "Sepeed at which we climb horizontally."), movementData [HorizontalClimbSpeedIndex].FloatValue);
            if (movementData [HorizontalClimbSpeedIndex].FloatValue < 0)
            {
                movementData [HorizontalClimbSpeedIndex].FloatValue = 0;
            }

            string[] layerNames = GenerateLayerNames();


            // Climbable layers
            if (movementData [HorizontalClimbLayersIndex] == null)
            {
                movementData [HorizontalClimbLayersIndex] = new MovementVariable();
            }
            movementData [HorizontalClimbLayersIndex].IntValue = EditorGUILayout.MaskField(new GUIContent("Horizontal Climb Layers", "Layers we can climb across on."),
                                                                                           movementData [HorizontalClimbLayersIndex].IntValue,
                                                                                           layerNames);

            // Dismount on Extent
            if (movementData [DismountOnExtentIndex] == null)
            {
                movementData [DismountOnExtentIndex] = new MovementVariable();
            }
            movementData [DismountOnExtentIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Dismount on Extent ", "Should we dismounnt from the ceiling when we reach the edge."),
                                                                                    movementData [DismountOnExtentIndex].BoolValue);

            return(movementData);
        }
Exemple #30
0
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Roll speed
            if (movementData[SpeedIndex] == null)
            {
                movementData[SpeedIndex] = new MovementVariable(DefaultSpeed);
            }
            movementData[SpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Speed", "How fast the character walks."), movementData[SpeedIndex].FloatValue);
            if (movementData[SpeedIndex].FloatValue < 0)
            {
                movementData[SpeedIndex].FloatValue = 0.0f;
            }

            //Roll time
            if (movementData[RollTimeIndex] == null)
            {
                movementData[RollTimeIndex] = new MovementVariable(DefaultRollTime);
            }
            movementData[RollTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Roll Time", "How long the character will roll for if not interrupted."), movementData[RollTimeIndex].FloatValue);
            if (movementData[RollTimeIndex].FloatValue < 0)
            {
                movementData[RollTimeIndex].FloatValue = 0.0f;
            }

            // Y velocity for roll
            if (movementData[YVelocityForRollIndex] == null)
            {
                movementData[YVelocityForRollIndex] = new MovementVariable(DefaultYVelocityForRoll);
            }
            movementData[YVelocityForRollIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Fall Speed", "How fast the character needs to be falling before roll starts."), movementData[YVelocityForRollIndex].FloatValue);
            if (movementData[YVelocityForRollIndex].FloatValue > 0)
            {
                movementData[YVelocityForRollIndex].FloatValue = 0.0f;
            }

            return(movementData);
        }
 /// <summary>
 /// Initialise the movement with the given movement data.
 /// </summary>
 /// <param name="character">Character.</param>
 /// <param name="movementData">Movement data.</param>
 public override Movement Init(Character character, MovementVariable[] movementData)
 {
     base.Init (character, movementData);
     crouchMovement = character.GetComponentInChildren<GroundMovement_Crouch> ();
     if (crouchMovement == null)
     {
         Debug.LogWarning ("Couldn't find a crouch movement, crouch jump will be disabled.");
         Enabled = false;
     }
     return this;
 }
 /// <summary>
 /// Draws the inspector.
 /// </summary>
 public static new MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
 {
     return AirMovement_Digital.DrawInspector(movementData, ref showDetails, target);
 }
        /// <summary>
        /// Initialise the movement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            // Set variables
            if (movementData != null && movementData.Length == MovementVariableCount)
            {
                airSpeed = movementData[AirSpeedIndex].FloatValue;
                jumpHeight = movementData[JumpHeightIndex].FloatValue;
                relativeJumpGravity = movementData[JumpRelativeGravityIndex].FloatValue;
                groundedLeeway = movementData[GroundedLeewayIndex].FloatValue;
                canDoubleJump = movementData[CanDoubleJumpIndex].BoolValue;
                doubleJumpHeight = movementData[DoubleJumpHeightIndex].FloatValue;
                jumpWhenButtonHeld = movementData[JumpWhenButtonHeldIndex].BoolValue;
                maxDoubleJumpCount = movementData[MaxDoubleJumpCountIndex].IntValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            #if UNITY_EDITOR
                if (movementData != null && movementData.Length == MovementVariableCount - 1)
                {
                    Debug.Log("Open the movement in the inspector to auto upgrade.");
                }
            #endif
            }

            // Calculate initial velocity
            initialVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * relativeJumpGravity * jumpHeight);
            doubleJumpInitialVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * relativeJumpGravity * doubleJumpHeight);

            AddGravityFlipHandler ();

            return this;
        }
        /// <summary>
        /// Initialise the movement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            // Set variables
            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                airSpeed = movementData[AirSpeedIndex].FloatValue;
                minJumpHeight = movementData[MinJumpHeightIndex].FloatValue;
                maxJumpHeight = movementData[MaxJumpHeightIndex].FloatValue;
                maxJumpAccelerationTime = movementData[MaxJumpAccelerationTimeIndex].FloatValue;
                relativeJumpGravity = movementData[JumpRelativeGravityIndex].FloatValue;
                groundedLeeway = movementData[GroundedLeewayIndex].FloatValue;
                jumpWhenButtonHeld = movementData[JumpWhenButtonHeldIndex].BoolValue;
                canDoubleJump = movementData[CanDoubleJumpIndex].BoolValue;
                doubleJumpHeight = movementData[DoubleJumpHeightIndex].FloatValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            }

            // Calculate initial velocity and acceleration
            initialVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * relativeJumpGravity * minJumpHeight);
            doubleJumpVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * relativeJumpGravity * doubleJumpHeight);
            return this;
        }
Exemple #35
0
 /// <summary>
 /// Initialise the movement with the given movement data.
 /// </summary>
 /// <param name="character">Character.</param>
 /// <param name="movementData">Movement data.</param>
 public virtual Movement Init(Character character, MovementVariable[] movementData)
 {
     Debug.LogError("The Movement class shouldn't be initialised with movement data. Did you forget to override the Init method?");
     return this;
 }
        /// <summary>
        /// Draws the standard physics settings (used by many movements).
        /// </summary>
        /// <param name="movementData">Movement data.</param>
        /// <param name="movementDataIndexOffset">Movement data index offset. Because different movements might place this in different places 
        /// in the movement data array we need to offset the array position.</param>
        public static void DrawStandardPhysicsSettings(MovementVariable[] movementData, int movementDataIndexOffset, bool showDetails)
        {
            // Reset values if null
            if (movementData[FrictionIndex + movementDataIndexOffset] == null) movementData[FrictionIndex + movementDataIndexOffset] = new MovementVariable(DefaultFriction);
            if (movementData[SlopeAccelerationIndex + movementDataIndexOffset] == null) movementData[SlopeAccelerationIndex + movementDataIndexOffset] = new MovementVariable(DefaultSlopeAcceleration);
            if (movementData[QuiesceSpeedIndex + movementDataIndexOffset] == null) movementData[QuiesceSpeedIndex + movementDataIndexOffset] = new MovementVariable(DefaultQuiesceSpeed);
            if (movementData[IgnoreForceIndex + movementDataIndexOffset] == null) movementData[IgnoreForceIndex + movementDataIndexOffset] = new MovementVariable(DefaultIgnoreForce);

            // Do we need to draw, if so draw.
            if (showDetails)
            {
                GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1));
                GUILayout.Label ("Physics Settings", EditorStyles.boldLabel);

                // Friction
                movementData[FrictionIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("FrictionCoefficient", "Default coefficient of friction. Platforms can override this."), movementData[FrictionIndex + movementDataIndexOffset].FloatValue);
                if (movementData[FrictionIndex + movementDataIndexOffset].FloatValue < 0) movementData[FrictionIndex].FloatValue = 0.0f;

                // Slope Acceleration
                movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.Slider(new GUIContent("Slope Acceleration", "If the character is standing on a slope should they start to slide down it?"), movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue , 0, 2);

                // Quiesce
                movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("QuiesceSpeed", "At what velocity should we sleep if no acceleration is applied?"), movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue);

                // Ignore Force
                movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue = EditorGUILayout.FloatField(new GUIContent("Max Ignored Force", "Forces smaller than this will be ignored. Use this to ignore slight slopes or very small input values."), movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue);

                // Reset button
                if (GUILayout.Button(new GUIContent("Reset Physics To Defaults", "Resets all physics settings to default values.")))
                {
                    movementData[FrictionIndex + movementDataIndexOffset].FloatValue = DefaultFriction;
                    movementData[SlopeAccelerationIndex + movementDataIndexOffset].FloatValue = DefaultSlopeAcceleration;
                    movementData[QuiesceSpeedIndex + movementDataIndexOffset].FloatValue = DefaultQuiesceSpeed;
                    movementData[IgnoreForceIndex + movementDataIndexOffset].FloatValue = DefaultIgnoreForce;
                }
            }
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static new MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air acceleration
            if (movementData[AirSpeedAccelerationIndex] == null) movementData[AirSpeedAccelerationIndex] = new MovementVariable(DefaultAirSpeedAcceleration);
            movementData[AirSpeedAccelerationIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed Acceleration(x)", "Rate at which the character moves to the desired air speed."), movementData[AirSpeedAccelerationIndex].FloatValue);
            if (movementData[AirSpeedAccelerationIndex].FloatValue < 0) movementData[AirSpeedAccelerationIndex].FloatValue = 0.0f;

            // Run speed
            if (movementData[AirSpeedRunIndex] == null) movementData[AirSpeedRunIndex] = new MovementVariable(DefaultAirSpeedRun);
            movementData[AirSpeedRunIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed Run(x)", "How fast the character moves in the X direction whle in the air when run is depressed."), movementData[AirSpeedRunIndex].FloatValue);
            if (movementData[AirSpeedRunIndex].FloatValue < 0) movementData[AirSpeedRunIndex].FloatValue = 0.0f;

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = AirMovement_Variable.DrawInspector (movementData, ref showDetails, target);
            System.Array.Copy (baseMovementData, movementData, baseMovementData.Length);

            return movementData;
        }
        /// <summary>
        /// Initialise the mvoement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            myAnimator = character.GetComponentInChildren<Animator> ();
            if (myAnimator == null) Debug.LogWarning ("Play Animation special movement could not find an animator.");

            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                loopUntilInterrupted = movementData [LoopUntilInterruptedIndex].BoolValue;
                shouldApplyGravity = movementData [ShouldApplyGravityIndex].BoolValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            }
            return this;
        }
        /// <summary>
        /// Initialise the mvoement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            // Set variables
            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                acceleration = movementData[AccelerationIndex].FloatValue;
                maxSpeed = movementData[MaxSpeedIndex].FloatValue;
                friction = movementData[FrictionIndex].FloatValue;
                useAnalogueInput = movementData[UseAnalogueIndex].BoolValue;
                slopeAccelerationFactor = movementData[SlopeAccelerationIndex].FloatValue;
                quiesceSpeed = movementData[QuiesceSpeedIndex].FloatValue;
                ignoreForce = movementData[IgnoreForceIndex].FloatValue;
                stickToGround = movementData[StickToGroundIndex].BoolValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            }
            return this;
        }
        //        /// <summary>
        //        /// Unity Update() hook
        //        /// </summary>
        //        void Update()
        //        {
        //        }

        #endregion Other

        #if UNITY_EDITOR

        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Cling Gravity
            if (movementData[ClingGravityIndex] == null) movementData[ClingGravityIndex] = new MovementVariable(DefaultClingGravity);
            movementData[ClingGravityIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Cling Gravity", "Gravity to apply while wall clinging (negative number). Use 0 to allow infinite cling."), movementData[ClingGravityIndex].FloatValue);
            if (movementData[ClingGravityIndex].FloatValue > 0) movementData[ClingGravityIndex].FloatValue = 0;

            // JumpHeightIndex
            if (movementData[JumpHeightIndex] == null) movementData[JumpHeightIndex] = new MovementVariable(DefaultJumpHeight);
            movementData[JumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Jump Height", "How high the character jumps away from the wall. Use zero to have jump simply detach from the wall."), movementData[JumpHeightIndex].FloatValue);
            if (movementData[JumpHeightIndex].FloatValue < 0) movementData[JumpHeightIndex].FloatValue = 0;

            // AwayDistanceIndex
            if (movementData[AwayDistanceIndex] == null) movementData[AwayDistanceIndex] = new MovementVariable(DefaultAwayDistance);
            movementData[AwayDistanceIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Away Distance", "How far the character jumps away from the wall before giving back control to player."), movementData[AwayDistanceIndex].FloatValue);
            if (movementData[AwayDistanceIndex].FloatValue < 0) movementData[AwayDistanceIndex].FloatValue = 0;

            // AirSpeedIndex
            if (movementData[AirSpeedIndex] == null) movementData[AirSpeedIndex] = new MovementVariable(DefaultAirSpeed);
            movementData[AirSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed", "The horizontal movement speed when jumping away from the wall."), movementData[AirSpeedIndex].FloatValue);
            if (movementData[AirSpeedIndex].FloatValue < 0) movementData[AirSpeedIndex].FloatValue = 0;

            // AirSpeedRunIndex
            if (movementData[AirSpeedRunIndex] == null) movementData[AirSpeedRunIndex] = new MovementVariable(DefaultAirSpeedRun);
            movementData[AirSpeedRunIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed Run", "The horizontal movement speed when jumping away from the wall with run depressed."), movementData[AirSpeedRunIndex].FloatValue);
            if (movementData[AirSpeedRunIndex].FloatValue < movementData[AirSpeedIndex].FloatValue) movementData[AirSpeedRunIndex].FloatValue = movementData[AirSpeedIndex].FloatValue;

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");
            if (showDetails)
            {
                // Required Colliders
                if (movementData[RequiredCollidersIndex] == null) movementData[RequiredCollidersIndex] = new MovementVariable();
                movementData[RequiredCollidersIndex].IntValue = EditorGUILayout.IntField(new GUIContent("Required Colliders", "The number of colliders required to initiate wall cling."), movementData[RequiredCollidersIndex].IntValue);
                if (movementData[RequiredCollidersIndex].IntValue < 1) movementData[RequiredCollidersIndex].IntValue = 2;

            }

            return movementData;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }
            else if (movementData.Length == MovementVariableCount - 1)
            {
                Debug.Log ("Upgading movement data for passdown.");
                MovementVariable[] tmpMovementData = movementData;
                movementData = new MovementVariable[MovementVariableCount];
                System.Array.Copy (tmpMovementData, movementData, MovementVariableCount - 1);
            }
            else if (movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Require Jump
            if (movementData[RequireJumpIndex] == null) movementData[RequireJumpIndex] = new MovementVariable();
            movementData[RequireJumpIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Use Jump Button", "If false, pressing downwards will passthrough, if true you need to press both down and jump."), movementData[RequireJumpIndex].BoolValue);

            // Bobble Height
            if (movementData[BobbleHeightIndex] == null) movementData[BobbleHeightIndex] = new MovementVariable(0);
            movementData[BobbleHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Bobble Height", "How high should the character bobble before moving downwards."), movementData[BobbleHeightIndex].FloatValue);
            if (movementData[BobbleHeightIndex].FloatValue < 0) movementData[BobbleHeightIndex].FloatValue = 0.0f;

            // Clearance Timer
            if (movementData[ClearanceTimeIndex] == null) movementData[ClearanceTimeIndex] = new MovementVariable(DefaultClearanceTime);
            movementData[ClearanceTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Clearance Time", "How long should this movement maintain control before giving it back to the normal air movement."), movementData[ClearanceTimeIndex].FloatValue);
            if (movementData[ClearanceTimeIndex].FloatValue < 0) movementData[ClearanceTimeIndex].FloatValue = 0.0f;

            // Support Tiles Jump
            if (movementData[SupportTilesIndex] == null) movementData[SupportTilesIndex] = new MovementVariable();
            movementData[SupportTilesIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Support Tiles", "If true all feet colliders will be ignored, if false only the middle ground collider."), movementData[SupportTilesIndex].BoolValue);

            return movementData;
        }
        /// <summary>
        /// Initialise the movement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            if (movementData != null && movementData.Length == MovementVariableCount)
            {
                RequiredColliders = movementData[RequiredCollidersIndex].IntValue;
                clingGravity = movementData[ClingGravityIndex].FloatValue;
                jumpHeight = movementData[JumpHeightIndex].FloatValue;
                awayDistance = movementData[AwayDistanceIndex].FloatValue;
                airSpeed = movementData[AirSpeedIndex].FloatValue;
                airSpeedRun = movementData[AirSpeedRunIndex].FloatValue;;
                initialVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * jumpHeight);
            }
            else
            {
                Debug.LogError("Invalid movement data, not enough values.");
            }
            return this;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Roll speed
            if (movementData[SpeedIndex] == null) movementData[SpeedIndex] = new MovementVariable(DefaultSpeed);
            movementData[SpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Speed", "How fast the character walks."), movementData[SpeedIndex].FloatValue);
            if (movementData[SpeedIndex].FloatValue < 0) movementData[SpeedIndex].FloatValue = 0.0f;

            //Roll time
            if (movementData[RollTimeIndex] == null) movementData[RollTimeIndex] = new MovementVariable(DefaultRollTime);
            movementData[RollTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Roll Time", "How long the character will roll for if not interrupted."), movementData[RollTimeIndex].FloatValue);
            if (movementData[RollTimeIndex].FloatValue < 0) movementData[RollTimeIndex].FloatValue = 0.0f;

            // Y velocity for roll
            if (movementData[YVelocityForRollIndex] == null) movementData[YVelocityForRollIndex] = new MovementVariable(DefaultYVelocityForRoll);
            movementData[YVelocityForRollIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Fall Speed", "How fast the character needs to be falling before roll starts."), movementData[YVelocityForRollIndex].FloatValue);
            if (movementData[YVelocityForRollIndex].FloatValue > 0) movementData[YVelocityForRollIndex].FloatValue = 0.0f;

            return movementData;
        }
        /// <summary>
        /// Initialise the mvoement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                speed = movementData[SpeedIndex].FloatValue;
                rollTime = movementData[RollTimeIndex].FloatValue;
                yVelocityForRoll = movementData[YVelocityForRollIndex].FloatValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            }
            return this;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Cling Gravity
            if (movementData[ClingGravityIndex] == null) movementData[ClingGravityIndex] = new MovementVariable();
            movementData[ClingGravityIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Cling Gravity", "Gravity to apply while wall clinging (negative number). Use 0 to allow infinite cling."), movementData[ClingGravityIndex].FloatValue);
            if (movementData[ClingGravityIndex].FloatValue > 0) movementData[ClingGravityIndex].FloatValue = 0;

            // Gravity Delay
            if (movementData[GravityDelayIndex] == null) movementData[GravityDelayIndex] = new MovementVariable();
            movementData[GravityDelayIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Gravity Delay", "How long to wait before applying gravity."), movementData[GravityDelayIndex].FloatValue);
            if (movementData[GravityDelayIndex].FloatValue < 0) movementData[GravityDelayIndex].FloatValue = 0;

            // JumpHeightIndex
            if (movementData[JumpHeightIndex] == null) movementData[JumpHeightIndex] = new MovementVariable();
            movementData[JumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Jump Height", "How high the character jumps away from the wall. Use zero to have jump simply detach from the wall."), movementData[JumpHeightIndex].FloatValue);
            if (movementData[JumpHeightIndex].FloatValue < 0) movementData[JumpHeightIndex].FloatValue = 0;

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");
            if (showDetails)
            {
                // Required Colliders
                if (movementData[RequiredCollidersIndex] == null) movementData[RequiredCollidersIndex] = new MovementVariable();
                movementData[RequiredCollidersIndex].IntValue = EditorGUILayout.IntField(new GUIContent("Required Colliders", "The number of colliders required to initiate wall cling."), movementData[RequiredCollidersIndex].IntValue);
                if (movementData[RequiredCollidersIndex].IntValue < 1) movementData[RequiredCollidersIndex].IntValue = 2;

                // Ignore cling after jump time
                if (movementData[IgnoreClingAfterJumpTimeIndex] == null) movementData[IgnoreClingAfterJumpTimeIndex] = new MovementVariable();
                movementData[IgnoreClingAfterJumpTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Ignore After Jump Time", "The number of seconds after jumping that all wall clings will be ignored."), movementData[IgnoreClingAfterJumpTimeIndex].FloatValue);
                if (movementData[IgnoreClingAfterJumpTimeIndex].FloatValue < 0) movementData[IgnoreClingAfterJumpTimeIndex].FloatValue = 0;

                // Must hold towards wall cosntantly to maintain cling
                if (movementData[MustHoldToMaintainClingIndex] == null) movementData[MustHoldToMaintainClingIndex] = new MovementVariable();
                movementData[MustHoldToMaintainClingIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Must Hold to Cling", "If true the user must constantly hold towards the wall to cling."), movementData[MustHoldToMaintainClingIndex].BoolValue);

                // Ignore jump time
                if (movementData[IgnoreJumpTimeIndex] == null) movementData[IgnoreJumpTimeIndex] = new MovementVariable();
                movementData[IgnoreJumpTimeIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Ignore Jump Time", "The number of seconds that the jump button will be ignored after a cling starts."), movementData[IgnoreJumpTimeIndex].FloatValue);
                if (movementData[IgnoreJumpTimeIndex].FloatValue < 0) movementData[IgnoreJumpTimeIndex].FloatValue = 0;

            }

            return movementData;
        }
 /// <summary>
 /// Clone constructor. Initializes a new instance of the <see cref="PlatformerPro.MovementVariable"/> class.
 /// </summary>
 /// <param name="originalVariable">Variable to clone values from.</param>
 public MovementVariable(MovementVariable originalVariable)
 {
     if (originalVariable != null)
     {
         this.floatValue = originalVariable.floatValue;
         this.intValue = originalVariable.intValue;
         this.stringValue = originalVariable.stringValue;
         this.boolValue = originalVariable.boolValue;
         this.vector2Value = originalVariable.vector2Value;
         this.gameObjectValue = originalVariable.gameObjectValue;
     }
 }
        /// <summary>
        /// Initialise the movement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            if (movementData != null && movementData.Length == MovementVariableCount)
            {
                RequiredColliders = movementData[RequiredCollidersIndex].IntValue;
                clingGravity = movementData[ClingGravityIndex].FloatValue;
                gravityDelay = movementData[GravityDelayIndex].FloatValue;
                jumpHeight = movementData[JumpHeightIndex].FloatValue;
                ignoreClingAfterJumpTime = movementData[IgnoreClingAfterJumpTimeIndex].FloatValue;
                mustHoldToMaintainCling = movementData[MustHoldToMaintainClingIndex].BoolValue;
                ignoreJumpTime = movementData[IgnoreJumpTimeIndex].FloatValue;
            }
            else
            {
                Debug.LogError("Invalid movement data, not enough values.");
            }

            highestRightCollider = character.Colliders.Where (c=>c.RaycastType == RaycastType.SIDE_RIGHT ).OrderByDescending(c=>c.WorldPosition.y).FirstOrDefault();
            highestLeftCollider  = character.Colliders.Where (c=>c.RaycastType == RaycastType.SIDE_LEFT ).OrderByDescending(c=>c.WorldPosition.y).FirstOrDefault();

            return this;
        }
        /// <summary>
        /// Checks for unexpected settings combinations and returns a warning if they are found.
        /// </summary>
        /// <returns>The string describing unexpected settings, or null if none found..</returns>
        protected static string CheckForUnexpectedSettings(MovementVariable[] movementData)
        {
            if (movementData[AvailableDismountsIndex].IntValue == 0) return "No method for dismounting ladders has been selected. This may mean you cannot get off from a ladder.";

            return null;
        }
        /// <summary>
        /// Initialise the movement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            base.Init (character, movementData);

            // Set variables
            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                airSpeedRun = movementData[AirSpeedRunIndex].FloatValue;
                airSpeedAcceleration = movementData[AirSpeedAccelerationIndex].FloatValue;
            }
            else
            {
                Debug.LogError("Invalid movement data.");
            }

            // Calculate initial velocity and acceleration
            initialVelocity = Mathf.Sqrt(-2.0f * character.DefaultGravity * relativeJumpGravity * minJumpHeight);

            return this;
        }
        /// <summary>
        /// Initialise the mvoement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            this.character = character;

            if (movementData != null && movementData.Length == MovementVariableCount)
            {
                climbSpeed = movementData[ClimbSpeedIndex].FloatValue;
                leeway = movementData[LeewayIndex].FloatValue;
                centeringRate = movementData[CenteringRateIndex].FloatValue;
                availableDismounts = movementData[AvailableDismountsIndex].IntValue;
                DetectLaddersByTag = movementData[DetectLaddersByTagIndex].BoolValue;
                LadderLayerOrTagName = movementData[LadderLayerOrTagNameIndex].StringValue;
            }
            else
            {
                Debug.LogError("Invalid movement data, not enough values.");
            }
            return this;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Max Speed
            if (movementData[MaxSpeedIndex] == null) movementData[MaxSpeedIndex] = new MovementVariable(DefaultMaxSpeed);
            movementData[MaxSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Maximum Speed", "The characters peak speed."), movementData[MaxSpeedIndex].FloatValue);
            if (movementData[MaxSpeedIndex].FloatValue < 0) movementData[MaxSpeedIndex].FloatValue = 0.0f;

            // Acceleration
            if (movementData[AccelerationIndex] == null) movementData[AccelerationIndex] = new MovementVariable(DefaultAcceleration);
            movementData[AccelerationIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Acceleration", "How fast the character accelerates."), movementData[AccelerationIndex].FloatValue);
            if (movementData[AccelerationIndex].FloatValue < 0) movementData[AccelerationIndex].FloatValue = 0.0f;

            // Use Analog
            if (movementData[UseAnalogueIndex] == null) movementData[UseAnalogueIndex] = new MovementVariable(false);
            movementData[UseAnalogueIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Use Analogue Input", "Should the characters acceleration be affected by how hard/far the character presses the controller?"), movementData[UseAnalogueIndex].BoolValue);

            // Stick to ground
            if (movementData[StickToGroundIndex] == null) movementData[StickToGroundIndex] = new MovementVariable(false);
            movementData[StickToGroundIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Stick to Ground", "Should the character stick to the ground when running on slopes?"), movementData[StickToGroundIndex].BoolValue);

            // Stick to ground warning
            if (target != null && !target.rotateToSlopes && !movementData[StickToGroundIndex].BoolValue)
            {
                EditorGUILayout.HelpBox("If your Character doesn't rotate to slopes you may want to enable stick to ground. If these settings are both off your cahracter will be able to 'run' off the slope.", MessageType.Info);
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Advanced Settings");
            DrawStandardPhysicsSettings(movementData, 0, showDetails);

            return movementData;
        }
 public MovementVariable Convert()
 {
     MovementVariable result = new MovementVariable ();
     result.FloatValue = this.floatValue;
     result.IntValue = this.intValue;
     result.StringValue = this.stringValue;
     result.BoolValue = this.boolValue;
     result.Vector2Value = this.vector2Value;
     result.GameObjectValue = this.gameObjectValue;
     return result;
 }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air speed
            if (movementData[AirSpeedIndex] == null) movementData[AirSpeedIndex] = new MovementVariable(DefaultAirSpeed);
            movementData[AirSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed (x)", "How fast the character moves in the X direction whle in the air."), movementData[AirSpeedIndex].FloatValue);
            if (movementData[AirSpeedIndex].FloatValue < 0) movementData[AirSpeedIndex].FloatValue = 0.0f;

            // Min Jump height
            if (movementData[MinJumpHeightIndex] == null) movementData[MinJumpHeightIndex] = new MovementVariable(DefaultMinJumpHeight);
            movementData[MinJumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Min Jump Height", "How high the character jumps if jump button is tapped."), movementData[MinJumpHeightIndex].FloatValue);
            if (movementData[MinJumpHeightIndex].FloatValue < 0) movementData[MinJumpHeightIndex].FloatValue = 0.0f;

            // Max Jump height
            if (movementData[MaxJumpHeightIndex] == null) movementData[MaxJumpHeightIndex] = new MovementVariable(DefaultMaxJumpHeight);
            movementData[MaxJumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Max Jump Height", "How high the character jumps if jump button is held for full jump acceleration time."), movementData[MaxJumpHeightIndex].FloatValue);
            if (movementData[MaxJumpHeightIndex].FloatValue < movementData[MinJumpHeightIndex].FloatValue) movementData[MaxJumpHeightIndex].FloatValue = movementData[MinJumpHeightIndex].FloatValue;

            // Jump Time
            if (movementData[MaxJumpAccelerationTimeIndex] == null) movementData[MaxJumpAccelerationTimeIndex] = new MovementVariable(DefaultMaxJumpAccelerationTime);
            movementData[MaxJumpAccelerationTimeIndex].FloatValue = EditorGUILayout.Slider(new GUIContent("Max Jump Time", "How long the player has to hold jump for the max height to be reached."), movementData[MaxJumpAccelerationTimeIndex].FloatValue, 0.01f, 1.0f);

            // Double jump
            if (movementData[CanDoubleJumpIndex] == null) movementData[CanDoubleJumpIndex] = new MovementVariable();
            movementData[CanDoubleJumpIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Can Double Jump", "If true player can double jump."), movementData[CanDoubleJumpIndex].BoolValue);

            // Double jump height
            if (movementData[CanDoubleJumpIndex].BoolValue)
            {
                if (movementData[DoubleJumpHeightIndex] == null) movementData[DoubleJumpHeightIndex] = new MovementVariable(DefaultMaxJumpHeight);
                movementData[DoubleJumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Double Jump Height", "How high the character double jumps."), movementData[DoubleJumpHeightIndex].FloatValue);
                if (movementData[DoubleJumpHeightIndex].FloatValue <= 0) movementData[DoubleJumpHeightIndex].FloatValue = DefaultMaxJumpHeight;
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");

            // Make sure we set defaults regardless of showDetails
            if (movementData[JumpRelativeGravityIndex] == null || movementData[JumpRelativeGravityIndex].FloatValue < 0.01f || movementData[JumpRelativeGravityIndex].FloatValue > 2.0f)
            {
                movementData[JumpRelativeGravityIndex] = new MovementVariable(DefaultRelativeJumpGravity);
            }
            if (movementData[GroundedLeewayIndex] == null)
            {
                movementData[GroundedLeewayIndex] = new MovementVariable(DefaultGroundedLeeway);
            }
            if (movementData[JumpWhenButtonHeldIndex] == null) movementData[JumpWhenButtonHeldIndex] = new MovementVariable();

            if (showDetails)
            {
                movementData = AirMovement.DrawStandardJumpDetails(movementData, JumpRelativeGravityIndex, GroundedLeewayIndex, JumpWhenButtonHeldIndex);
            }

            // As this may not be set if show details are closed lets set it.
            if (movementData [JumpRelativeGravityIndex] == null) movementData [JumpRelativeGravityIndex] = new MovementVariable (DefaultRelativeJumpGravity);

            // Check for things that don't look right
            if (((movementData[MaxJumpHeightIndex].FloatValue - movementData[MinJumpHeightIndex].FloatValue) * movementData[MaxJumpAccelerationTimeIndex].FloatValue ) > 0.5f)
            {
                EditorGUILayout.HelpBox("Your jump settings mean that your character may moves in an unnatural floaty way if jump is held. Consider reducing Max Jump Time or increasing the Min Jump Height.", MessageType.Warning);
                float betterTime = 0.5f / (movementData[MaxJumpHeightIndex].FloatValue - movementData[MinJumpHeightIndex].FloatValue);
                if (betterTime < 1 && betterTime >= 0.1f)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.FlexibleSpace();
                    if (GUILayout.Button(string.Format("Set time to {0:0.00}", betterTime)))
                    {
                        movementData[MaxJumpAccelerationTimeIndex].FloatValue = betterTime;
                    }
                    GUILayout.EndHorizontal();
                }
            }

            // Check for things that don't look right
            if (movementData[JumpRelativeGravityIndex].FloatValue < 1.4f)
            {
                EditorGUILayout.HelpBox("Variable height jumps tend to look more natural with a high relative jump gravity.", MessageType.Warning);
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Set to " + DefaultRelativeJumpGravity))
                {
                    movementData[JumpRelativeGravityIndex].FloatValue = DefaultRelativeJumpGravity;
                }
                GUILayout.EndHorizontal();
            }
            return movementData;
        }
 public static void SaveToFile(string fullPath, MovementVariable[] data)
 {
     if (fullPath.Length != 0) {
         //using (StreamWriter writer = new StreamWriter(fullPath))
         using (Stream writer = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None))
         {
             IFormatter formatter = new BinaryFormatter();
             formatter.Serialize(writer, data.ToList ().ConvertAll(m => new SavableMovementVariable(m)));
         }
     }
     else
     {
         Debug.LogError ("Tried to save movement data to file but no input path was specified.");
     }
 }
        /// <summary>
        /// Initialise the mvoement with the given movement data.
        /// </summary>
        /// <param name="character">Character.</param>
        /// <param name="movementData">Movement data.</param>
        public override Movement Init(Character character, MovementVariable[] movementData)
        {
            Init (character);

            if (movementData != null && movementData.Length >= MovementVariableCount)
            {
                requireJump = movementData[RequireJumpIndex].BoolValue;
                bobbleHeight = movementData[BobbleHeightIndex].FloatValue;
                clearanceTime = movementData[ClearanceTimeIndex].FloatValue;
                supportTiles  = movementData[SupportTilesIndex].BoolValue;
            }
            else
            {
                Debug.LogWarning("Invalid movement data.");
            }
            return this;
        }
 /// <summary>
 /// Clone constructor. Initializes a new instance of the <see cref="PlatformerPro.MovementVariable"/> class.
 /// </summary>
 /// <param name="originalVariable">Variable to clone values from.</param>
 public SavableMovementVariable(MovementVariable originalVariable)
 {
     this.floatValue = originalVariable.FloatValue;
     this.intValue = originalVariable.IntValue;
     this.stringValue = originalVariable.StringValue;
     this.boolValue = originalVariable.BoolValue;
     this.vector2Value = originalVariable.Vector2Value;
     this.gameObjectValue = originalVariable.GameObjectValue;
 }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }
            if (movementData[LoopUntilInterruptedIndex] == null) movementData[LoopUntilInterruptedIndex] = new MovementVariable();
            movementData[LoopUntilInterruptedIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Loop Forever", "If true animation will loop and maintain control until the StopAnimation() function is called."), movementData[LoopUntilInterruptedIndex].BoolValue);

            if (movementData[ShouldApplyGravityIndex] == null) movementData[ShouldApplyGravityIndex] = new MovementVariable();
            movementData[ShouldApplyGravityIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Should Apply Gravity", "If true gravity will be applied during the animation."), movementData[ShouldApplyGravityIndex].BoolValue);

            if (movementData[FallAnimationStateIndex] == null) movementData[FallAnimationStateIndex] = new MovementVariable((int)AnimationState.FALL);
            if (movementData [ShouldApplyGravityIndex].BoolValue)
            {
                movementData [FallAnimationStateIndex].IntValue = (int) (AnimationState) EditorGUILayout.EnumPopup (new GUIContent ("Fall Animation State", "If gravity is enabled this is the animation state to send while falling "), (AnimationState) movementData [FallAnimationStateIndex].IntValue);
            }
            return movementData;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData != null  && movementData.Length == MovementVariableCount - 1)
            {
                Debug.LogWarning("Upgrading AirMovement_Digital movement data.");
                MovementVariable[] tmp = movementData;
                movementData = new MovementVariable[MovementVariableCount];
                System.Array.Copy(tmp, movementData, MovementVariableCount - 1);
            }
            else if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Air speed
            if (movementData[AirSpeedIndex] == null) movementData[AirSpeedIndex] = new MovementVariable(DefaultAirSpeed);
            movementData[AirSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Air Speed (x)", "How fast the character moves in the X direction whle in the air."), movementData[AirSpeedIndex].FloatValue);
            if (movementData[AirSpeedIndex].FloatValue < 0) movementData[AirSpeedIndex].FloatValue = 0.0f;

            // Jump height
            if (movementData[JumpHeightIndex] == null) movementData[JumpHeightIndex] = new MovementVariable(DefaultJumpHeight);
            movementData[JumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Jump Height", "How high the character jumps"), movementData[JumpHeightIndex].FloatValue);
            if (movementData[JumpHeightIndex].FloatValue < 0) movementData[JumpHeightIndex].FloatValue = 0.0f;

            // Can double-jump
            if (movementData[CanDoubleJumpIndex] == null) movementData[CanDoubleJumpIndex] = new MovementVariable(DefaultCanDoubleJump);
            movementData[CanDoubleJumpIndex].BoolValue = EditorGUILayout.Toggle(new GUIContent("Can Double-jump", "Can the character double-jump?"), movementData[CanDoubleJumpIndex].BoolValue);

            // Double-jump settings
            if (movementData[DoubleJumpHeightIndex] == null) movementData[DoubleJumpHeightIndex] = new MovementVariable(DefaultDoubleJumpHeight);
            if (movementData[MaxDoubleJumpCountIndex] == null) movementData[MaxDoubleJumpCountIndex] = new MovementVariable(2);
            if (movementData[CanDoubleJumpIndex].BoolValue)
            {
                // Double-jump height
                movementData[DoubleJumpHeightIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Double Jump Height", "How high the character jumps on a double-jump."), movementData[DoubleJumpHeightIndex].FloatValue);
                if (movementData[DoubleJumpHeightIndex].FloatValue < 0) movementData[DoubleJumpHeightIndex].FloatValue = 0.0f;

                if (EditorGUILayout.Toggle(new GUIContent("Infinite Double Jumps", "Can the character jump in the air forever?"), movementData[MaxDoubleJumpCountIndex].IntValue == -1))
                {
                    movementData[MaxDoubleJumpCountIndex].IntValue = -1;
                }
                else
                {
                    // Max Double Jump Count
                    movementData[MaxDoubleJumpCountIndex].IntValue = 1 + EditorGUILayout.IntField(new GUIContent("Max Jumps", "How many times can the character jump while in the air."), movementData[MaxDoubleJumpCountIndex].IntValue - 1);
                    if (movementData[MaxDoubleJumpCountIndex].IntValue < 2) movementData[MaxDoubleJumpCountIndex].IntValue = 2;
                }
            }

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");

            // Make sure we set defaults regardless of showDetails
            if (movementData[JumpRelativeGravityIndex] == null || movementData[JumpRelativeGravityIndex].FloatValue < 0.01f || movementData[JumpRelativeGravityIndex].FloatValue > 2.0f)
            {
                movementData[JumpRelativeGravityIndex] = new MovementVariable(DefaultRelativeJumpGravity);
            }
            if (movementData[GroundedLeewayIndex] == null)
            {
                movementData[GroundedLeewayIndex] = new MovementVariable(DefaultGroundedLeeway);
            }
            if (movementData[JumpWhenButtonHeldIndex] == null) movementData[JumpWhenButtonHeldIndex] = new MovementVariable();

            if (showDetails)
            {
                movementData = AirMovement.DrawStandardJumpDetails(movementData, JumpRelativeGravityIndex, GroundedLeewayIndex, JumpWhenButtonHeldIndex);
            }
            return movementData;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length != MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Climb speed
            if (movementData[ClimbSpeedIndex] == null) movementData[ClimbSpeedIndex] = new MovementVariable(DefaultClimbSpeed);
            movementData[ClimbSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Climb Speed", "How fast the character climbs."), movementData[ClimbSpeedIndex].FloatValue);
            if (movementData[ClimbSpeedIndex].FloatValue < 0) movementData[ClimbSpeedIndex].FloatValue = 0.0f;
            if (movementData[ClimbSpeedIndex].FloatValue == 0.0f) EditorGUILayout.HelpBox("Climb speed should be larger than 0.", MessageType.Warning, true);

            // Dismounts
            if (movementData[AvailableDismountsIndex] == null) movementData[AvailableDismountsIndex] = new MovementVariable(DefaultAvailableDismounts);

            showDismounts = EditorGUILayout.Foldout(showDismounts, new GUIContent("Dismounts", "Options for defining how the character exits a ladder."));
            if (showDismounts)
            {
                bool jump = EditorGUILayout.Toggle(new GUIContent("Jump", "Can the character jump off of the ladder."), (movementData[AvailableDismountsIndex].IntValue & (int)LadderDismountType.JUMP) == (int)LadderDismountType.JUMP);
                if (jump) movementData[AvailableDismountsIndex].IntValue |= (int) LadderDismountType.JUMP;
                else  movementData[AvailableDismountsIndex].IntValue &= ~((int) LadderDismountType.JUMP);

                bool leftRight = EditorGUILayout.Toggle(new GUIContent("Left/Right", "Can the character move left and right off of the ladder."), (movementData[AvailableDismountsIndex].IntValue & (int)LadderDismountType.LEFT_RIGHT) == (int)LadderDismountType.LEFT_RIGHT);
                if (leftRight) movementData[AvailableDismountsIndex].IntValue |= (int) LadderDismountType.LEFT_RIGHT;
                else  movementData[AvailableDismountsIndex].IntValue &= ~((int) LadderDismountType.LEFT_RIGHT);

                bool topBottom = EditorGUILayout.Toggle(new GUIContent("Bottom/Top", "Can the character climb off the top and bottom of the ladder."), (movementData[AvailableDismountsIndex].IntValue & (int)LadderDismountType.TOP_BOTTOM) == (int)LadderDismountType.TOP_BOTTOM);
                if (topBottom) movementData[AvailableDismountsIndex].IntValue |= (int) LadderDismountType.TOP_BOTTOM;
                else  movementData[AvailableDismountsIndex].IntValue &= ~((int) LadderDismountType.TOP_BOTTOM);
            }

            // Make sure we reset defaults even if details not shown
            if (movementData[LeewayIndex] == null) movementData[LeewayIndex] = new MovementVariable(DefaultLeeway);
            if (movementData[CenteringRateIndex] == null) movementData[CenteringRateIndex] = new MovementVariable(DefaultCenteringRate);

            showDetails = EditorGUILayout.Foldout(showDetails, "Details");
            if (showDetails)
            {
                // Leeway
                movementData[LeewayIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Leeway", "How close to the ladder the character needs to be before they snap to the middle."), movementData[LeewayIndex].FloatValue);
                if (movementData[LeewayIndex].FloatValue < 0) movementData[LeewayIndex].FloatValue = 0.0f;

                // Centering Rate
                movementData[CenteringRateIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Centering Rate", "The rate at which the character snaps to the middle of the ladder."), movementData[CenteringRateIndex].FloatValue);
                if (movementData[CenteringRateIndex].FloatValue < 0) movementData[CenteringRateIndex].FloatValue = 0.0f;

            }

            // Help Box if a weird combination is found
            string warning = CheckForUnexpectedSettings(movementData);
            if (warning != null) EditorGUILayout.HelpBox(warning, MessageType.Warning, true);

            return movementData;
        }
        /// <summary>
        /// Draws the inspector.
        /// </summary>
        public static new MovementVariable[] DrawInspector(MovementVariable[] movementData, ref bool showDetails, Character target)
        {
            if (movementData == null || movementData.Length < MovementVariableCount)
            {
                movementData = new MovementVariable[MovementVariableCount];
            }

            // Draw base inspector and copy values
            MovementVariable[] baseMovementData = GroundMovement_Digital.DrawInspector (movementData, ref showDetails, target);
            System.Array.Copy (baseMovementData, movementData, baseMovementData.Length);

            // Run speed
            if (movementData[RunSpeedIndex] == null) movementData[RunSpeedIndex] = new MovementVariable();
            movementData[RunSpeedIndex].FloatValue = EditorGUILayout.FloatField(new GUIContent("Run Speed", "How fast the character runs."), movementData[RunSpeedIndex].FloatValue);
            if (movementData[RunSpeedIndex].FloatValue < 0) movementData[RunSpeedIndex].FloatValue = 0.0f;

            return movementData;
        }