Jump to content
Unity Insider Forum

Waffen in einen Ego Shooter zufügen


Sir_Mathew

Recommended Posts

Hi,

also ich wollte Waffen meinen Ego Shooter anfügen.

Als in der Ich Perspektive soll meine Waffe im Fenster erscheinen und beim Waffen Wechsel, soll diese auch ausgetauscht werden.

Ich könnte nun alle Waffen im Spiel außerhalb der Welt Platzieren und je nach gewählte Waffe zu meinen Player bewegen. Aber das gefällt mir irgendwie nicht.

Ich würde lieber die Waffe erst beim auswählen erstellen. Beim abwählen soll diese dann auch wieder gelöscht werden.

Denke das ist eine Standard Aufgabe und würde mich freuen, diese auch zu können mit Instanzen erstellen etc.

Hoffe ihr könnt mir da einen denkanstoß geben.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mit Instantiate kannst du spawnen und mit Destroy wieder despawnen. Da gerade Instantiate aber etwas teuer sein kann, ist es keine schlechte Idee, alle Waffen von vorneherein da zu haben. Dafür musst du sie auch nicht irgendwo platzieren, sondern kannst sie alle gleich an der richtigen Stelle haben und immer alle bis auf eine deaktiviert haben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo

 

Das klingt so, als hätte der Spieler die Waffen in seinem Inventar und kann dann die aussuchen, die er nutzen möchte?! Warum willst du sie in der Welt platzieren (also beim Aussuchen)? Warum willst du die Waffe beim Auswählen erstellen? Ohne jetzt genau dein Konzept zu kennen, würde ich die Waffen in der Welt (also Kisten oder frei) platzieren. Wenn der Spieler sie aufsammelt, wandern sie in dein Inventar und dann geht es von dort weiter. Vielleicht habe ich dich aber auch falsch verstanden..

 

Christoph

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 6 Minuten schrieb gombolo:

ich glaube er meint einfach SetActive(bool)

Spätestens bei den Projektilen wirst du auf das selbe Problem stoßen. Oder willst du alle 50Katrillionen Geschosse in der Welt verstecken :D

 

Oh das mit der Munition ist tatsächlich das selbe Problem. Instantiate wäre dabei auch schlecht? Hm Mal sehen was @Sascha dazu sagt🤔

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich sage:

  • @gombolo hat Recht: Ich meine SetActive.
  • Instantiate und Destroy gehen immer, aber wie gesagt - Instantiate kostet immer ein bisschen was und Destroy erzeugt Garbage.
  • Prinzipiell würde ich das so zusammenfassen:
    • Wenn ein Objekt einmalig oder sehr selten spawnt oder recht lange existiert, kann man schon Instantiate benutzen. Beispiele wären in meinem Spiel die 1-4 Spielfiguren, die für lokalen Coop spawnen oder ein Loot-Item das in seiner Form nur selten auftaucht (z.B. eine Waffe in Borderlands).
    • Wenn ein Objekt immer wieder auftaucht (wie deine Waffen), dann sollte es in der Szene sein (ob im Editor platziert oder einmalig mit Instantiate erstellt kommt auf den Kontext an - geht beides). Es wird dann z.B. mit SetActive immer aktiviert und deaktiviert, anstatt es zu zerstören und neu zu spawnen.
    • Wenn eine Sorte Objekt oft auftaucht und/oder schnell wieder verschwindet (so wie Partikel, häufiger Loot wie Münzen bei Mario oder Patronenhülsen), dann sollte man Pooling verwenden. Das ist prinzipiell dasselbe wie die vorhergehende Option mit ständigem Deaktivieren und Reaktivieren, aber ohne dass die Identität einer Instanz bewahrt wird. Ein Pooling-System verwaltet Instanzen. Wenn ein Objekt nicht mehr gebraucht wird und despawnen soll, wird es zurück in den Pool gepackt. Wenn eine neue Instanz gebraucht wird, schaut das Pooling-System, ob im Pool noch ein Objekt zum Recyceln rumliegt und gibt dieses ggf. zurück. Nur, wenn der Pool leer ist, wird eine neue Instanz erstellt.
Link zu diesem Kommentar
Auf anderen Seiten teilen

Also das Pooling ist ja echt Genial. Aber das eine neue Instanz erstellt wird, wenn das Pooling leer ist, hab ich nirgendwo gelesen. Aber ist ja nicht so wichtig. Ich werde beim Spielstart einfach einige erstellen. Einfach paar mehr, als möglich gleichzeitiger Geschosse.

Habs mal mit 20K Waffen getestet, ui ui ui es laggt dann :D

Aber noch was anderes. Kann ich zur Laufzeit beim Spielstart meine Waffe erstellen und an meinen Monitor Bild Positionieren?

Finde ich sehr unübersichtlich alle Waffen Vorab meinen Player zuzuweißen. Hab dann sonst 10 Waffen am Player Kleben in der Scene.

Also Waffe erstellen und in mein Bild Positionieren.

Danke

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

hmmm...Du kannst doch die Waffe über SetActive(bool) aktivieren bzw. deaktivieren. Wie viele Waffen willst du den erstellen? Zu Beginn sind alle deaktiviert und nur die Standardwaffe ist aktiv und zu sehen. Dann kannst du doch z.B. über das Mausrad die nächste Waffe auswählen. Dann deaktivierst Du die Standardwaffe und aktiviertest den nächsten usw...  

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Sir_Mathew:

Aber das eine neue Instanz erstellt wird, wenn das Pooling leer ist, hab ich nirgendwo gelesen

Naja, wo soll die denn sonst her kommen?

vor einer Stunde schrieb Sir_Mathew:

Aber noch was anderes. Kann ich zur Laufzeit beim Spielstart meine Waffe erstellen und an meinen Monitor Bild Positionieren?

Finde ich sehr unübersichtlich alle Waffen Vorab meinen Player zuzuweißen. Hab dann sonst 10 Waffen am Player Kleben in der Scene.

Ja, kein Ding. Einfach einen Spawnpunkt für Waffen am Spieler haben (den hast du vermutlich sowieso schon) und dann ein Script drautun mit einer Liste an Prefabs. Dann in Start durch die Liste gehen und alle mit Instantiate spawnen und direkt im Anschluss alle bis auf eine mit SetActive wieder deaktivieren.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ah ja Spawnpunkt hab ich nicht, hab das nun meiner Player Position mit etwas + zugewiesen.

Aber Waffe ist schon mal da.

 Hab da aber etwas ganz merkwürdiges.

Und zwar erstelle ich die Waffe und füge sie einer Position zu.

Wenn ich an der Position im Code etwas änder, gleiche gilt auch für localScale, dann werden die werte erst nach 2 mal Run übernommen.

Warum ärgert mich da Unity? Wieso nimmt er die Werte erst im 2.Run?

 public GameObject waffe1;
int zählerWaffen = 0;

    private void Update()
    {
        waffen();
    }

    void waffen()
    {
        GameObject tmp;
        if (zählerWaffen < 1)
        {
            tmp = Instantiate(waffe1);
            tmp.SetActive(true);
            zählerWaffen++;

            waffe1.transform.position = player.transform.position + new Vector3(0.0f, 0.0f, 10.0f);
        }
    }

Ach und wenn ich die Positions Werte auskommentiere, dann bleiben die werte egal wie oft ich Run starte.

Dürfte doch absolut nicht sein, da ich bei jeden Run eigentlich das Model neu erstelle.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Es läuft und läuft aber sehr schleppend.

Wie kann ich ein Animationsclip nun meiner Instanzierten Waffe hinzufügen und abspielen? 

Die zugefügte Animation landet immer Animations Element 0.

Vermutlich für mehrere Animationen? Dann wäre das auch OK wenn ich es wenigstens abspielen könnte.

public GameObject waffe1;
public AnimationClip animWaffe1;
GameObject tmp;
    void waffen()
    {

        if (zählerWaffen < 1)
        {
            tmp = Instantiate(waffe1);
            tmp.SetActive(true);
            zählerWaffen++;
            tmp.transform.parent = playerCam.transform;
            tmp.AddComponent<Animation>();
            Animation Shoot = tmp.GetComponent<Animation>();
            Shoot.AddClip(animWaffe1, "Shoot");
        }


        if (Input.GetButtonDown("Fire1"))
        {
            tmp.GetComponent<Animation>().Play("Shoot");
        }


        tmp.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
        tmp.transform.localPosition = new Vector3(0.093f, -0.034f, 0.22f);
        tmp.transform.localRotation = Quaternion.Euler(1.0f, -5.0f, 0.0f);
    }

Vermutlich hab ich alles was mit Animation habe falsch.

Gameobject tmp hab ich Extern von der Funktion, teste noch.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Boar ich bin ja auch so dusselig.

Dachte immer es geht nicht, weil die Waffe immer Kurz verschwindet.

Hab die Animation an einer Waffe gemacht, die irgendwo in der Welt steht. Hab diese dann meiner Waffe die an mein Player hängt übertragen.

Das Problem ist, beim start der Animation, wird die Koordinate mein anderen Waffe verwendet. Also wandert sie dort hin, macht seine Animation und kommt zurück.

Bei sehr langsamen abspielen der Animation, sieht man wie die Waffe angeflogen kommt.

Hab nun meine Welt Waffe auf die Position meiner Instanzierten Waffe gepackt, animiert und es läuft.

Laut Handbuch kann man auch Root Motion aktivieren um die Welt Koordinaten zu Ignorieren.

Aber all das soll im neueren Animator  Controller sein und nicht im alten Animation so wie ich jetzt habe.

Also hab ich mich auch an Animator Controller versucht und sage nur oooohje.

Ich will ja keine super Animation sondern einfach nur das meine Waffe beim Schuss einen rückstoß hat. Eventuell muss ich aber auch noch Gegner Animieren.

Muss mich wohl oder übel damit beschäftigen.

Wenn jemand gute Tutorials auf Deutsch kennt immer her damit.

Diese die ich bisher sah, waren die einzelnen Animationen schon fertig und wurden nur der Reihenfolge wie sie ausgeführt werden gezeigt.

Es soll auch Automatische Animationen für z.b. Humanoide geben usw. Also ich bin sehr gespannt auf dieses sehr Komplexe Thema.:o

Link zu diesem Kommentar
Auf anderen Seiten teilen

So nach ewigen hin und her, bestimmt 100 mal meine Waffe animiert und egal wie auch immer, es sieht schrecklich aus.

Daher dachte ich mir, Waffen Bewegung mach ich peer Script

    Quaternion from;
    Quaternion to;

    void waffen() //aufruf in Update
    {
      
        if (zählerWaffen < 1)
        {
            tmp = Instantiate(waffe1);
            tmp.SetActive(true);
           
            tmp.transform.parent = playerCam.transform;
       
            tmp.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
            tmp.transform.localPosition = new Vector3(0.093f, -0.034f, 0.22f);
            tmp.transform.localRotation = Quaternion.Euler(1.0f, -5.0f, 0.0f);
            from = Quaternion.Euler(1.0f, -5.0f, 0.0f);
            zählerWaffen++;
        }

        if (Input.GetButtonDown("Fire1"))
        {
          to = Quaternion.Euler(180, -5, 0);
        }
        tmp.transform.localRotation = Quaternion.Lerp(from, to, Time.deltaTime * 2.0f);

        Debug.Log(from);
        Debug.Log(to);
    }

Um meine Waffe nicht Ruckartig zu drehen dachte ich an Lerp.

Bis dahin schön und gut.

Aber es funktioniert gleich 0 und das verstehe ich nicht.

Hab die Quaternionen Variablen ausgelesen.

Diese sagen:

to = 0.0, 0.0, 0.0, 0.0 und nach Mausklick "Fire1" ändert sich der Wert auf 1.0, 0.0, 0.0, 0.0

from = bleibt bei 0.0, 0.0, 0.0, 1.0

Beide Variablen müssten ganz andere Zahlen haben, so wie ich vorgegeben habe.

Wo liegt da mein Denkfehler?

Danke

Link zu diesem Kommentar
Auf anderen Seiten teilen

Quaternions sind ein bisschen speziell. Wenn du bei einem Quaternion vier Werte siehst, dann siehst du die tatsächlichen internen Werte, und die sind nicht dieselben wie die der Euler-Repräsentation. Ist also normal, dass du andere Werte siehst. Der Rest sind Rundungen für Debug.Log, das will nämlich gerne nur eine Nachkommastelle anzeigen. Quaternion.Euler(180, -5, 0) ergibt (0.9990482, 1.906664E-09, 0.04361939, -4.366979E-08), und das wird ganz fix auf (1.0, 0.0, 0.0, 0.0) gerundet.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hä?

die werte hauen ja dann gar nicht hin.

hab auch statt 180 z.b. 30000 probiert etc.... aber die Waffe dreht sich nur wenige Millimeter.

Oh man was mach ich da nur? Ob Quaternion.Lerp etc.... ist mir egal.

Wie gesagt, wollte halt nur eine Drehung Smoth Interpolieren ohne ruckartig zu drehen.

Gibt es dann vielleicht andere Ansätze?

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 28 Minuten schrieb Sir_Mathew:

die werte hauen ja dann gar nicht hin.

Öh... doch? Sind nur halt Quaternion-Werte, das ist n bisschen finstere Mathemagie.

vor 28 Minuten schrieb Sir_Mathew:

Oh man was mach ich da nur? Ob Quaternion.Lerp etc.... ist mir egal.

Wie gesagt, wollte halt nur eine Drehung Smoth Interpolieren ohne ruckartig zu drehen.

Gibt es dann vielleicht andere Ansätze?

Lerp ist eine simple mathematische Funktion. Werte rein, Ergebnis raus. Die Formel ist

lerp(a, b, t) = a + (b - a) * t

Wenn du da immer denselben Wert für A, immer denselben Wert für B und immer mehr oder weniger denselben Wert für T reinsteckst, dann kommt auch immer mehr oder weniger dasselbe heraus. Stelle dir Lerp vor als "x% des Weges gehen". Und du gehst halt

Time.deltaTime * 2.0f

Prozent des Weges. Wäre bei 60 fps ein Wert von etwa 0,0333. Und "from" und "to" ändern sich nicht. Du gehst also immer 3,3% von from nach to. Da hast du halt ein einigermaßen konstantes Ergebnis.

Schau dir evtl. mal eine Tween-Library an, da sparst du dir ne Menge Arbeit mit ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

So nun ist es so weit, ich flippe aus.

Hab nun alles mögliche getestet.

Hab erstmal Time.DeltaTime raus genommen.

tmp.transform.localRotation = Quaternion.Lerp(from, to,0.01f);

Soweit so gut. Es dreht sich.

1.0f gibt Komischerweiße einen Fehler 

Assertion failed on expression: '!CompareApproximately(aScalar, 0.0F)'
UnityEngine.Quaternion:Lerp (UnityEngine.Quaternion,UnityEngine.Quaternion,single)

Warum wieso weshalb, keine Ahnung. Da 1.0f 100% der Drehung bringt, was ja eigentlich möglich sein sollte. Naja ich kann auch mit 0.1f also 10% Arbeiten.

Obwohl ich merke gerade das sind nicht mal 10%.

Was für eine Lila Farbene Mathemagie.:blink:

So also es dreht sich erstmal, mit Zahlenwerten rumprobieren wird es schon werden.

Aber hab da noch eine Frage.

Lerp macht doch eigentlich eine Smoothe Bewegung oder?

Weil da ist nix Smooth sondern Sofort.

Wie dreht ihr denn Gegenstände Smooth?

 

 

Hab gerade mal nach Tween-Library gegoogelt, was soll das denn sein?

 

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 11 Minuten schrieb Sir_Mathew:

Lerp macht doch eigentlich eine Smoothe Bewegung oder?

Jein. Das ist genau das, was ich schon schrieb:

Am 30.3.2021 um 22:12 schrieb Sascha:

Lerp ist eine simple mathematische Funktion. Werte rein, Ergebnis raus.

Wenn du das einmal aufrufst, dann kommt da einmal ein Ergebnis raus. Wenn du das nochmal mit denselben Werten aufrufst, kommt nochmal dasselbe Ergebnis raus. Eine Art Animation kannst du damit hinkriegen, indem du das Ergebnis, also die neue Position, im nächsten Aufruf als "from" einsetzt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Oh man, hab nochmal mir das Vector3.Lerp angeschaut.

Kam zum Schluss, das ich das Festgesetzte from weg nehmen muss.

Hab nun:

 tmp.transform.localRotation = Quaternion.Lerp(tmp.transform.localRotation, to, 0.01f);

Und nun dreht sich das ganz Smooth.

Warum das aber so funktioniert hmmmm.

Bei jedem Frame wird sich tmp.transform.localRotation dem to annähern. Dann müsste es sich ja am Anfang langsam drehen und immer langsamer werden.

Die Logik ist mir schleierhaft. Lilafarbene Mathemagie ebend.

Hauptsache es geht.

Danke für die Hilfe

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...