using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; using System.Collections; using System.Collections.Generic; // Zaroori: Script ka naam aur file ka naam same hona chahiye: "RacingGameSuperScript" public class RacingGameSuperScript : MonoBehaviour { // ========================================== // 1. GAME SETTINGS & REFERENCES // ========================================== [Header("--- Game References ---")] public Transform playerCar; // Player ki car body public Transform[] aiCars; // AI Cars ki list public Transform cameraTarget; // Camera follow target (Player ke andar) public Transform waypointContainer; // Empty object jiske bache waypoints hain [Header("--- UI References ---")] public GameObject mainMenuPanel; public GameObject gameplayPanel; public GameObject gameOverPanel; public Text speedText; public Text coinsText; public Text positionText; [Header("--- Mobile Controls (Assign UI Buttons) ---")] // In buttons par EventTrigger laga kar ye bools control honge public bool pressGas = false; public bool pressBrake = false; public bool pressLeft = false; public bool pressRight = false; // Internal States private bool isGameActive = false; private int coins = 0; private float raceTimer = 0f; // Singleton Instance public static RacingGameSuperScript Instance; void Awake() { Instance = this; SetupUI(); } void Update() { if (!isGameActive) return; // UI Updates if (playerCar != null) { float speed = playerCar.GetComponent().velocity.magnitude * 3.6f; speedText.text = Mathf.FloorToInt(speed) + " KM/H"; } raceTimer += Time.deltaTime; // Quick Restart (Back Key for Android) if (Input.GetKeyDown(KeyCode.Escape)) TogglePause(); } // ========================================== // 2. GAME LOGIC (MANAGER) // ========================================== public void StartGame() { isGameActive = true; mainMenuPanel.SetActive(false); gameplayPanel.SetActive(true); gameOverPanel.SetActive(false); // Initialize Player Car SetupCarPhysics(playerCar, false); // Initialize AI Cars foreach (Transform ai in aiCars) { SetupCarPhysics(ai, true); } } public void EndGame(bool win) { isGameActive = false; gameplayPanel.SetActive(false); gameOverPanel.SetActive(true); // Show Ads Logic here Debug.Log(win ? "You Won! +50 Coins" : "You Lost! Try Again"); if(win) coins += 50; SaveData(); } public void RestartGame() { SceneManager.LoadScene(SceneManager.GetActiveScene().name); } void SetupUI() { mainMenuPanel.SetActive(true); gameplayPanel.SetActive(false); gameOverPanel.SetActive(false); coins = PlayerPrefs.GetInt("Coins", 0); coinsText.text = "Coins: " + coins; } void SaveData() { PlayerPrefs.SetInt("Coins", coins); PlayerPrefs.Save(); } void TogglePause() { // Simple pause toggle Time.timeScale = Time.timeScale == 0 ? 1 : 0; } // ========================================== // 3. COMPONENT SETUP HELPER // ========================================== void SetupCarPhysics(Transform carObj, bool isAI) { // Agar pehle se components hain to hata do ya skip karo if (carObj.GetComponent() == null) { SimpleCarController controller = carObj.gameObject.AddComponent(); controller.isAI = isAI; // Basic physics setup Rigidbody rb = carObj.GetComponent(); if(rb == null) rb = carObj.gameObject.AddComponent(); rb.mass = 1500; rb.drag = 0.05f; rb.angularDrag = 0.05f; } } } // ========================================== // 4. THE CAR CONTROLLER LOGIC (Physics) // ========================================== public class SimpleCarController : MonoBehaviour { public bool isAI = false; [Header("Settings")] public float motorForce = 1500f; public float steerAngle = 30f; public float brakeForce = 3000f; public float antiRoll = 5000f; // Wheel Colliders (Code will find them automatically if named correctly) public WheelCollider FL, FR, RL, RR; private Rigidbody rb; private RacingGameSuperScript gameManager; // AI Variables private List waypoints; private int currentWaypoint = 0; void Start() { rb = GetComponent(); gameManager = RacingGameSuperScript.Instance; // Auto-Find Wheel Colliders (Ensure you name them FL, FR, RL, RR in Editor) WheelCollider[] wheels = GetComponentsInChildren(); if(wheels.Length >= 4) { FL = wheels[0]; FR = wheels[1]; RL = wheels[2]; RR = wheels[3]; } // Stabilize Car (Lower Center of Mass) rb.centerOfMass = new Vector3(0, -0.5f, 0); // AI Setup if (isAI && gameManager.waypointContainer != null) { waypoints = new List(); foreach(Transform t in gameManager.waypointContainer) waypoints.Add(t); } } void FixedUpdate() { float inputGas = 0f; float inputSteer = 0f; bool inputBrake = false; if (isAI) { // --- AI LOGIC --- if (waypoints != null && waypoints.Count > 0) { Vector3 target = waypoints[currentWaypoint].position; Vector3 relativeVector = transform.InverseTransformPoint(target); inputSteer = (relativeVector.x / relativeVector.magnitude); inputGas = 1f; // Always accelerator // Waypoint Distance Check if (Vector3.Distance(transform.position, target) < 10f) { currentWaypoint = (currentWaypoint + 1) % waypoints.Count; } } } else { // --- PLAYER MOBILE INPUT --- if (gameManager.pressGas) inputGas = 1f; if (gameManager.pressLeft) inputSteer = -1f; if (gameManager.pressRight) inputSteer = 1f; if (gameManager.pressBrake) inputBrake = true; // Keyboard Override for Editor if (Application.isEditor && inputGas == 0 && inputSteer == 0) { inputGas = Input.GetAxis("Vertical"); inputSteer = Input.GetAxis("Horizontal"); inputBrake = Input.GetKey(KeyCode.Space); } } MoveCar(inputGas, inputSteer, inputBrake); } void MoveCar(float gas, float steer, bool brake) { if (RL == null || RR == null) return; // Safety check // Apply Motor RL.motorTorque = gas * motorForce; RR.motorTorque = gas * motorForce; // Apply Steer FL.steerAngle = steer * steerAngle; FR.steerAngle = steer * steerAngle; // Apply Brake float currentBrake = brake ? brakeForce : 0f; FL.brakeTorque = currentBrake; FR.brakeTorque = currentBrake; RL.brakeTorque = currentBrake; RR.brakeTorque = currentBrake; // Anti-Roll Bar Logic (Keeps car stable) ApplyAntiRoll(FL, FR); ApplyAntiRoll(RL, RR); } void ApplyAntiRoll(WheelCollider WL, WheelCollider WR) { WheelHit hit; float travelL = 1.0f; float travelR = 1.0f; bool groundedL = WL.GetGroundHit(out hit); if (groundedL) travelL = (-WL.transform.InverseTransformPoint(hit.point).y - WL.radius) / WL.suspensionDistance; bool groundedR = WR.GetGroundHit(out hit); if (groundedR) travelR = (-WR.transform.InverseTransformPoint(hit.point).y - WR.radius) / WR.suspensionDistance; float antiRollForce = (travelL - travelR) * antiRoll; if (groundedL) rb.AddForceAtPosition(WL.transform.up * -antiRollForce, WL.transform.position); if (groundedR) rb.AddForceAtPosition(WR.transform.up * antiRollForce, WR.transform.position); } } // ========================================== // 5. CAMERA FOLLOW SCRIPT // ========================================== public class SimpleCameraFollow : MonoBehaviour { public Transform target; public float distance = 6.0f; public float height = 2.5f; public float damping = 5.0f; void Start() { // Auto find player if target is null if(target == null && RacingGameSuperScript.Instance != null) { target = RacingGameSuperScript.Instance.playerCar; } } void LateUpdate() { if (!target) return; float wantedRotationAngle = target.eulerAngles.y; float wantedHeight = target.position.y + height; float currentRotationAngle = transform.eulerAngles.y; float currentHeight = transform.position.y; currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, damping * Time.deltaTime); currentHeight = Mathf.Lerp(currentHeight, wantedHeight, damping * Time.deltaTime); Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0); Vector3 pos = target.position; pos -= currentRotation * Vector3.forward * distance; pos.y = currentHeight; transform.position = pos; transform.LookAt(target); } }