/// <summary> /// Launches a new ball in a direction between the negative and positive maxLaunchAngle with respect /// to the paddles transform up. A ball is only launched if a prefab with a ballcontroller is /// set up in the inspector. /// </summary> private void LaunchBall() { if (ball == null) { ball = Instantiate(ballPrefab); ball.transform.position = transform.position + transform.up * 0.5f; BallController ballController = ball.GetComponent <BallController>(); if (ballController != null) { ballController.Owner = this.gameObject; float angle = Random.Range(-maxLaunchAngle, maxLaunchAngle); Vector3 direction = Quaternion.AngleAxis(angle, transform.forward) * transform.up; ballController.SetDirection(direction); } } }
/// <summary> /// This is where the magic happens. The paddle has an affect on the ball depending on the /// paddle surface material. Since this method comes after fixed update the collision will /// already be resolved before this event. This event is therefore a correction of /// collision event. /// </summary> /// <param name="collision"></param> private void OnCollisionEnter2D(Collision2D collision) { BallController ball = collision.gameObject.GetComponent <BallController>(); if (ball != null) { Rigidbody2D ballBody = collision.rigidbody; if (ballBody != null) { ContactPoint2D contactPoint = collision.GetContact(0); // We check if the collision normal is equal to the paddles transform up. // This is the case where we can do fun stuff with the ball reflections // Note that the == operator for Vector2s and Vector3s is an // approximatly equal operator. if (contactPoint.normal == -(Vector2)transform.up) { // We find the position of the top center of the collider. This takes rotation // into consideration Vector2 topMiddle = paddleCollider.bounds.center + transform.up * paddleCollider.size.y / 2; // We find the distance between the contact point and the paddle top center Vector2 distance = topMiddle - contactPoint.point; // We find the signed length from the contact point. We must cast to vector3 to be able to find the sign. We use the // cross product to see if the contact point is to the left or right of the transform up. float signedLength = Mathf.Sign(Vector3.Cross((Vector3)distance, (Vector3)contactPoint.normal).z) * distance.magnitude; if (material != null) { // We calculate the new angles added by the collision point from the ball and the paddle velocity float posAngle = material.CalculateAngleToAddFromCollision(signedLength, paddleCollider.size.x / 2); // Calculate the new direction of the ball. Remember, the balls velocity is already reflected from the fixed update, so we // must add the angles in a way that is consistent with the outward velocity. Vector3 ballDirection = ballBody.velocity; Vector3 newDirection = Quaternion.AngleAxis(posAngle, transform.forward) * ballDirection; ball.SetDirection(newDirection); } } } } }