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; }