Jump to content
Unity Insider Forum

Eine Runde Welt ganz flach


Singular

Recommended Posts

Hallo zusammen, 

Ich habe folgendes Problem bzw Fragestellung... ich möchte in meinem Spiel, dass der Spieler ein Raumschiff in Topdown Ansicht steuert. Da er sich auf einem Planeten befindet, kann er logischerweise um die Kugel fliegen können. Allerdings ist die Welt natürlich in alle 4 Himmelsrichtungen endlich. Deshalb soll er und alles andere natürlich auch wenn er das Ende erreicht hat auf die andere Seite gesetzt werden. Das ist noch die einfachere Übung. Allerdings möchte ich nicht, dass der Spieler etwas davon bemerkt. Heißt er erreicht das linke Ende und kann weiter links gegner und Gebäude sieht, die sich eigentlich ganz rechts am Rand befinden. Ich will das ganze nicht wirklich auf einer Kugel stattfinden lassen sondern nur flach wie ein Brett.

Wie wäre hier eine gute Herangehensweise. Ich habe dazu bisher noch keinen Code den ich euch zeigen könnte ich bräuchte lediglich ein paar gedankenanstöße.

Danke euch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin!

Teile halt deine Flachwelt in vier Rechtecke auf. Das Raumschiff ist immer auf einem dieser vier Rechtecke, und immer irgendwo von dessen Mittelpunkt aus. Wenn du auf deinem Rechteck oben links bist, dann werden die anderen drei Rechtecke links und überhalb platziert. Wenn du dann auf die rechte Hälfte wechselst, werden die beiden linken Felder nach rechts verschoben. Und so weiter. Damit der Spieler nicht immer weiter vom Szenen-Nullpunkt wegfliegen kann, kannst du ja gleichzeitig das ganze Konstrukt gegenläufig verschieben, sodass alles mehr oder weniger in der Mitte bleibt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nice, die Idee habe ich auch gehabt allerdings nicht mit 4 Platten sondern mit 9, also eine in der Mitte und die anderen 8 drum herum aber mit 4n ist das ein bischen überschaubarer. :D Habe das mal gerade realisiert. Das Funktioniert aus soweit wunderbar!

Jetzt habe ich allerdings das Problem, was mache ich wenn auf dem Planeten sich mehrere Spieler tummeln sollen (bis zu vier)? Die Scene vier mal aufzubauen wäre eine Option aber die halte ich für etwas zu aufwändig und etwas überdimensioniert... Im Schlimmsten Fall fliegen 2 Spiele genau entgegen gesetzt. Einer fligt links heraus, der andere rechts... Die beiden sollen sich also begegnen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein, online Multiplayer

Aber ich glaube einmal drüber schlafen hat mir die Idee gebracht... ich darf nicht stumpf die Position 1 zu 1 übernehmen sondern muss diese soweit verschieben wie sich der Spieler bewegt hat. Ich fürchte allerdings, dass es dann zum stocken des chars kommt. Ich schaue mal und melde mich später nochmal falls dem so ist 🤔

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn's Online ist, dann solltest du einfach die Serverpositionen und lokale Positionen voneinander entkoppeln.

Auf dem Server hast du einfach eine imaginäre Fläche, und wenn ein Raumschiff links raus fliegt, kommt es rechts wieder rein. Lokal wendest du die Positionen, die vom Server kommen, nicht einfach blind an, sondern überträgst sie auf die lokale Umgebung und passt dann die Bodenflächen an. Es hilft sehr, sich innerlich von dem Gedanken zu lösen, bei allen Spielern müsse die Szene gleich aussehen. Besonders, wenn du so krass am faken bist, wie du es hier tust ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb Sascha:

Wenn's Online ist, dann solltest du einfach die Serverpositionen und lokale Positionen voneinander entkoppeln.

Auf dem Server hast du einfach eine imaginäre Fläche, und wenn ein Raumschiff links raus fliegt, kommt es rechts wieder rein. Lokal wendest du die Positionen, die vom Server kommen, nicht einfach blind an, sondern überträgst sie auf die lokale Umgebung und passt dann die Bodenflächen an. Es hilft sehr, sich innerlich von dem Gedanken zu lösen, bei allen Spielern müsse die Szene gleich aussehen. Besonders, wenn du so krass am faken bist, wie du es hier tust ;)

Ja das war auch schon mein gedanke. Wenn wir beide zusammen spielen würden und mein Raumschiff bei dir aus der Welt fliegt, kann es mir ja egal sein, weil ich das nicht sehe. So weit war ich auch schon :D. Deswegen wollte ich jetzt wie folgt vorgehen stoße aber schon an ein Problem von PunRPC aber der Reihe nach...

Um Also die Position von Spieler 2 an Spieler 1 zu übermitteln habe ich mir gedacht, dass die Position von Spieler 2 abgefragt wird.
Also das Raumschiff, das bei Spieler 1 angezeigt ist und von Spieler 2 ist, wird gefragt wo er gerade ist. Rückgabewert ist also ein Vector3. Abhängig von der Spielerposition von Spieler 1, wird dieser also wieder um x und z verschoben und dort angezeigt (Ich weiß nicht ob das verständlich ist... aber fast egal denn:)

Jetzt habe ich aber das Problem, dass PunRPC kein Rückgabewert hat. Grund dafür ist, (habe ich bei denen im Forum gefunden) dass nicht klar ist ob es überhaupt ein Objekt gibt, das eine Rückgabe tätigen kann oder vielleicht sogar mehrere. Deswegen stehe ich wieder fast am Anfang.

Hier der Code, mit dem ich das ungefähr vor hatte:

public class MultiplayerPosition : MonoBehaviour
{
    public float offsetX;
    public float offsetZ;

    private PhotonView photonView;

    private void Start()
    {
        photonView = GetComponent<PhotonView>();
    }

    void Update()
    {
        Vector3 currentPosition = photonView.RPC("CurrentPosition", RpcTarget.All); // Hier der Fehler, da kein Rückgabewert vorhanden
        currentPosition.x += offsetX;
        currentPosition.z += offsetZ;
        transform.position = currentPosition;
    }


    [PunRPC]
    public Vector3 CurrentPosition()
    {
        Vector3 returnVector = transform.position;
        returnVector.x -= offsetX;
        returnVector.z -= offsetZ;
        return transform.position;
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Rückgabewerte ergeben bei Networking auch nicht so viel Sinn, weil sie bedeuten würden, dass du eine Anfrage schickst und dann auf eine Antwort wartest. Bei einem nicht ungewöhnlichen Ping von 100 und 60 FPS würde das bedeuten, dass du dafür direkt 6 Frames skipst. Darüber hinaus schickst du eine Anfrage hier an alle anderen Clients... von wem wäre denn da der eine Rückgabewert?

Wenn du den Server unbedingt etwas fragen musst, musst du ein Command schicken und der Server sendet als Antwort einen RPC zurück.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 20 Stunden schrieb Sascha:

Wenn du den Server unbedingt etwas fragen musst, musst du ein Command schicken und der Server sendet als Antwort einen RPC zurück.

Das macht dann keinen Sinn. zumindest, wenn die Latenz zwischen den beiden höher ist. Vor allem sieht es dann etwas seltsam aus, wie das Schiff des anderen herum springt..

Wie gehe ich am besten weiter vor. Das Problem dass ich jetzt habe ist, dass beispielsweise Spieler 1 bereits 5 mal um den Planeten nach Osten geflogen ist und auf der x Koordinate bereits bei x = 250 (Spieler 1 - x = 250, z = 0) ist. Spieler zwei hat das nicht getan sondern ist nach Süden geflogen und steht jetzt auf (Spieler 2 - x = 0, z = -50)

Aber eigentlich stehen jetzt beide am startpunkt und sogar auf dem Selben feld. (Dass die beiden kollidieren sollten lassen wir mal außen vor.

Ich brauche jetzt also eine möglichkeit, die die Spieler korrekt anzeigt heißt also für Spieler 1 steht Spieler 2 auf (x = 250, z = 0) usw. 

Ich habe ein Script geschrieben, welches die Position verschieben soll und es funktioniert genau so wie ich erwartet habe... nämlich dass der jeweils andere Spieler immer hin und her fliegt weil seine Position immer zwischen seiner echten und der neu berechneten hin und her springt.

(Auch wenn ich erwarte die Antwort zu kennen) Kann ich dem Transform einen Wert geben, der kontinuierlich einfach zu seiner x bzw z position hinzuaddiert wird?

Hier ist das oben genannte Script:

    public float offsetX;
    public float offsetZ;

    private PhotonView photonView;

    private void Start()
    {
        photonView = GetComponent<PhotonView>();
        if (photonView.IsMine) Destroy(this);
    }

    void Update() //hier ist egal ob LateUpdate, FixedUpdate oder Update das ergebnis ist das selbe (Wie zu erwarten war)
    {
        Vector3 newPos = transform.position;

        newPos.x += offsetX;
        newPos.z += offsetZ;

        transform.position = newPos;
    }


    [PunRPC]
    public void SetOffset(float x, float z)
    {
        offsetX = x;
        offsetZ = z;
    }

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb Singular:

Wie gehe ich am besten weiter vor. Das Problem dass ich jetzt habe ist, dass beispielsweise Spieler 1 bereits 5 mal um den Planeten nach Osten geflogen ist und auf der x Koordinate bereits bei x = 250 (Spieler 1 - x = 250, z = 0) ist. Spieler zwei hat das nicht getan sondern ist nach Süden geflogen und steht jetzt auf (Spieler 2 - x = 0, z = -50)

Das ist genau das Problem. Auch der Server sollte keine ewig wachsenden Positionswerte nutzen. Und der Server hat auch keinen Grund, irgendetwas herum zu schieben, weil Dinge auf dem Server aussehen können wie sie wollen. Sagen wir also einfach mal, die Welt sieht auf dem Server so aus:

fields-server.pngWenn einer oben aus A rausfliegt, kommt er unten bei C wieder heraus. Ohne Wenn und Aber. Auf dem Server ist die Position eines Spielers damit immer zwischen (0, 0) und (2, 2). Natürlich wird deine Platte nicht 1x1 groß sein, sondern irgendwie größer, aber du verstehst schon.

Wenn dein Client und dein Server miteinander kommunizieren, dann solltest du dafür ein Protokoll haben. Klingt krasser als es ist - du definierst nur halt, auf welche Art kommuniziert wird. In diesem Fall heißt das, dass du einmal festlegst, in welchem Format die Positionen übertragen werden. Ich würde dazu tendieren, nur die Serverposition zu nutzen. Ein Client rechnet also aus, wo auf diesem Grid sein Raumschiff ist, und sendet es dem Server. Der Server sendet ebenfalls nur die Position auf diesem Grid an die Clients, und die rechnen dann aus, wo auf dem Fake-Boden das Raumschiff jetzt genau hingehört.

 

 

 

 

 

fields-local.png

Wenn ein Raumschiff jetzt auf (0.1, 1.9) ist, also ganz weit oben links, dann würde der Client ja Feld A nach unten rechts packen wollen:

Du würdest also in Wirklichkeit das Schiff auf (1.1, 0.9) platzieren. Die "reale" Position ist aber weiterhin (0.1, 1.9).

Von einem zum anderen und wieder zurück rechnen kann sehr anstrengend sein. Ich würde daher immer nur in eine Richtung rechnen. Du nimmst also einfach ein "reale" Position in einem Vektor:

private Vector2 realPlanetaryPosition;

Daraus kannst du dann sowohl die Anordnung der Felder als auch die Position des GameObjects ziehen. Wenn dein Spieler in irgendeine Richtung fliegt, wendest du die Geschwindigkeit auf diesen Vektor an und rechnest dann diese beiden Sachen (Anordnung und Transform.position) neu aus. Anschließend sendest du direkt diesen Wert an den Server. Oder auch nicht. Je nach dem, wie autoritär dein Server ist.

Wenn dann der Server eine Position eines Raumschiffs an den Client schickt, muss dieser diese wieder verarbeiten. Wenn es sich nicht um den Spieler handelt, hat die Position des Raumschiffs ja keinen Einfluss auf die Anordnung der Felder. Aber die "reale" Position muss dann in Abhängigkeit der Feld-Anordnung in eine Transform.position umgerechnet werden.

Ich hoffe, das hilft ein bisschen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Peferkt! Das war der Denkanstoß, den ich gebraucht habe. Ich habe es (hoffe ich) so gemacht wie du gesagt hast. Zum einen wird die Position des Spielers nicht mehr über den PhotonView aktualisiert, sondern das macht der Spieler "selbst". Über die Update Methode habe ich das jetzt laufen, dass der Spieler seine Position an sein Pondon übermittelt. Dieser kennt die Verschiebung und berechnet die entsprechnede Position. Leider scheint es dadurch etwas zu stocken. wahrscheinlich nicht der sauberste weg es über die Update Methode laufen zu lassen oder?

Mal schauen wie das mit anderen Objekten läuft. Die werden ja ähnlich arbeiten^^ wird wahrscheinlich etwas aufwändig. Danke dir. 😃

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 8 Stunden schrieb Singular:

wahrscheinlich nicht der sauberste weg es über die Update Methode laufen zu lassen oder?

Das ist schon zu 100% ne Networking-spezifische Frage, und da kann ich leider kaum helfen 😅

Aber bei einer Handvoll Objekten sollte das eigentlich nicht schon stocken. Vor allem sendest du ja jetzt nicht mehr Daten als vorher, oder?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Naja, kommt halt darauf an, wie der PhotonView arbeitet. Wenn der stumpf auch nur in der UpdateMethode die Position von sich selbst bei den anderen Spielern aktualisiert, dann ist es das gleiche, mit dem Unterschied, dass zu der Position einen Vector3 hinzuzählt. Ich denke diese Operation kostet nicht viel.

Danke dir auf jeden Fall! 😄 Ich eröffne mal einen neuen Thread im Multiplayer Bereich.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...