Logo

Főoldal

Blog

Elmélet

3D Studio

Adatvédelmi nyilatkozat

GY.I.K.

Házirend

Szerző: Marosi Csaba / marosi.csaba@3d-studio.hu

DiscordGitHubLinkedIn
Developedia
Developedia
/Feladatgyűjtemény
Feladatgyűjtemény
/Fizikai szimuláció
Fizikai szimuláció
Fizikai szimuláció

Fizikai szimuláció

‣
Gravitáció szimuláció

Írj komponenst, lefelé gyorsít egy objektumot [SerializeField] változóban beállított gyorsulás érték szerint.

A beállított gyorsulás azt adja meg, mennyi tud változni a sebesség másodpercenként.

Ha a GameObject eléri a 0 magasságot, megáll.

A beállított gyorsulás azt adja meg, mennyi tud változni a sebesség másodpercenként.

A megoldáshoz ne használj RigidBody-t!

‣
Illusztráció
image
‣
Megoldás
‣
Gyorsulás

Írj komponenst, ami x tengelyen halad. Ha egy [SerializeField] változóban megadunk egy cél X értéket, akkor az objektum odamegy!

A komponensnek be kell állítani egy-egy [SerializeField] változóban egy gyorsulásértéket és egy maximális haladási sebességet.

A beállított max sebesség azt adja meg, legfeljebb mekkora utat tehet meg egy másodperc alatt a GameObject.

A beállított gyorsulás azt adja meg, mennyi tud változni a sebesség másodpercenként.

Ha a GameObject eléri a célját, akkor megáll.

A megoldáshoz ne használj RigidBody-t!

‣
Illusztráció
image
‣
Megoldás
‣
Gyorsulás és lassulás

Írj komponenst, [SerializeField] változóban megadhatunk:

  • egy másik Transform-ot, mint célt
  • egy gyorsulás- és
  • lassulásértéket
  • valamint egy távolság határértéket.

A komponenst feladata, hogy megpróbálja határértéken belülre közelíteni a cél Transform-hoz.

Ha a cél a határértéken kívül van, akkor a cél irányába gyorsul.

Ha a cél a határértéken belül van, akkor akkor elkezd lassulni.

A beállított gyorsulás és lassulás azt adja meg mennyi tud változni a sebességvektor másodpercenként.

A határértéket rajzold ki gizmóval!

A megoldáshoz ne használj RigidBody-t!

‣
Illusztráció
image
‣
Megoldás
‣
Szöcske ugrás

Írj szöcske (Grasshopper) komponenst, ami gombnyomásra ugrál a lenyomott gomb által megadott irányba!

A komponensed nem mehet lejjebb 0 magasságnál!

Ha megnyomja a felhasználó a kurzorgombok egyikét, a komponens ugrik egyet a megfelelő irányba!

Az ugrás úgy történik, hogy kap egy függőleges sebességet az objektum és egy vízszinteset is a megadott irányba. A függőleges sebesség folyamatosan csökken, a vízszintes állandó marad addig a pontig, amig az y koordináta nagyobb, mint 0.

A megoldáshoz ne használj RigidBody-t!

A levegőben nem tud ugrani a szöcske.

Függőleges irányban gyakorlatilag gravitáció szimulációt kell írni. (Könnyebb, mint gondolnád)

‣
Illusztráció
image
‣
Megoldás
‣
Flappy Physics

Írj komponenst, a Flappy Bird mintájára.

Ha a játékos megnyomja az ugrás gombot, az objektum ugrik egyet és elkezd esni.

Újabb gombnyomásra újabb lökést kap az objektum függőleges irányban.

Ha az objektum elér egy maximum vagy minimum magasságot, akkor kiírja, hogy GAME OVER és vissza teszi az objektumot a két határérték közé.

Ha megnyomja a felhasználó az ugrás gombot, újra kezdődik a játék.

Gravitáció szimulációt kell írni!

A megoldáshoz ne használj RigidBody-t!

‣
Illusztráció
image
‣
Megoldás
‣
Asteroids

Tanulmányozd az Asteroids című 1979 by Atari arcade játékban az űrhajó mozgását.

Írj komponenst, ami egy objektumot annak mintájára mozgat.

A megoldáshoz ne használj RigidBody-t!

‣
Illusztráció (Próbáld ki a játékot!)

(Vonatkoztass el attól, hogy a hajó átteleportál a falon. Ez nem a feladat része.)

‣
Megoldás
‣
Három test probléma

Írj bolygó (Planet) komponenst, aminek gravitációs hatása van kettő másik beállításban megadható bolygóra. Minden bolygónak van egy beállítható tömege is.

Minden test vonzza a másik kettő testet a Newtoni tömegvonzás törvénye szerint.

A megoldáshoz ne használj RigidBody-t!

‣
Mögöttes fizika

Newton féle tömegvonzási törvény:

F=G⋅m1⋅m2r2F = G⋅ \frac{m_1 ⋅ m_2} {r^2}F=G⋅r2m1​⋅m2​​
‣
Ahol:

FFF : Erő

m1m_1m1​ : Egyik test tömege

m2m_2m2​ : Másik Test tömege

rrr : két test távolsága

GGG : Newton féle gravitációs konstans

Értéke: 6.67430⋅10−11N⋅m2⋅kg26.67430 ⋅ 10^{−11} N⋅m2⋅kg^26.67430⋅10−11N⋅m2⋅kg2

Ti más értéket használjatok! Olyat, amivel a mozgás látszik kis számokon is.

Szóval az erő, ami két bolygó hat közt (egyikre és másikra is) az egyenesen arányos mind két bolygó tömegével, fordítottan arányos a kettő közti távolsággal és függ egy Newton gravitációs állandójától.

És mivel F=m⋅aF = m ⋅ aF=m⋅a (Newton második törvénye) (aaa : gyorsulás)

Ezért a gyorsulás egy testen: a=G⋅m2/r2a = G⋅m_2 / r^2a=G⋅m2​/r2

Tehát egy testen ható gyorsulás, amit egy másik test okoz rajta egyenesen arányos a másik test tömegével, fordítottan arányos a kettő közti távolság négyzetével és függ egy Newton gravitációs állandójától.

(Ha akarsz, oszthatsz a távolsággal a távolság négyzete helyett.)

(G értékét magad válaszd meg érzés szerint!)

Ha több test igy egyszerre hat egy testre a rajta ható eredő gyorsulásvektor a több egyedülálló gyorsulásvektor összege.

‣
Megoldás
‣
Bolygómozgás

Írj bolygó (Planet) komponenst, aminek gravitációs hatása van minden többi bolygóra.

Minden bolygónak van egy beállítható tömege.

Minden test vonzza a többi testet a Newtoni tömegvonzás törvénye szerint.

A megoldáshoz ne használj RigidBody-t!

‣
Mögöttes fizika

Newton féle tömegvonzási törvény:

F=G⋅m1⋅m2r2F = G⋅ \frac{m_1 ⋅ m_2} {r^2}F=G⋅r2m1​⋅m2​​
‣
Ahol:

FFF : Erő

m1m_1m1​ : Egyik test tömege

m2m_2m2​ : Másik Test tömege

rrr : két test távolsága

GGG : Newton féle gravitációs konstans

Értéke: 6.67430⋅10−11N⋅m2⋅kg26.67430 ⋅ 10^{−11} N⋅m2⋅kg^26.67430⋅10−11N⋅m2⋅kg2

Ti más értéket használjatok! Olyat, amivel a mozgás látszik kis számokon is.

Szóval az erő, ami két bolygó hat közt (egyikre és másikra is) az egyenesen arányos mind két bolygó tömegével, fordítottan arányos a kettő közti távolsággal és függ egy Newton gravitációs állandójától.

És mivel F=m⋅aF = m ⋅ aF=m⋅a (Newton második törvénye) (aaa : gyorsulás)

Ezért a gyorsulás egy testen: a=G⋅m2/r2a = G⋅m_2 / r^2a=G⋅m2​/r2

Tehát egy testen ható gyorsulás, amit egy másik test okoz rajta egyenesen arányos a másik test tömegével, fordítottan arányos a kettő közti távolság négyzetével és függ egy Newton gravitációs állandójától.

(Ha akarsz, oszthatsz a távolsággal a távolság négyzete helyett.)

(G értékét magad válaszd meg érzés szerint!)

Ha több test igy egyszerre hat egy testre a rajta ható eredő gyorsulásvektor a több egyedülálló gyorsulásvektor összege.

‣
Segítség

A többi bolygó megtalálására használhatsz FindObjectsOfType függvényt

‣
Illusztráció

A megoldásomban az erő a távolsággal fordítottan arányos és nem a távolság négyzetével, mint az a valós fizikában lenne.

Ezzel érem el, hogy ne parittyázzák könnyedén ki egymást a bolygók.

Kirajzolom a sebességvektort is. Ez nem volt feladat.

A bolygók mérete reprezentálja a tömegüket. Ez nem volt feladat.

image
‣
Megoldás
‣
Egyszínű Rigidbody-k

Írj metódust, ami egy Material-t kap paraméterben és visszaadja Rigidbody-k egy listáját.

A lista az összes olyan a Scene-ben megtalálható Rigidbody-t adja vissza, amikhez tartozik MeshRenderer és materiáljuk megegyezik a paraméterben megadottal!

‣
Megoldás
List<Rigidbody> RigidbodiesWithTheSameMaterial(Material material)
{
    var result = new List<Rigidbody>();
    Rigidbody[] all = FindObjectsOfType<Rigidbody>();
    foreach (Rigidbody rb in all)
    {
        MeshRenderer mr = rb.GetComponent<MeshRenderer>();
        if (mr!= null && mr.material == material)
        {
            result.Add(rb);
        }
    }
    return result;
}
‣
Mire kattintok?

Írj komponenst, ami kiírja az objektum nevét, amire kattint a felhasználó az egérrel.

‣
Megoldás
‣
Lézer célzó

Írj komponenst, ami egy sugarat lő (Raycasting) saját pozíciójából lokális előre irányába!

A komponensnek [SerializeField] beállításként megadható GameObject-ek egy tömbje.

Ha a sugárvetés célt talált, akkor tömb elemeit felsorakoztatja a célzás és találat pontjai közé egyenlő távolságra. Ha a sugárvetés nem talált célt, a tömb elemeit inaktiválja!

Lehessen a komponensnek beállítani maximális távolságot!

A sugarat Gizmóval rajzold ki!

‣
Illusztráció
image
‣
Megoldás
‣
Mágneses monopol

Írj olyan mágnes (Magent) komponenst, aminek beállításai közt szerepel, a pólusú (pozitív vagy negatív) és hogy mekkora az ereje.

Az azonos pólusú elemek taszítják egymást ez ellenkezők vonzzák egymást.

A vonzás mértéke a távolsággal csökken, a mágnesek erejével nő.

A megoldáshoz használhattok Rigidbody-t.

‣
Illusztráció

2D-ben oldottam meg a feladatot.

Megjelenítésre SpriteRenderer-t, ütközéshez CircleCollider-t használtam.

A megoldásomban a vonzó/ taszító erő egyenesen arányos mindkét pólusok erejével és fordítottan arányos a távolság négyzetével.

‣
Megoldás
‣
Dobbantó

Írj komponenst, ami ha valahova kattintunk az egérrel ott “dobbant” egyet.

A dobbantás függőleges felfelé irányba meglöki a Rigidbody-kat.

A dobbantásnak van egy hatótáv, amin belül hat.

A hatótáv széléhez közeledve gyengül a lökés ereje.

‣
Illusztráció
‣
Megoldás
‣
Gravitáció módosítók

Írj komponenst, ami saját maga körül egy beállítható sugarú gömbben módosítja a gravitációt.

A gravitáció módosításának mértéke és iránya egy vektor-ként állítható be.

‣
Illusztráció

A vizualizáció nem a feladat része

‣
Megoldás
‣
Optimálisabb Megoldás
‣
Időzített bomba

Készíts bombát, ami egy idő letelte után ellöki a körülötte lévő RigidBody-kat és megsemmisíti önmagát.

A robbanásnak van egy beállítható ereje és hatótávolsága.

A hatótáv széléhez közeledve gyengül a lökés ereje.

‣
Illusztráció
‣
Megoldás
‣
Lézer célzó 2

Írj komponenst, ami egy sugarat lő (Raycasting) saját pozíciójából lokális előre irányába!

A komponensnek [SerializeField] beállításként megadható egy GameObject, mint prototípus.

Ha a sugárvetés célt talált, akkor az objektum másolatait beteszi a célzás és találat pontja közé, úgy hogy az elemek beállítható d távolságban legyenek egymástól. Ha a sugárvetés nem talált célt, nem látszanak a célzó pontok!

Lehessen a komponensnek beállítani maximális távolságot!

A sugarat Gizmóval rajzold ki!

‣
Illusztráció
image
‣
Megoldás
‣
Ugrás a kattintás felé

Írj komponenst, ami ha valahová kattint a játékos az egérrel, megpróbál a kattintás irányába ugrani!

Az ugrást úgy oldd meg, hogy erőt adsz RigidBody-hoz!

Az ugrás mindig függőlegesen mindig 45-fokos szögben történjen!

Az ugrás sebessége beállítható legyen!

‣
Megoldás:
‣
Ballisztikus pálya

Készíts komponenst, ami kirajzol egy ballisztikus pályát. Gizmóval vagy Line Renderer segítségével.

A ballisztikus pálya egy megadott sebességgel, megadott irányba elhajított test pontjainak összessége. (Nem kell minden pontot megadni, csak egy beállítható sűrűségű sorozatát a pontoknak.)

A pálya kiszámítása pillanatszerű legyen! A pálya kiszámításához nem kell valóban eldobni egy testet vagy valóban kivárni a szimuláció idejét.

A beállítható adatok:

Vector3 gravity; Mekkora a gravitációs gyorsulás mértéke és iránya?

Vector3 velocity = 5f; Kezdősebesség mértéke és iránya. Az irányra használható a kapcsolódó Transform komponens előre iránya.

Vector3 startPosition; Kiindulási pozíció. Használható a kapcsolódó Transform komponens pozíciója.

float maxTime = 2f; Milyen “hosszú” legyen a szimulált pálya időben megadva. Eldobástól számítva ennyi ideig szimulálunk.

float timeStep = 0.1f; A szimuláció legkisebb időegysége. (Olyasmi, mint a Time.deltaTime)

float drag = 0.1f; OPCIONÁLIS Közegellenállás. A tanult módon számítható.

‣
Illusztráció:
image
‣
Megoldás
using UnityEngine;

public class GravityApplier : MonoBehaviour
{ 
    [SerializeField] float acceleration; // Gyorsulás
    
    float currentSpeed = 0;              // Jelenlegi sebesség

    // A gyorsulást érdemes a FixedUpdate-ben kezelni
    void FixedUpdate()
    {
        // Gyorsulás (Sebesség módosítása):
        currentSpeed += acceleration * Time.fixedDeltaTime;
    }
    
    // Az elmozdulást érdemes az Update-ben kezelni
    void Update()
    {
        Vector3 position = transform.position;  // Jelenlegi pozíció
        float currentY = position.y;            // Jelenlegi pozíció Y értéke

        // Mozgás:
        float move = currentSpeed * Time.deltaTime;
        if(currentY > 0) // Ha elér a célhoz
        {
            position.y = 0;
            transform.position = position;
            currentSpeed = 0;
        }
        else // Ha nam ér el a célhoz
        {
            position.y -= move;
            transform.position = position;
        }
    }
}
using UnityEngine;

public class AcceleratingMover : MonoBehaviour
{
    [SerializeField] float targetX;      // Cél
    [SerializeField] float maxSpeed;     // Max sebesség
    [SerializeField] float acceleration; // Gyorsulás
    
    float currentSpeed = 0;              // Jelenlegi sebesség

    // A gyorsulást érdemes a FixedUpdate-ben kezelni:
    void FixedUpdate()
    {
        float currentX =  transform.position.x; // Jelenlegi pozíció X értéke
        float distance = targetX - currentX;    // Távolság a célhoz
        
        // Gyorsulás (Sebesség módosítása):
        currentSpeed +=
					Mathf.Sign(distance) * acceleration * Time.fixedDeltaTime;
        // Max sebesség korlátozása:
        currentSpeed = Mathf.Clamp(currentSpeed, -maxSpeed, maxSpeed);
    }
    
    // Az elmozdulást érdemes az Update-ben kezelni:
    void Update()
    {
        Vector3 position = transform.position;  // Jelenlegi pozíció
        float currentX = position.x;            // Jelenlegi pozíció X értéke
        float distance = targetX - currentX;    // Távolság a célhoz 

        // Mozgás:
        float move = currentSpeed * Time.deltaTime;
        if(Mathf.Abs(move) > Mathf.Abs(distance)) // Ha elér a célhoz
        {
            position.x = targetX;
            transform.position = position;
            currentSpeed = 0;
        }
        else // Ha nam ér el a célhoz
        {
            position.x += move;
            transform.position = position;
        }
    }
}
using UnityEngine;

public class AccelerateAndDecelerate : MonoBehaviour
{
    [SerializeField] Transform target;      // Cél
    [SerializeField] float acceleration;    // Gyorsulás
    [SerializeField] float deceleration;    // Lassulás
    [SerializeField] float limitDistance;   // Távolság határérték
    
    Vector3 velocity;   // Sebességvektor
    
    // A gyorsulást és lassulást érdemes a FixedUpdate-ben kezelni:
    void FixedUpdate()
    {
        float distance = Vector3.Distance(target.position, transform.position);
        Vector3 direction = (target.position - transform.position).normalized;
         
        if (distance > limitDistance)   // Gyorsulás:
            velocity += acceleration * Time.fixedDeltaTime * direction;
        else    // Lassulás:
            velocity = Vector3.MoveTowards(
                velocity, 
                Vector3.zero, 
                deceleration * Time.fixedDeltaTime);
    }

    // Az elmozdulást érdemes az Update-ben kezelni:
    void Update()
    {
        transform.position += velocity * Time.deltaTime;
    }
    
    // Gizmo kirajzolása:
    void OnDrawGizmos()
    { 
        if(target == null) return;

        Gizmos.color = new Color(1, 0, 0, 0.5f); // Átlátszó piros
        Gizmos.DrawWireSphere(target.position, limitDistance);
    }
}
using UnityEngine;

public class Grasshopper : MonoBehaviour
{
    [SerializeField] float jumpVelocityVertical;    // Függőleges ugrási sebesség
    [SerializeField] float jumpVelocityHorizontal;  // Vízszintes ugrási sebesség
    [SerializeField] float acceleration;            // gravitációs gyorsulás
    
    Vector3 velocity;   // Sebességvektor
    
    // A gyorsulást és lassulást érdemes a FixedUpdate-ben kezelni:
    void FixedUpdate()
    { 
        if(transform.position.y > 0)
            velocity.y -= acceleration * Time.fixedDeltaTime; // gravitációs gyorsulás
    }

    void Update()
    {
        // Input kezelés
        if (transform.position.y <= 0)  // A levegőben nem tud ugrani a szöcske
        {
            if(Input.GetKeyDown(KeyCode.UpArrow))
                velocity = new Vector3(0,jumpVelocityVertical, jumpVelocityHorizontal);
            if(Input.GetKeyDown(KeyCode.DownArrow))
                velocity = new Vector3(0, jumpVelocityVertical, -jumpVelocityHorizontal);
            if(Input.GetKeyDown(KeyCode.RightArrow))
                velocity = new Vector3(jumpVelocityHorizontal, jumpVelocityVertical, 0);
            if(Input.GetKeyDown(KeyCode.LeftArrow))
                velocity = new Vector3(-jumpVelocityHorizontal, jumpVelocityVertical, 0);
        }

        // Mozgás 
        // Az elmozdulást érdemes az Update-ben kezelni
        transform.position += velocity * Time.deltaTime;
        
        // Megállás
        if(transform.position.y <= 0)
            velocity = Vector3.zero;
    }
}
using UnityEngine;

public class Flappy : MonoBehaviour
{
    [SerializeField] float top;
    [SerializeField] float bottom;
    [SerializeField] float jumpVelocityVertical;
    [SerializeField] float acceleration;

    bool isPlaying = false;     // Játék folyamatban van-e?
    float velocity;             // Sebességvektor

    void Start()
    {
        Reset(); // Kezdeti állapot beállítása
    }

    // A gyorsulást és lassulást érdemes a FixedUpdate-ben kezelni:
    void FixedUpdate()
    { 
				// gravitációs gyorsulás
        if(isPlaying)
            velocity -= acceleration * Time.fixedDeltaTime; 
    }

    void Update()
    {
        // Input kezelés
        if (Input.anyKeyDown)
        {
            isPlaying = true;
            velocity += jumpVelocityVertical;
        }

        // Mozgás (érdemes azUpdate-ben kezelni)
        if (isPlaying)  // Ha megy a játék
        {
            transform.position += 
								new Vector3(0, velocity * Time.deltaTime, 0);
            
            // Game over
            float y = transform.position.y;
            if (y <= bottom || y >= top)
            {
                Debug.Log("Game Over");
                Reset();
            }
        }
    }

    void Reset() // Kezdeti állapot beállítása
    {
        isPlaying = false; // Megállás
        velocity = 0; // Sebesség nullázása
        
        // Középre helyezés:
        Vector3 pos = transform.position;
        pos.y = (top + bottom) / 2;
        transform.position = pos;
    }
}
using UnityEngine;

class AsteroidsSpaceShip : MonoBehaviour
{
    [SerializeField] float acceleration = 5f;       // Gyorsulás
    [SerializeField, Range(0,1)] float drag = 0.8f; // Közegellenállás
    [SerializeField] float rotationSpeed = 360f;    // Szögsebesség
    
    Vector2 velocity; // Sebességvektor

    // Gyosulást szerencsésebb FixedUpdate-ben végezni.
    void FixedUpdate()
    {
        // Input
        float forwardInput = Input.GetKey(KeyCode.UpArrow) ? 1 : 0;

        // Gyosrulás
        if (forwardInput > 0)
        {
            Vector2 forwardDir = transform.up;
            velocity += forwardDir * (acceleration * Time.fixedDeltaTime);
        }

        // Lassulás
        velocity *= Mathf.Pow(1 - drag, Time.fixedDeltaTime);
        
    }

    // Mozgatás és egyenletes forgatást szerencsésebb Update-ben végezni.
    void Update()
    {
        // Mozgatás
        transform.position += (Vector3)velocity * Time.deltaTime;
        
        // Forgatás 
        float turnInput = (Input.GetKey(KeyCode.LeftArrow) ? 1 : 0) +
                          (Input.GetKey(KeyCode.RightArrow) ? -1 : 0);
        transform.Rotate(0, 0, turnInput * rotationSpeed * Time.deltaTime); 
    }
}
using UnityEngine;

public class Planet : MonoBehaviour
{
	[SerializeField] Planet p1, p2;            // Egyéb bolygók
	[SerializeField, Min(0)] float mass = 1;   // Tömeg 

	Vector3 velocity;                          // Sebességvektor

	// A gyorsulást és lassulást érdemes a FixedUpdate-ben kezelni:
	void FixedUpdate()
	{
		ApplyGravity(p1);
		ApplyGravity(p2);
	}

	// Gravitációs erő alkalmazása egy másik bolygóra:
	void ApplyGravity(Planet otherPlanet)
	{
		float gravity = 5; // Newton féle gravitatációs állandó (saját értékkel)
		Vector3 distanceVector = otherPlanet.transform.position - transform.position;
		if (distanceVector == Vector3.zero)
			return; // Következő bolygóra lépünk

		float distance = distanceVector.magnitude;      // Távolság
		Vector3 direction = distanceVector.normalized;  // Irányvektor

		float acceleration = gravity * otherPlanet.mass / distance;
		// ITT MOST NEM A TÁVOLSÁG NÉGYZETÉVEL OSZTOK!!!
		// Mint az a valós fizika szerint történne!
		// Ennek oka, hogy túl nehéz vele stabil rendszert építeni, ami nem esik szét.

		velocity += direction * (acceleration * Time.fixedDeltaTime); // gravitációs gyorsulás
	}

	// Az elmozdulást érdemes az Update-ben kezelni:
	void Update()
	{
		transform.position += velocity * Time.deltaTime;
	}
}
using UnityEngine;

public class Planet : MonoBehaviour
{
    [SerializeField, Min(0)] float mass = 1;   // tömeg 
    
    Vector3 velocity;             // Sebességvektor

    // Kiszámolom a méretet a tömeg alapján (NEM VOLT FELADAT)
    void OnValidate()
    {
        float scale = Mathf.Pow(mass, 1/3f); // a tömeg köbgyöke
        transform.localScale = new Vector3(scale, scale, scale);
    }

    // A gyorsulást és lassulást érdemes a FixedUpdate-ben kezelni:
    void FixedUpdate()
    {
        float gravity = 5; // Newton féle gravitatációs állandó (saját értékkel)
        foreach (var otherPlanet in FindObjectsOfType<Planet>())  // Minden egyéb bolygó hat ránk
        {
            if(otherPlanet == this)    // Saját magára nem hat a bolygó
                continue; // Következő bolygóra lépünk
            
            Vector3 distanceVector = otherPlanet.transform.position - transform.position;
            if(distanceVector == Vector3.zero)
                continue; // Következő bolygóra lépünk
            
            float distance = distanceVector.magnitude;      // Távolság
            Vector3 direction = distanceVector.normalized;  // Irányvektor
            
            float acceleration = gravity * otherPlanet.mass / distance;
            // NEM A TÁVOLSÁG NÉGYZETÉVEL OSZTOK!!!
            // Mint az a valós fizika szerint történne!
            // Ennek oka, hogy túl nehéz vele stabil rendszert építeni, ami nem esik szét.
            
            velocity += direction * (acceleration * Time.fixedDeltaTime); // gravitációs gyorsulás
        }
    }
    
    // Az elmozdulást érdemes az Update-ben kezelni:
    void Update()
    {
        transform.position += velocity * Time.deltaTime;
    }

    // Sebességvektor kirajzolása (NEM VOLT FELADAT)
    void OnDrawGizmos()
    {
        Gizmos.color = new Color(1,1,1,0.25f); // Átlátszó fehér 
        Gizmos.DrawLine(transform.position, transform.position + (velocity * 0.5f)); // Sebességvektor
    }
}
using UnityEngine;

public class NameOfTheClicked : MonoBehaviour
{ 
    void Update()
    {
        Camera cam = Camera.main;                               // Fő kamera
        Ray ray = cam.ScreenPointToRay(Input.mousePosition);    // Sugár
        if (Input.GetMouseButtonDown(0))                        // Ha bal egérgombbal kattintok
        {
            if (Physics.Raycast(ray, out RaycastHit hit))       // Ha a sugár ütközik valamivel
                Debug.Log(hit.collider.name);                   // Kiírja a konzolba a nevét
        }
    }
}
using UnityEngine;

public class Pointer : MonoBehaviour
{ 
    [SerializeField] float rayLength = 100f;
    [SerializeField] GameObject[] objects;

    void Update()
    {
        Vector3 position = transform.position; // Pozíció
        Ray ray = new Ray(position, transform.forward); // Előre mutató sugár

        bool isHit = Physics.Raycast(ray, out RaycastHit hit, rayLength); // Sugárvetés = raycast

        foreach (GameObject o in objects)   // Végigmegyek az összes objektumon
            o.SetActive(isHit);             // Ki vgy be kapcsolom az objektumokat
                                            // függően attól, hogy történt e találat

        if (isHit) // Ha van találat
        {
            for (int index = 0; index < objects.Length; index++) // Az összese elemre:
            {
                float rate = index / (objects.Length - 1f); // 0-1 közötti érték
                Vector3 p = Vector3.Lerp(position, hit.point, rate); // Lineáris interpoláció
                objects[index].transform.position = p; // Pozíció beállítása
            }
        }
    }

    void OnDrawGizmos()
    {
        Vector3 position = transform.position;                                  // Pozíció
        Ray ray = new Ray(position, transform.forward );            // Előre mutató sugár 
        Gizmos.color = Color.red;                                               // Gizmos színe
        Gizmos.DrawLine(ray.origin, ray.origin + (ray.direction * rayLength));  // Sugár kirajzolása 
    }
}
using UnityEngine;
 
public class Magnet : MonoBehaviour
{
    [SerializeField] new Rigidbody2D rigidbody;
    [SerializeField] float power;
    [SerializeField] bool isPositive;
 
    void FixedUpdate()
    {
        Magnet[] magnets = FindObjectsOfType<Magnet>();

//  	  for(int i = 0; i < magnets.Length; i++) // for ciklus is lehetne
//			{
//					Magnet other = magnets[i];

        foreach (Magnet other in magnets)       // for ciklus is lehetne
        {                                       // Látsd fentebb ↑

            if (other == this) continue;        // Saját magára nem hat
            
            Vector2 vector = other.transform.position - transform.position;
            float distance = vector.magnitude;  // Távolság
            Vector2 direction = vector;         // Irány
            
            if(isPositive != other.isPositive)  // Ha ellentétesek a pólusok
                direction *= -1;                // akkor vonzzák egymást
            
            //A kifejtett erő:

						// egyenesen arányos mindkét pólus erejével,
            float force = power * other.power;
						// és fordítottan a távolság négyzetével.
            force /= distance * distance;
            
						// Erőt fejtünk ki a másikra
            other.rigidbody.AddForce(direction * force);
        }
    }
}
using UnityEngine;

public class Stomper : MonoBehaviour
{
    [SerializeField] float force = 10f;
    [SerializeField] float range = 5f;

    void Update()
    {
        if (!Input.GetMouseButtonDown(0)) 
            return;
        
        Camera mainCam = Camera.main;
        Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);
        
        if (!Physics.Raycast(ray, out RaycastHit hit))
            return;
        
        Rigidbody[] rigidbodies = FindObjectsOfType<Rigidbody>();
        foreach (Rigidbody rb in rigidbodies)
        {
            float distance =
								Vector3.Distance(rb.transform.position, hit.point);
            float rate = 1 - (distance / range);

            if (rate > 0)
                rb.AddForce(Vector3.up * (force * rate), ForceMode.Impulse);
        }
    }
}
using UnityEngine;

class GravityModifier : MonoBehaviour
{
	[SerializeField] Vector3 gravity = new(0, 10, 0);
	[SerializeField] float range = 1.0f;

  void FixedUpdate()
  {
		Rigidbody[] rigidbodies = FindObjectsOfType<Rigidbody>();
		foreach (Rigidbody rb in rigidbodies)
		{
			float distance = Vector3.Distance(transform.position, rb.position);
			if (distance < range)
				rb.AddForce(gravity, ForceMode.Acceleration);
		}
	}
}
// Listával és triggerekkel

using System.Collections.Generic;
using UnityEngine;

class GravityModifier : MonoBehaviour
{
		//Kifejtett gyorsulás
    [SerializeField] Vector3 gravity = new(0, 10, 0); 

		// Itt tárolom az éppen triggeren belül lévőket
    List<Rigidbody> _rigidbodies = new();

		// Tárolom a belépőket
    void OnTriggerEnter(Collider other)
    {
        Rigidbody rb = other.attachedRigidbody;
        if (rb != null)            
            _rigidbodies.Add(rb);
    }
    
		// Törlöm a listából a távozókat
    void OnTriggerExit(Collider other)
    {
        Rigidbody rb = other.attachedRigidbody;
        if (rb != null)
            _rigidbodies.Remove(rb);
    }

    void FixedUpdate()
    { 
				// Hozzáadom a gyorsulást
        foreach (Rigidbody rb in _rigidbodies)
		        rb.AddForce(gravity, ForceMode.Acceleration);
    }
}
using UnityEngine;

public class Bomb : MonoBehaviour
{
    [SerializeField] float delay = 5f;
    [SerializeField] float force = 25f;
    [SerializeField] float range = 5f;
    [SerializeField] float up = 0.5f;
    
    float _startTime;

    void Start()
    {
        _startTime = Time.time;
    }

    void Update()
    {
        if (Time.time - _startTime > delay)
        {
            Explode();
            Destroy(gameObject);
        }
    }

    void Explode()
    {
        Rigidbody[] rigidbodies = FindObjectsOfType<Rigidbody>();
        foreach (Rigidbody rb in rigidbodies)
						rb.AddExplosionForce(
								force,
								transform.position,
								range,
								up,
								ForceMode.Impulse); 
	  }
}
using System.Collections.Generic;
using UnityEngine;

public class Pointer : MonoBehaviour
{ 
    [SerializeField] float rayLength = 100f;           // Sugárvetés maximális hossza
    [SerializeField] float distance = 0.25f;           // Két célzópont távolsága
    [SerializeField] GameObject prototype;             // Ebből készítünk másolatokat

    List<GameObject> objects = new List<GameObject>(); // Ebbe a listába tesszük ez elemeket

    void Update()
    {
        Vector3 position = transform.position;            // Pozíció
        Vector3 forward = transform.forward;              // Előre irány
        Ray ray = new Ray(position, forward); // Előre mutató sugár

        bool isHit = Physics.Raycast(ray, out RaycastHit hit, rayLength); // Sugárvetés = raycast 
        
        int count = 0; // Hány elemet rejzoljuk ki
        
        if (isHit) // Ha van találat
        {
            // Hány elemet rejzoljuk ki:
            count = Mathf.CeilToInt(Vector3.Distance(position, hit.point) / distance);
            
            // Ha nincsenek létrehozva, példányosítom és eltárolom a célzópontokat
            while (count > objects.Count)
            {
                GameObject newInstance = Instantiate(prototype);
                objects.Add(newInstance);
            }
            
            for (int i = 0; i < count; i++)     // Az összese megjelenítendő objektumra:
            {
                objects[i].SetActive(true);                         // bekapcsolás
                Vector3 p = position + (i * distance * forward);    // pozíció kiszámítása
                objects[i].transform.position = p;                  // Pozíció beállítása
            }
        }

        // Az összese NEM megjelenítendő objektumra:
        for (int i = count; i < objects.Count; i++)
            objects[i].SetActive(false);  // kikapcsolás
    }

    void OnDrawGizmos()
    {
        Vector3 position = transform.position;                                  // Pozíció
        Ray ray = new Ray(position, transform.forward );            // Előre mutató sugár 
        Gizmos.color = Color.red;                                               // Gizmos színe
        Gizmos.DrawLine(ray.origin, ray.origin + (ray.direction * rayLength));  // Sugár kirajzolása 
    }
}
using UnityEngine;

public class ClickJumper: MonoBehaviour
{
    [SerializeField] float velocity = 1f;
    [SerializeField] new Rigidbody rigidbody;

    void Update()
    {
        if(!Input.GetMouseButtonDown(0))
            return;

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit))
        {
            Vector3 directionVector = hit.point - transform.position;
            directionVector.y = 0;
            directionVector.Normalize();
            directionVector.y = 1;
            directionVector.Normalize();
            rigidbody.AddForce(
								directionVector * velocity,
								ForceMode.VelocityChange);
        }
    }
}
using System.Collections.Generic;
using UnityEngine;

[ExecuteAlways]
public class Ballistics : MonoBehaviour
{
    [SerializeField] LineRenderer lineRenderer;
    
    [Space]
    
    [SerializeField] Vector3 gravity = new Vector3(0, -9.81f, 0);
    [SerializeField] float speed = 5f; 
    [SerializeField] float drag = 0.1f;
    [SerializeField] float timeStep = 0.1f;
    [SerializeField] float maxTime = 2f;

    void Update()
    {
        if(lineRenderer == null) return;
        
        var calculatedPoints = GetBallisticPath(transform.position, transform.forward * speed, gravity, drag, timeStep, maxTime);
        lineRenderer.positionCount = calculatedPoints.Count;
        lineRenderer.SetPositions(calculatedPoints.ToArray());
    }

    List<Vector3> GetBallisticPath(Vector3 position, Vector3 velocity, Vector3 gravity, float drag, float timeStep, float maxTime)
    {
        var points = new List<Vector3>();
        timeStep = Mathf.Max(timeStep, 0.001f);
        maxTime = Mathf.Max(maxTime, timeStep);
        
        for (float t = 0; t < maxTime; t += timeStep)
        {
            points.Add(position);
            position += velocity * timeStep;
            velocity += gravity * timeStep;
            velocity *= 1 - drag * timeStep;
        }

        return points;
    }
}