Jump to content
Unity Insider Forum
Sign in to follow this  
Singular

Mein Raumschiff schießt nicht nach vorne

Recommended Posts

Hallo zusammen,

ich bin noch relativ neu hier und deswegen Hallo von meiner Seite. 👋

Ich bin sowohl mit C# als auch mit Unity noch nicht all zulange dabei und stoße schon an die ein oder anderen Probleme.

In meinem ersten kleinen Spiel habe ich folgendes Problem: (Noch als kurz Info vorne weg, ich befinde mich in einer 3D Umgebung, das Spiel selbst ist aber in 2D.)

Mein Raumschiff schießt teilweise nach hinten bzw. die Rotation des Schusses läuft doppelt so schnell ab wie die meines Raumschiffes. Heißt, wenn ich mein Raumschiff nach ob ausrichte, kommt der Schuss richtig nach oben. Richte ich mein Raumschiff nach links aus, fliegt der Schuss nach unten und richte ich mein Schiff nach unten aus, fliegt der Schuss nach oben.

Meine Scripts hierzu sehen so aus:

 

public class Kugeln : MonoBehaviour
{
    Movement player;
    public float bulletSpeed = 20f;
    private Transform tr;

    void Awake()
    {
        player = GameObject.Find("Player").GetComponent<Movement>();
        tr = GetComponent<Transform>();
        bulletSpeed += player.speed;
    }

    void Update()
    {
        transform.Translate(tr.forward * bulletSpeed * Time.deltaTime);
    }
}

 

Dazu noch das Script (gekürtz) das auf meinem Raumschiff liegt, was die Drehung und das Abfeuern der Kugeln steuert.

public class Movement : MonoBehaviour
{
    [Header("Schiffseigenschaften")]
    public float speed;
    public Vector3 v1;
    public Vector3 v2;
    public float schubVor = 150f;
    public float schubZurück = 120f;
    public float drehgeschwindigkeit = 100f;
    public float bremskraft = 0.8f;
    private Rigidbody rb;
    private Transform tr;

    [...]

    [Header("Kampf")]
    public GameObject laser;
    public GameObject Rakete;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        tr = GetComponent<Transform>();

        v1 = transform.position;

        InvokeRepeating("GeschwindigkeitMessen", 0.1f, 0.1f);
    }


    void Update()
    {
        MoveCharacter();
        RotateCharacter();
        SchußAbfeuern();
        [...]
    }

    [...]


    void RotateCharacter()
    {
        if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
        {
             transform.Rotate(transform.up, drehgeschwindigkeit * Time.deltaTime);
        }
        

        else if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
        {
             transform.Rotate(transform.up, -drehgeschwindigkeit * Time.deltaTime);
        }
    }

    void SchußAbfeuern()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            GameObject g = Instantiate(laser, transform.position, transform.rotation);
        }
    }

 

Danke schon mal im voraus.

Share this post


Link to post
Share on other sites

Hat echt nen Moment gedauert, bis ich's gefunden hab. Ist echt gemein.

Transform.Translate verschiebt ein Objekt in dessen local space, heißt: Wenn du Vector3.forward reinschmeißt, fliegst du dahin wo die Nase hinzeigt. Wenn du aber Transform.forward reinschmeißt, ist das doppelt gemoppelt. Richtig wäre also

tr.Translate(Vector3.forward);

oder auch

tr.Translate(tr.forward, Space.World);

oder, wo wir schon dabei sind,

tr.position += tr.forward;

(Jeweils mit was-auch-immer-du-da-raufmultiplizieren-willst.)

  • Thanks 1

Share this post


Link to post
Share on other sites

Mmh, muss ich mir heute Abend mal anschauen wenn ich wieder zuhause bin. Den Fehler habe ich jetzt schon zum zweiten Mal. Das ganze mit Space World und Translate ist mir noch etwas fremd.

Vielen Dank schon mal.

Share this post


Link to post
Share on other sites

Ja, wie du sagtest es hat (natürlich) geklappt...

Aber ich muss nochmal nachhaken um es zu verstehen.

Mit Translate wechsel ich in das Koordinatensystem des Objektes. Was genau tut dann "Space.World" und "translate.forward" vor allem, was ist doppelt gemoppelt? Weil deine 2. Version ist dann aus meiner Sicht auch doppelt, da du hier Translate UND forward verwendest. (Das ist übrigens die Variante, die ich jetzt bei mir gewählt habe)

Share this post


Link to post
Share on other sites
vor 31 Minuten schrieb Singular:

Mit Translate wechsel ich in das Koordinatensystem des Objektes

Naja, von einem "Wechsel" zu reden ist etwas gefährlich. Kann sein, dass du das Richtige meinst, aber so würde ich das nicht ausdrücken.

Erinnerst du dich, wie der Geographielehrer in der Schule darauf bestanden hat, dass man bei einer Karte "östlich von" gesagt hat und nicht "rechts von"? Genau um diesen Unterschied geht es. World space bedeutet, dass über das Koordinatensystem der Welt geredet wird. "Vorne" ist quasi "Norden", egal, wie du dich drehst. Wenn du aber im local space bist, dann ist vorne da, wo die Nase hinzeigt.

Transform.Translate kann dich entweder relativ zur Welt bewegen (du sagst "oben" und steigst in der Höhe, egal, wie du geneigt bist) oder relativ zum Objekt (wenn du auf der Seite liegst, rutscht du mit "oben" über den Boden). Mit dem zweiten Parameter kannst du angeben, welche der beiden Varianten du haben willst. Und wenn du ihn weglässt, dann wird als Standardwert local space benutzt. Das ist so, weil es irgendein Entwickler bei Unity irgendwann mal definiert hat, und aus keinem anderen Grund :)

Share this post


Link to post
Share on other sites

Okay ich glaube so 100% habe ich noch nicht verstanden, wie der Code funktioniert. Klar wenn ich von den Weltkoordinaten spreche und mich nach "oben" bewege, dass ich dann nach oben steige (egal wie ich ausgerichtet bin) bzw. vom Objekt aus gesehen nach über den Boden rutsche.

Mir ist nur nicht ganz klar, wie ich meinem Script klar machen kann in welches Koordinatensystem ich gehen möchte. Hierzu habe ich mir nochmal mein Script für mein Raumschiff angesehen. Wie es im Weltraum so ist, habe ich es so gemacht, dass wenn ich Schub gebe ich in die Richtung "geschoben" werde in die ich (mit meinem Raumschiff) schaue. der Code sieht so aus:

        if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
        {
            if (Tank > 0)
            {
                rb.AddForce(tr.forward * schubVor * Time.deltaTime);
                Tank -= Time.deltaTime * verbraucht;
            }
        }

Das mit "Tank" bitte einfach ignorieren, dass ist nur für den Sprittverbrauch meines Raumschiffs.

Hier gebe ich Schub in Blickrichtung, wenn ich W drücke. Aber warum in Blickrichtung? 

...

Da schreibe ich diesen Beitrag bis hierher und plötzlich fällt es mir wie Schuppen aus den Haaren. Jetzt hab ich es glaube ich verstanden... wegen tr.forward (tr = Transform / rb = Rigidbody des Objektes auf dem das Script liegt) Da ich hier lediglich eine kraft auf den rb ausübe und ihm sage, dass ich in Richtung tr.forward fliegen will natürlich im Koordinatensystem des Objektes.

In meinem vorherigen script habe ich nur den Transform verändert wodurch das Objekt bewegt wurde...

...

nächste erkenntnis... kann es sein, dass ich es mir tr sparen kann da ich über transform.position direkt darauf zugreifen kann??

...

ja kann ich. Ich glaube antworten auf diesen Beitrag sind nicht notwendig. Danke für deine Hilfe ;)

Share this post


Link to post
Share on other sites
vor 6 Stunden schrieb Singular:

Da schreibe ich diesen Beitrag bis hierher und plötzlich fällt es mir wie Schuppen aus den Haaren. Jetzt hab ich es glaube ich verstanden...

Nice!

vor 6 Stunden schrieb Singular:

kann es sein, dass ich es mir tr sparen kann da ich über transform.position direkt darauf zugreifen kann??

Jein. Die Property "transform" gibt eine Referenz auf die Transform-Komponente des GameObjects zurück, auf dem das Script liegt und tut damit im Prinzip dasselbe wie deine Variable, die die Referenz einmalig zugewiesen kriegt und dann speichert.

Allerdings ist "transform" keine Variable, sondern eben eine Property. Die sehen aus wie Variablen und werden syntaktisch fast genauso verwendet, beim Auslesen oder Setzen des Wertes können aber Dinge passieren. Und tatsächlich speichert "transform" nicht die Referenz, sondern führt bei jedem Zugriff "GetComponent<Transform>()" aus, so wie du es einmalig tust. Wie du es machst, ist daher minimal performanter. Das zählt unter "Mikrooptimierungen, wegen denen man sich wirklich keinen Kopf machen sollte", aber da es so extrem simpel zu machen ist, schadet es auch nicht, das drin zu lassen.

Ich programmiere eigentlich immer mit "transform", und wenn ich dann das Bedürfnis habe, die Performance noch ein wenig eleganter zu machen, dann baue ich eine überschattende Variable mit demselben Namen und weise den Wert zu. Dann muss ich nichts am restlichen Code ändern :)

new private Transform transform;

private void Awake()
{
  transform = base.transform;
}

 

Share this post


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...
Sign in to follow this  

×
×
  • Create New...