namespace UnityCheatSheet { using System; // Wird für Events / Actions benötigt using System.Collections; // Wird für Coroutinen benötigt using UnityEngine; // Der Haupt-Namespace für fast alles in Unity // Das Attribut RequireComponent zwingt Unity dazu, automatisch einen Rigidbody // an das GameObject zu hängen, sobald dieses Skript hinzugefügt wird. [RequireComponent(typeof(Rigidbody))] public class UnityReferenz : MonoBehaviour { // ======================================================================== // 1. VARIABLEN & SICHTBARKEIT (Attribute für den Inspektor) // ======================================================================== [Header("Basis-Variablen")] [Tooltip("Das ist ein Tooltip. Er erscheint, wenn man mit der Maus im Editor darüber fährt.")] public int lebenspunkte = 100; // Public: Von überall sichtbar UND im Editor sichtbar [SerializeField] private float geschwindigkeit = 5.5f; // Private + SerializeField: Nur in diesem Skript nutzbar, ABER im Editor einstellbar! (Best Practice) [Range(0f, 1f)] public float lautstaerke = 0.5f; // Erzeugt einen schönen Schieberegler im Unity Editor [HideInInspector] public bool istVersteckt = true; // Public, aber im Editor unsichtbar (für interne Logik) [Header("Referenzen zu anderen Dingen")] [SerializeField] private GameObject meinPrefab; // Referenz auf ein Prefab (z.B. ein Schuss oder Gegner) [SerializeField] private Transform zielPosition; // Referenz auf eine Position in der Welt (Transform) [SerializeField] private Renderer meinRenderer; // Referenz auf eine visuelle Komponente // Private Variablen (weder von außen noch vom Editor erreichbar) private Rigidbody meinRigidbody; private float zeitSeitStart = 0f; // ======================================================================== // 2. UNITY LEBENSZYKLUS (Event-Methoden, die Unity automatisch aufruft) // ======================================================================== // Awake wird als ALLERERSTES aufgerufen, noch bevor das Spiel richtig losgeht. // Hier holt man sich Referenzen auf die eigenen Komponenten. void Awake() { // Holt den Rigidbody, der auf DIESEM GameObject liegt. meinRigidbody = GetComponent(); if (meinRigidbody == null) { Debug.LogError("Hilfe! Hier fehlt ein Rigidbody!"); // Schreibt einen Fehler in die Konsole } } // Start wird aufgerufen, bevor das erste Update läuft (für Initialisierungen). void Start() { Debug.Log("Das Spiel ist gestartet! Hallo von: " + gameObject.name); // Farbe ändern als Test if (meinRenderer != null) { meinRenderer.material.color = Color.blue; } // Startet eine asynchrone Hintergrund-Schleife (Coroutinen, siehe unten) StartCoroutine(MeinTimer()); } // Update wird JEDEN FRAME aufgerufen. // Achtung: Wenn das Spiel mit 60 FPS läuft, läuft das hier 60x pro Sekunde! void Update() { // 1. Timer hochzählen mit Time.deltaTime (Zeit, die seit dem letzten Frame vergangen ist) zeitSeitStart += Time.deltaTime; // 2. Input abfragen AbfrageInput(); } // FixedUpdate wird in festen Zeitintervallen aufgerufen (Standard: 50x pro Sekunde). // ALLES was mit Physik zu tun hat, MUSS hier rein, NICHT in Update! void FixedUpdate() { // Beispiel: Wir schieben das Objekt stetig nach vorne // meinRigidbody.AddForce(Vector3.forward * geschwindigkeit); } // ======================================================================== // 3. EIGENE METHODEN: INPUT & BEWEGUNG // ======================================================================== private void AbfrageInput() { // TASTENABFRAGE (Einmaliges Drücken) if (Input.GetKeyDown(KeyCode.Space)) { Springen(); } // TASTENABFRAGE (Gedrückt halten) if (Input.GetKey(KeyCode.W)) { // Bewege das Objekt direkt (ohne Physik) nach vorne // transform.Translate(Vector3.forward * geschwindigkeit * Time.deltaTime); } // MAUSABFRAGE (0 = Links, 1 = Rechts, 2 = Mitte) if (Input.GetMouseButtonDown(0)) { SpawnObjekt(); } } private void Springen() { // Wirft das Objekt physikalisch in die Luft meinRigidbody.AddForce(Vector3.up * 300f); Debug.Log("Hüpf!"); } // ======================================================================== // 4. INSTANZIIEREN (Spawnen) & ZERSTÖREN // ======================================================================== public void SpawnObjekt() { if (meinPrefab == null) return; // Abbruch, wenn kein Prefab hinterlegt ist // Instantiate erstellt eine Kopie des Prefabs an unserer aktuellen Position GameObject neuesObjekt = Instantiate(meinPrefab, transform.position, Quaternion.identity); // Wir können das neue Objekt direkt benennen neuesObjekt.name = "Klon_von_" + gameObject.name; // Wir können das Objekt nach 5 Sekunden automatisch zerstören lassen Destroy(neuesObjekt, 5f); } // ======================================================================== // 5. PHYSIK & KOLLISIONEN // ======================================================================== // Wird ausgelöst, wenn ein anderes Objekt (mit Collider und Rigidbody) uns RAMMT void OnCollisionEnter(Collision collision) { // Checken, wen wir da gerammt haben (anhand von Tags) if (collision.gameObject.CompareTag("Player")) { Debug.Log("Autsch! Der Spieler hat mich gerammt!"); // So können wir z.B. Leben abziehen: lebenspunkte -= 10; } } // Wird ausgelöst, wenn ein Objekt eine unsichtbare Lichtschranke durchquert // (Collider muss auf "Is Trigger" gestellt sein) void OnTriggerEnter(Collider other) { Debug.Log("Etwas ist in meinen Trigger gelaufen: " + other.name); } // ======================================================================== // 6. RAYCASTING (Laser-Strahlen schießen) // ======================================================================== private void SchiesseLaser() { RaycastHit hit; // Schießt einen Strahl von unserer Position nach vorne, 100 Meter weit if (Physics.Raycast(transform.position, transform.forward, out hit, 100f)) { Debug.Log("Ich schaue genau auf: " + hit.collider.name); // Wenn man auf das getroffene Objekt zugreifen will: // hit.collider.gameObject.GetComponent().MachWas(); } } // ======================================================================== // 7. COROUTINEN (Dinge, die Zeit brauchen / Warten) // ======================================================================== // Eine Methode vom Typ IEnumerator läuft parallel und kann pausiert werden private IEnumerator MeinTimer() { Debug.Log("Timer gestartet..."); // Pausiert die Ausführung dieser Methode für exakt 2 Sekunden yield return new WaitForSeconds(2f); Debug.Log("2 Sekunden sind vorbei!"); // Endlos-Schleifen sind hier okay, WEIL sie mit yield return pausiert werden! while (lebenspunkte > 0) { // Mache jede Sekunde einen Tick Schaden // lebenspunkte -= 1; yield return new WaitForSeconds(1f); } } } }