Ejemplo n.º 1
0
    void BeginBounceState(bounceDirection dir)
    {
        if (!dashState)
        {
            return;
        }
        hasDashDistance   = 0;
        dashState         = false;
        bounceOnWallState = true;
        bounceDir         = dir;
        int direction = dir == bounceDirection.right ? 1 : -1;

        //_velocity.x = Mathf.Sqrt(bounceForceX * bounceDragX * 2) * direction; bounceForceX为3左右
        //_velocity.y = Mathf.Sqrt(bounceForceY * -gravity * 2);bounceForceY为2左右
        _velocity.x = bounceForceX * direction;
        _velocity.y = bounceForceY;
    }
        void Awake()
        {
            // add our one-way platforms to our normal platform mask so that we can land on them from above
            hitByWall     = bounceDirection.none;
            platformMask |= oneWayPlatformMask;

            // cache some components
            transform   = GetComponent <Transform>();
            boxCollider = GetComponent <BoxCollider2D>();
            //rigidBody2D = GetComponent<Rigidbody2D>();

            // here, we trigger our properties that have setters with bodies
            skinWidth = _skinWidth;

            // we want to set our CC2D to ignore all collision layers except what is in our triggerMask
            for (var i = 0; i < 32; i++)
            {
                // see if our triggerMask contains this layer and if not ignore it
                if ((triggerMask.value & 1 << i) == 0)
                {
                    Physics2D.IgnoreLayerCollision(gameObject.layer, i);
                }
            }
        }
        /// <summary>
        /// we have to use a bit of trickery in this one. The rays must be cast from a small distance inside of our
        /// collider (skinWidth) to avoid zero distance rays which will get the wrong normal. Because of this small offset
        /// we have to increase the ray distance skinWidth then remember to remove skinWidth from deltaMovement before
        /// actually moving the player
        /// </summary>
        void moveHorizontally(ref Vector3 deltaMovement)
        {
            var isGoingRight     = deltaMovement.x > 0;
            var rayDistance      = Mathf.Abs(deltaMovement.x) + _skinWidth;
            var rayDirection     = isGoingRight ? Vector2.right : -Vector2.right;
            var initialRayOrigin = isGoingRight ? _raycastOrigins.bottomRight : _raycastOrigins.bottomLeft;


            Vector2 fetchedThingInitialOrigin = Vector2.zero;
            int     extraRays = 0;

            if (boxFetched)
            {
                extraRays = totalHorizontalRays;
                fetchedThingInitialOrigin = isGoingRight ? boxCastOrigins.bottomRight : boxCastOrigins.bottomLeft;
            }
            else if (circleFetched)
            {
                extraRays = 7;
            }

            for (var i = 0; i < totalHorizontalRays + extraRays; i++)
            {
                var ray = Vector2.zero;;
                if (i < totalHorizontalRays)
                {
                    ray = new Vector2(initialRayOrigin.x, initialRayOrigin.y + i * _verticalDistanceBetweenRays);
                }
                else
                {
                    if (boxFetched)
                    {
                        ray = new Vector2(fetchedThingInitialOrigin.x, fetchedThingInitialOrigin.y + (i - totalHorizontalRays) * _verticalDistanceBetweenRays);
                    }
                    else
                    {
                        float angle = Mathf.PI / (extraRays - 1) * (i - totalHorizontalRays);
                        ray = circleCastOrigins.center + new Vector2(circleCastOrigins.radius * Mathf.Sin(angle) * rayDirection.x, -circleCastOrigins.radius * Mathf.Cos(angle));
                    }
                }


                DrawRay(ray, rayDirection * rayDistance, Color.red);

                // if we are grounded we will include oneWayPlatforms only on the first ray (the bottom one). this will allow us to
                // walk up sloped oneWayPlatforms
                if (i == 0 && collisionState.wasGroundedLastFrame)
                {
                    _raycastHit = Physics2D.Raycast(ray, rayDirection, rayDistance, platformMask);
                }
                else
                {
                    _raycastHit = Physics2D.Raycast(ray, rayDirection, rayDistance, platformMask & ~oneWayPlatformMask);
                }

                if (_raycastHit)
                {
                    // the bottom ray can hit a slope but no other ray can so we have special handling for these cases
                    if (i == 0 && handleHorizontalSlope(ref deltaMovement, Vector2.Angle(_raycastHit.normal, Vector2.up)))
                    {
                        _raycastHitsThisFrame.Add(_raycastHit);
                        break;
                    }

                    // set our new deltaMovement and recalculate the rayDistance taking it into account
                    deltaMovement.x = _raycastHit.point.x - ray.x;
                    rayDistance     = Mathf.Abs(deltaMovement.x);


                    // remember to remove the skinWidth from our deltaMovement
                    if (isGoingRight)
                    {
                        deltaMovement.x     -= _skinWidth;
                        collisionState.right = true;
                        hitByWall            = bounceDirection.left;
                    }
                    else
                    {
                        deltaMovement.x    += _skinWidth;
                        collisionState.left = true;
                        hitByWall           = bounceDirection.right;
                    }

                    _raycastHitsThisFrame.Add(_raycastHit);

                    // we add a small fudge factor for the float operations here. if our rayDistance is smaller
                    // than the width + fudge bail out because we have a direct impact
                    if (rayDistance < _skinWidth + kSkinWidthFloatFudgeFactor)
                    {
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// attempts to move the character to position + deltaMovement. Any colliders in the way will cause the movement to
        /// stop when run into.
        /// </summary>
        /// <param name="deltaMovement">Delta movement.</param>
        public void move(Vector3 deltaMovement)
        {
            // save off our current grounded state which we will use for wasGroundedLastFrame and becameGroundedThisFrame
            collisionState.wasGroundedLastFrame = collisionState.below;

            // clear our state
            collisionState.reset();
            _raycastHitsThisFrame.Clear();
            _isGoingUpSlope = false;

            primeRaycastOrigins();


            // first, we check for a slope below us before moving
            // only check slopes if we are going down and grounded
            if (deltaMovement.y < 0f && collisionState.wasGroundedLastFrame)
            {
                handleVerticalSlope(ref deltaMovement);
            }

            // now we check movement in the horizontal dir
            if (deltaMovement.x != 0f)
            {
                moveHorizontally(ref deltaMovement);
            }

            // next, check movement in the vertical dir
            if (deltaMovement.y != 0f)
            {
                moveVertically(ref deltaMovement);
            }

            // move then update our state
            deltaMovement.z = 0;
            transform.Translate(deltaMovement, Space.World);

            //如果dash撞墙
            if (hitByWall != bounceDirection.none && OnWallBounceEvent != null)
            {
                OnWallBounceEvent(hitByWall);
                hitByWall = bounceDirection.none;
            }

            // only calculate velocity if we have a non-zero deltaTime
            if (Time.deltaTime > 0f)
            {
                velocity = deltaMovement / Time.deltaTime;
            }

            // set our becameGrounded state based on the previous and current collision state
            if (!collisionState.wasGroundedLastFrame && collisionState.below)
            {
                collisionState.becameGroundedThisFrame = true;
            }

            // if we are going up a slope we artificially set a y velocity so we need to zero it out here
            if (_isGoingUpSlope)
            {
                velocity.y = 0;
            }

            // send off the collision events if we have a listener
            if (onControllerCollidedEvent != null)
            {
                for (var i = 0; i < _raycastHitsThisFrame.Count; i++)
                {
                    onControllerCollidedEvent(_raycastHitsThisFrame[i]);
                }
            }

            ignoreOneWayPlatformsThisFrame = false;
        }