コード例 #1
0
    void FixedUpdate()
    {
        // Get current head position
        float currentHeight = head.localPosition.y;

        if (IsKeyPressed(keys))
        {
            // Crouch down
            float minHeight = defaultHeadYLocalPosition - crouchYLocalPosition;

            // Enforce crouched y local position animation of the head.
            if (minHeight < currentHeight)
            {
                head.localPosition = new Vector3(head.localPosition.x, head.localPosition.y - 0.1f, head.localPosition.z);
            }

            // Lower the capsule collider.
            if (capsuleCollider)
            {
                capsuleCollider.height = defaultCapsuleColliderHeight - (defaultHeadYLocalPosition - crouchYLocalPosition);
                capsuleCollider.center = Vector3.up * capsuleCollider.height * .5f;
            }

            // Set state.
            if (!isCrouched)
            {
                isCrouched = true;
                CrouchStart?.Invoke();
            }
        }
        else
        {
            // Will the Real Slim Shady please stand up?
            float maxHeight = defaultHeadYLocalPosition;

            // Reset the head to its default y local position.
            if (currentHeight < maxHeight)
            {
                head.localPosition = new Vector3(head.localPosition.x, head.localPosition.y + 0.1f, head.localPosition.z);
            }

            // Reset the capsule collider's position.
            if (capsuleCollider)
            {
                capsuleCollider.height = defaultCapsuleColliderHeight;
                capsuleCollider.center = Vector3.up * capsuleCollider.height * .5f;
            }

            // Reset state.
            isCrouched = false;
            CrouchEnd?.Invoke();
        }
    }
コード例 #2
0
    void LateUpdate()
    {
        if (Input.GetKey(key))
        {
            // Enforce crouched y local position of the head.
            head.localPosition = new Vector3(head.localPosition.x, crouchYLocalPosition, head.localPosition.z);

            // Lower the capsule collider.
            if (capsuleCollider)
            {
                capsuleCollider.height = defaultCapsuleColliderHeight - (defaultHeadYLocalPosition - crouchYLocalPosition);
                capsuleCollider.center = Vector3.up * capsuleCollider.height * .5f;
            }

            // Set state.
            if (!IsCrouched)
            {
                IsCrouched = true;
                SetSpeedOverrideActive(true);
                CrouchStart?.Invoke();
            }
        }
        else if (IsCrouched)
        {
            // Reset the head to its default y local position.
            head.localPosition = new Vector3(head.localPosition.x, defaultHeadYLocalPosition, head.localPosition.z);

            // Reset the capsule collider's position.
            if (capsuleCollider)
            {
                capsuleCollider.height = defaultCapsuleColliderHeight;
                capsuleCollider.center = Vector3.up * capsuleCollider.height * .5f;
            }

            // Reset state.
            IsCrouched = false;
            SetSpeedOverrideActive(false);
            CrouchEnd?.Invoke();
        }
    }
コード例 #3
0
    void LateUpdate()
    {
        if (Input.GetKey(key))
        {
            // Enforce a low head.
            if (headToLower)
            {
                // If we don't have the defaultHeadYLocalPosition, get it now.
                if (!defaultHeadYLocalPosition.HasValue)
                {
                    defaultHeadYLocalPosition = headToLower.localPosition.y;
                }

                // Lower the head.
                headToLower.localPosition = new Vector3(headToLower.localPosition.x, crouchYHeadPosition, headToLower.localPosition.z);
            }

            // Enforce a low colliderToLower.
            if (colliderToLower)
            {
                // If we don't have the defaultColliderHeight, get it now.
                if (!defaultColliderHeight.HasValue)
                {
                    defaultColliderHeight = colliderToLower.height;
                }

                // Get lowering amount.
                float loweringAmount;
                if (defaultHeadYLocalPosition.HasValue)
                {
                    loweringAmount = defaultHeadYLocalPosition.Value - crouchYHeadPosition;
                }
                else
                {
                    loweringAmount = defaultColliderHeight.Value * .5f;
                }

                // Lower the colliderToLower.
                colliderToLower.height = Mathf.Max(defaultColliderHeight.Value - loweringAmount, 0);
                colliderToLower.center = Vector3.up * colliderToLower.height * .5f;
            }

            // Set IsCrouched state.
            if (!IsCrouched)
            {
                IsCrouched = true;
                SetSpeedOverrideActive(true);
                CrouchStart?.Invoke();
            }
        }
        else
        {
            if (IsCrouched)
            {
                // Rise the head back up.
                if (headToLower)
                {
                    headToLower.localPosition = new Vector3(headToLower.localPosition.x, defaultHeadYLocalPosition.Value, headToLower.localPosition.z);
                }

                // Reset the colliderToLower's height.
                if (colliderToLower)
                {
                    colliderToLower.height = defaultColliderHeight.Value;
                    colliderToLower.center = Vector3.up * colliderToLower.height * .5f;
                }

                // Reset IsCrouched.
                IsCrouched = false;
                SetSpeedOverrideActive(false);
                CrouchEnd?.Invoke();
            }
        }
    }
        public StateController <CharacterState, CharacterContext> BuildCharacterControllerImpl(StateControllerBuilder <CharacterState, CharacterContext> builder)
        {
            Builder = builder;
            InjectState(this);

            // Declare Smash Attacks
            SmashUp.Charge.Data.SmashAttack   = SmashAttack.Charge;
            SmashSide.Charge.Data.SmashAttack = SmashAttack.Charge;
            SmashDown.Charge.Data.SmashAttack = SmashAttack.Charge;

            SmashUp.Attack.Data.SmashAttack   = SmashAttack.Attack;
            SmashSide.Attack.Data.SmashAttack = SmashAttack.Attack;
            SmashDown.Attack.Data.SmashAttack = SmashAttack.Attack;

            // Ground Attacks
            new [] { Idle, Walk, CrouchStart, Crouch, CrouchEnd }
            // Smash Attacks
            .AddTransitions <CharacterState, CharacterContext>(context => {
                var input = context.Input;
                if (!input.Attack.WasPressed)
                {
                    return(null);
                }
                switch (input.Smash.Direction)
                {
                case Direction.Right:
                case Direction.Left:
                    return(SmashSide.Charge);

                case Direction.Up:
                    return(SmashUp.Charge);

                case Direction.Down:
                    return(SmashDown.Charge);
                }
                return(null);
            })
            // Tilt Attacks
            .AddTransitions <CharacterState, CharacterContext>(context => {
                var input = context.Input;
                if (!input.Attack.WasPressed)
                {
                    return(null);
                }
                switch (input.Movement.Direction)
                {
                case Direction.Right:
                case Direction.Left:
                    return(TiltSide);

                case Direction.Up:
                    return(TiltUp);

                case Direction.Down:
                    return(TiltDown);
                }
                return(Neutral);
            });
            SmashUp.Charge.AddTransitionTo(SmashUp.Attack);
            SmashDown.Charge.AddTransitionTo(SmashDown.Attack);
            SmashSide.Charge.AddTransitionTo(SmashSide.Attack);
            TiltDown.AddTransitionTo(Crouch, Input(i => i.Movement.Direction == Direction.Down));
            new[] { Neutral, TiltUp, TiltDown, TiltSide, SmashUp.Attack, SmashDown.Attack, SmashSide.Attack }
            .AddTransitionTo(Idle);

            new [] { Fall, Jump, JumpAerial }
            .AddTransitions(Land, ctx => ctx.IsGrounded)
            // Aerial Attacks
            .AddTransitions <CharacterState, CharacterContext>(context => {
                var input = context.Input;
                if (!input.Attack.WasPressed)
                {
                    return(null);
                }
                switch (input.Movement.Direction)
                {
                case Direction.Right:
                    return(context.Direction >= 0f ? AerialForward : AerialBackward);

                case Direction.Left:
                    return(context.Direction >= 0f ? AerialBackward : AerialForward);

                case Direction.Up:
                    return(AerialUp);

                case Direction.Down:
                    return(AerialDown);
                }
                return(AerialNeutral);
            });
            new[] { AerialForward, AerialBackward, AerialDown, AerialUp, AerialNeutral }
            .AddTransitions(AerialAttackLand, ctx => ctx.IsGrounded)
            .AddTransitionTo(Fall);
            AerialAttackLand.AddTransitionTo(Idle);

            // Aerial Movement
            new [] { Idle, Walk, Dash, Run, RunTurn, RunBrake, CrouchStart, Crouch, CrouchEnd, Shield.Main }
            .AddTransitions(JumpStart, ctx => ctx.Input.Jump.WasPressed && ctx.CanJump);
            new[] { JumpStart, JumpAerial }.AddTransitionTo(Jump);
            new[] { Jump, Fall }.AddTransitions(JumpAerial, ctx => ctx.Input.Jump.WasPressed && ctx.CanJump)
            .AddTransitions(EscapeAir, Input(i => i.Shield.WasPressed));
            Jump.AddTransition(Idle, ctx => ctx.NormalizedStateTime >= 1.0f && ctx.IsGrounded)
            .AddTransition(Fall, ctx => ctx.NormalizedStateTime >= 1.0f && !ctx.IsGrounded);
            EscapeAir.AddTransitionTo(FallHelpless);
            new[] { Fall, FallHelpless, EscapeAir }.AddTransitions(Land, ctx => ctx.IsGrounded);
            Land.AddTransitionTo(Idle);

            Func <Func <PlayerInputContext, DirectionalInput>, Func <CharacterContext, bool> >
            movementContext = func => {
                return(ctx => !DirectionInput(Direction.Down)(ctx) &&
                       Input(i => Mathf.Abs(func(i).Value.x) > DirectionalInput.DeadZone)(ctx));
            };

            // Running States
            Idle.AddTransition(Dash, movementContext(i => i.Smash));
            Dash.AddTransitionTo(Idle, DirectionInput(Direction.Neutral));
            new[] { Dash, RunTurn }.AddTransitionTo(Run);
            Run.AddTransition(RunBrake, DirectionInput(Direction.Neutral));
            Run.AddTransition(RunTurn,
                              ctx => !Mathf.Approximately(Mathf.Sign(ctx.Input.Movement.Value.x), Mathf.Sign(ctx.Direction)));
            RunBrake.AddTransitionTo(Idle);

            // Ground Movement
            new[] { Idle, Walk, Run }
            .AddTransitions(CrouchStart, DirectionInput(Direction.Down))
            .AddTransitions(Fall, ctx => !ctx.IsGrounded);

            Idle.AddTransition(Walk, movementContext(i => i.Movement));
            Walk.AddTransition(Idle, DirectionInput(Direction.Neutral));

            // Crouching States
            CrouchStart.AddTransitionTo(Crouch);
            CrouchEnd.AddTransitionTo(Idle);
            new[] { CrouchStart, Crouch, CrouchEnd }.AddTransitions(Fall, ctx => !ctx.IsGrounded);
            Crouch.AddTransition(CrouchEnd, Input(i => i.Movement.Direction != Direction.Down));

            // Ledge States
            new[] { Idle, Fall, FallHelpless }.AddTransitions(LedgeGrab, ctx => ctx.State.IsGrabbingLedge);
            LedgeGrab.AddTransitionTo(LedgeIdle);
            LedgeIdle.AddTransition(LedgeRelease, ctx => !ctx.State.IsGrabbingLedge)
            .AddTransition(LedgeClimb, DirectionInput(Direction.Up))
            .AddTransition(LedgeJump, ctx => ctx.Input.Jump.WasPressed && ctx.CanJump)
            .AddTransition(LedgeAttack, Attack());
            LedgeJump.AddTransitionTo(Jump);
            new[] { LedgeRelease, LedgeClimb, LedgeEscape, LedgeAttack }
            .AddTransitions(Idle, ctx => ctx.NormalizedStateTime >= 1.0f && ctx.IsGrounded)
            .AddTransitions(Fall, ctx => ctx.NormalizedStateTime >= 1.0f && !ctx.IsGrounded);

            // Shielding
            Idle.AddTransition(Shield.On, Input(i => i.Shield.Current));
            Shield.On.AddTransition(Shield.Perfect, ctx => ctx.State.IsHit)
            .AddTransitionTo(Shield.Main);
            Shield.Main.AddTransition(Shield.Broken, ctx => ctx.State.ShieldDamage <= 0)
            .AddTransition(Shield.Off, Input(i => !i.Shield.Current));
            Shield.Off.AddTransitionTo(Idle);
            new[] { Shield.Broken, Shield.Stunned, Idle }.Chain();

            // Rolls/Sidesteps
            Shield.Main
            .AddTransition(EscapeForward, ctx => {
                if (ctx.Direction > 0f)
                {
                    return(DirectionalSmash(Direction.Right)(ctx));
                }
                else
                {
                    return(DirectionalSmash(Direction.Left)(ctx));
                }
            })
            .AddTransition(EscapeBackward, ctx => {
                if (ctx.Direction > 0f)
                {
                    return(DirectionalSmash(Direction.Left)(ctx));
                }
                else
                {
                    return(DirectionalSmash(Direction.Right)(ctx));
                }
            })
            .AddTransition(Escape, DirectionInput(Direction.Down));
            new[] { Escape, EscapeForward, EscapeBackward }.AddTransitionTo(Shield.Main);

            Builder.WithDefaultState(Idle);
            BuildCharacterController();
            return(Builder.Build());
        }