PaddleScript.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using UnityEngine;
  2. using UnityEngine.InputSystem;
  3. [RequireComponent(typeof(Collider2D))]
  4. [RequireComponent(typeof(Rigidbody2D))]
  5. public class PaddleScript : MonoBehaviour
  6. {
  7. [Header("Movement")]
  8. [SerializeField] private float moveSpeed = 10f;
  9. [Header("Bounds")]
  10. [Tooltip("Extra gap between the paddle edge and the camera edge.")]
  11. [SerializeField] private float edgePadding = 0.1f;
  12. private float _minX;
  13. private float _maxX;
  14. private float _halfWidth;
  15. private bool _useMouse = true;
  16. void Awake()
  17. {
  18. // Paddle is player-driven via transform — kinematic prevents physics forces from interfering.
  19. GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
  20. }
  21. void Start()
  22. {
  23. _halfWidth = GetComponent<Collider2D>().bounds.extents.x;
  24. // Derive horizontal limits from the camera viewport so the paddle never leaves the screen.
  25. Camera cam = Camera.main;
  26. float distToCamera = Mathf.Abs(cam.transform.position.z);
  27. _minX = cam.ViewportToWorldPoint(new Vector3(0f, 0f, distToCamera)).x + _halfWidth + edgePadding;
  28. _maxX = cam.ViewportToWorldPoint(new Vector3(1f, 0f, distToCamera)).x - _halfWidth - edgePadding;
  29. }
  30. void Update()
  31. {
  32. var keyboard = Keyboard.current;
  33. var mouse = Mouse.current;
  34. float keyInput = 0f;
  35. if (keyboard != null)
  36. {
  37. if (keyboard.aKey.isPressed || keyboard.leftArrowKey.isPressed) keyInput -= 1f;
  38. if (keyboard.dKey.isPressed || keyboard.rightArrowKey.isPressed) keyInput += 1f;
  39. }
  40. // Any keyboard movement disables mouse; any mouse click re-enables mouse.
  41. if (Mathf.Abs(keyInput) > 0.01f)
  42. _useMouse = false;
  43. else if (mouse != null && mouse.leftButton.wasPressedThisFrame)
  44. _useMouse = true;
  45. Vector3 pos = transform.position;
  46. if (!_useMouse && Mathf.Abs(keyInput) > 0.01f)
  47. {
  48. // Keyboard: direct movement at moveSpeed.
  49. pos.x += keyInput * moveSpeed * Time.deltaTime;
  50. }
  51. else if (_useMouse && mouse != null)
  52. {
  53. // Mouse: smoothly move toward the cursor's world X at moveSpeed.
  54. Camera cam = Camera.main;
  55. Vector2 mouseScreen = mouse.position.ReadValue();
  56. Vector3 mouseWorld = cam.ScreenToWorldPoint(
  57. new Vector3(mouseScreen.x, mouseScreen.y, Mathf.Abs(cam.transform.position.z)));
  58. pos.x = Mathf.MoveTowards(pos.x, mouseWorld.x, moveSpeed * Time.deltaTime);
  59. }
  60. pos.x = Mathf.Clamp(pos.x, _minX, _maxX);
  61. transform.position = pos;
  62. }
  63. private void OnCollisionEnter2D(Collision2D collision)
  64. {
  65. if (!collision.gameObject.CompareTag("Ball"))
  66. return;
  67. Rigidbody2D ballRb = collision.rigidbody;
  68. if (ballRb == null)
  69. return;
  70. // Map hit position to [-1, 1]: -1 = left edge, 0 = centre, +1 = right edge.
  71. float hitOffset = (collision.transform.position.x - transform.position.x) / _halfWidth;
  72. hitOffset = Mathf.Clamp(hitOffset, -1f, 1f);
  73. // Preserve the ball's current speed so movement effects still apply.
  74. BallScript ballScript = collision.gameObject.GetComponent<BallScript>();
  75. float speed = ballScript != null ? ballScript.GetCurrentSpeed() : 10f;
  76. // A centre hit goes straight up; edge hits angle up to 75 degrees to either side.
  77. float angle = hitOffset * 75f * Mathf.Deg2Rad;
  78. ballRb.linearVelocity = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * speed;
  79. }
  80. }