Jump to content
Unity Insider Forum

Impact velocity von einer Box


Recommended Posts

Hi,

in meinem 2D Platformer Game habe ich Kisten:

image.png.fdbef0820f4d120b0064b7e11deceb5c.png

und Gegner die diese Kisten auf den Spieler werfen können:

image.png.3009471f5dc8143b34a14687c2a98c4f.png + image.png.fdbef0820f4d120b0064b7e11deceb5c.png = image.png.4f6b00e3bf12e444c9c1a6007a13cabb.png 

 Ich möchte dass diese Boxen wenn sie mit einer gewissen Wucht auf etwas stoßen (Terrain oder Spieler) zerstört werden. Dafür hatte ich erst die OnCollisionEnter2D Funktion benutzen. Das sah dann so aus:

private void OnCollisionEnter2D(Collision2D collision) {
        if (!collision.collider.isTrigger && !collision.collider.CompareTag("Enemy")) {
			
	    //wenn die Velocity x oder y größer als 5 ist.
            if (Mathf.Abs(collision.relativeVelocity.x) > 5 || Mathf.Abs(collision.relativeVelocity.y) > 5) {
                
					if (collision.collider.CompareTag("Player")) {
                    collision.collider.GetComponent<Player>().TakeDamage(1);
                }
                DestroyBox();
            }
        }
    }

Das Problem hierbei ist dass die Kiste auch zerstört wird wenn der Spieler sie berührt wärend er rennt oder draufspringt, da die Velocity der collision (in dem fall dem Spieler) genommen wird.

Daher hab ich mir dann eine andere Methode ausprobiert und zwar mit der Funktion onTriggerEnter2D:

private void OnTriggerEnter2D(Collider2D collision) {
        if (!collision.isTrigger && !collision.CompareTag("Enemy")) {
            if (Mathf.Abs(rb.velocity.x) > 5f || Mathf.Abs(rb.velocity.y) > 5f) {
                if (collision.CompareTag("Player")) {
                    collision.GetComponent<Player>().TakeDamage(1);
                }
                DestroyBox();
            }
        }
    }

image.png.e162bb078dbf9dfc42a8e9d283d959ed.png

 

Aber um ehrlich zu sein finde ich diese Methode sehr unschön. Außerdem wird die Box schon kurz vor dem Impact zerstört was man zwar nicht wirklich merkt aber ich weiß es und das stört mich. Darum wollte ich fragen ob es da einen schöneren weg gibt.

ich habe online immer nur diese 2 Methoden gefunden. 

image.png

Link to post
Share on other sites

Wenn ich dich richtig verstehe, dann möchtest du das zu 100% von der Geschwindigkeit der Box abhängig machen und ignorieren, wie schnell das Objekt ist, das getroffen wird? Scheint mit ein koimischer Umweg zu sein, anstatt zu sagen "wenn die Kiste geworfen wird, ist sie automatisch schnell genug, dass sie immer kaputt geht"... aber deine Entscheidung :)

Ich würde dafür jedenfalls ganz einfach die Geschwindigkeit des Rigidbodys nehmen, denn um die geht's ja. Sie ist nur halt in OnCollisionEnter2D bereits durch die Kollision abgewandelt. Deshalb musst du sie dir im vorherigen FixedUpdate speichern:

new private Rigidbody2D rigidbody2D;
private Vector2 preCollisionVelocity;

private void Awake()
{
    rigidbody2D = GetComponent<Rigidbody2D>();
}

private void FixedUpdate()
{
    preCollisionVelocity = rigidbody2D.velocity;
}

private void OnCollisionEnter2D(Collision2D collision)
{
    Debug.Log(preCollisionVelocity);
}

 

Link to post
Share on other sites

hallo sascha danke erstmal dass du mir noch so spät so schnell antwortest.

vor 31 Minuten schrieb Sascha:

Wenn ich dich richtig verstehe, dann möchtest du das zu 100% von der Geschwindigkeit der Box abhängig machen und ignorieren, wie schnell das Objekt ist, das getroffen wird?

genau. ob der Spieler springt, rennt, fällt soll keinen Einfluss haben ob die Kiste bei Kontakt kaputt geht oder nicht. Daher konnte ich das relativeVelocity nicht benutzen.

 

vor 36 Minuten schrieb Sascha:

Scheint mit ein koimischer Umweg zu sein, anstatt zu sagen "wenn die Kiste geworfen wird, ist sie automatisch schnell genug, dass sie immer kaputt geht"

das Problem ist dass man Kisten auch schieben kann und sollten sie irgendwo runterfallen dann können sie dadurch auch kaputt gehen. Sorry dass ich das nicht erwähnt habe vorher.

Jedenfalls scheint dein Ansatz eigentlich zu passen für mich.. Aber kann sowas nicht zu Problemen führen wenn die fps mal dropen oder so? Sorry bin was performence und so Zeugs angeht noch Frischling in Unity

Außerdem wollte ich fragen was es mit dem "new" keyword beim rigidbody aufsich hat. Hab das nämlich nicht stehen bei mir. Sollte man das benutzen bei den eigenen Komponenten? Hat zwar nichts mit dem Thema zu tun aber das interessiert mich jetzt :D

Link to post
Share on other sites
vor 8 Stunden schrieb Brighthell96:

das Problem ist dass man Kisten auch schieben kann und sollten sie irgendwo runterfallen dann können sie dadurch auch kaputt gehen. Sorry dass ich das nicht erwähnt habe vorher.

Das ist zwar mehr Denkarbeit, aber der übliche Weg ist da (nicht ohne Grund!), eine Flag einzubauen - also ein bool-Feld, das angeht, wenn die Bedingungen zum kaputt gehen erfüllt sind (wird geworfen, fällt von der Kante). Und bei einer Kollision wird geschaut, ob die Flag gesetzt ist und wenn ja, geht's kaputt. Aber für's Erste, nicht zuletzt um da ein Gefühl für zu kriegen, kannst du auch relativ problemlos™  bei der velocity-Variante bleiben.

vor 8 Stunden schrieb Brighthell96:

Jedenfalls scheint dein Ansatz eigentlich zu passen für mich.. Aber kann sowas nicht zu Problemen führen wenn die fps mal dropen oder so? Sorry bin was performence und so Zeugs angeht noch Frischling in Unity

FixedUpdate ist genau dafür da, dass die Framerate egal wird. Deshalb passiert die gesamte Physik auch auf dem FixedUpdate-Zyklus. Hier hast du einen Artikel von mir darüber - bei Fragen gerne fragen :)

vor 9 Stunden schrieb Brighthell96:

Außerdem wollte ich fragen was es mit dem "new" keyword beim rigidbody aufsich hat. Hab das nämlich nicht stehen bei mir. Sollte man das benutzen bei den eigenen Komponenten? Hat zwar nichts mit dem Thema zu tun aber das interessiert mich jetzt

Äh ja, Angewohnheit von mir. Nicht besonders wichtig, aber... deine Script-Klasse erbt ja von MonoBehaviour. Und in MonoBehaviour sind ein Haufen Sachen definiert, z.B. GetComponent. Ohne diese Definition könntest du nicht einfach GetComponent schreiben und das Programm wüsste, was du meinst. Aus früheren Unity-Tagen sind da auch ein paar Propertys drin, die dich auf übliche Unity-Komponenten zugreifen lassen. So kannst du statt

GetComponent<Rigidbody>()

einfach

rigidbody

schreiben. Den Quark haben die sich aber zum Glück vor ein paar Jahren anders überlegt und neuere Komponenten kannst du so nicht mehr kriegen. Diese Propertys tauchen in der Dokumentation nicht einmal mehr auf, existieren aber noch als obsoleter Code, der Abwärtskompatibilität wegen.

Jedenfalls ist es bei Vererbung so, dass wenn du eine Property oder so hast und dann in einer erbenden Klasse (also deinem Script) ein Ding mit genau demselben Namen definierst, dass die neuere Definition die ältere "überschattet". Wenn du also "rigidbody2D" schreibst, ist nicht 100%ig sicher, ob du dein rigidbody2D meinst oder das, was Unity selber definiert. Unity wird dann deine Definition nehmen, aber das ist etwas, das man nicht versehentlich tun möchte. Stell dir vor, irgendwo weiter unten verlässt sich ein anderer in deinem Team (oder du selbst nach zwei Wochen) darauf, dass Unitys "rigidbody2D" gemeint ist, aber es ist in Wirklichkeit deine Variable.

Nimm gerne mal das "new" weg und schau mal, was dir deine IDE sagt. Die wird so etwas sagen wie "rigidbody2D hides inherited member MonoBehaviour.rigidbody2D" oder so, und dann "use the new keyword if hiding was intended".

Lange Rede, kurzer Sinn: Der Compiler beschwert sich, wenn man mit dem new-Keyword nicht explizit deutlich macht, dass man da mit Absicht die "rigidbody2D"-Defintion, die Unity da schon drin hat, überschatten möchte. Einige Leute finden das schon zu anstrengend und nehmen deshalb einfach einen anderen Namen für ihr Feld, wie "rb2d" oder "myRigidbody" oder so. Ich finde den Namen "rigidbody2D" aber genau richtig und will ihn deshalb benutzen :D

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...