Jump to content
Unity Insider Forum

TopDown Haus = neue Scene?


xDeejox

Recommended Posts

Hallöchen,

zwar hab ich kein Problem,sondern eigentlich nur eine viell. (naive) Frage. Bin noch ziemlicher Anfänger was Unity angeht. Hab bis jetzt nur meine Idee und sammel Grad Funktionen etc. für mein Game.

Aber nun zu meiner Frage.

Also ich möchte ein TopDown RPG erstellen. Jetzt stellt ich mir bloß die Frage, hab jetzt mein Dorf mit Häusern fertig und in Unity exportiert, aber das Dorf ist jetzt auf eine einzigen Scene,jetzt möchte ich in Häuser gehen, muss ich dafür eine neue Scene anlegen oder kann ich des auch anders lösen? Weil ich denk mir so, wenn ich viele Städte, sagen wir Mal vier, habe und jede Stadt mindestens vier Häuser, werden es ja viele Scenen und mein Spiel ja ziemlich groß und ein 5Gb Spiel,will ich eigentlich nicht erstellen😁

Ich hoffe ihr könnt mir ein paar Tipps geben.

Danke schonmal im Vorraus.

Schöne Grüße aus dem Schwarzwald 

Steve

Link zu diesem Kommentar
Auf anderen Seiten teilen

Szenen sind einfach nur Ansammlungen von Objekten. Wenn du eine Szene lädst, werden alle Objekte der Szene geladen. Wenn du eine Szene entlädst, werden alle ihre Objekte gelöscht.

Ob du jetzt drei Szenen mit jeweils einhundert Objekten oder eine Szene mit dreihundert Objekten baust, macht quasi keinen Unterschied für die Größe deines Spiels.

Ob du für irgendetwas mehr oder weniger Szenen benutzt, ist ganz dir überlassen und sollte einfach danach entschieden werden, was dir besser passt. Wenn du ein Spiel wie Super Mario baust, ist pro Level eine Szene sinnvoll, weil man durch Laden einer neuen Szene das alte Level entfernt und das neue Level lädt. Ist also genau das, was sowieso passieren soll. Wenn du so etwas wie Paper Mario hast, wo du fließend und schnell zwischen Dorf und Haus-Innenleben wechselst, sind einzelne Szenen dafür weniger gut, aber auch nicht unbedingt schlecht. Schließlich kann Unity auch Szenen additiv laden, also ohne dass die vorherige Szene entladen wird. Dann kannst du das Haus einzeln bearbeiten, ohne die ganze Dorfszene dafür zu laden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Servus Sascha,

Danke erstmal für die schnelle Antwort.

Hat mir jetzt schonmal bissle Licht ins Dunkle gebracht.

Welche alternativen gäbe es denn noch, das ganze auf einer Scene zu bekommen? Dass ich es so hinbekommen kann wie bei deinem bsp. von PaperMario dass ich einfach zwischen Dorf und Haus(Innen) wechseln kann?

Gruß Steve

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox Das ist eine mehrschichtige Frage und es gibt keine einzelne richtige Antwort. Eine Szene kann auch additiv und/oder asynchron geladen werden. Bei einer kleinen Szene eine solltest du so geringe Ladezeit haben dürftest, dass es beim Betreten eines Hauses gar nicht auffällt, dass die Inneneinrichtung nachgeladen wird. Man kann aber nicht ohne weiteres Referenzen von einer Szene in eine andere setzen, und wenn die Szene nicht so komplex ist, dass Unity beim Editieren lahm wird, dann kann man auch alles in einer Szene haben.

Es geht ja aber nicht nur um Performance, sondern auch darum, dass man in endlicher Zeit etwas auf die Beine gestellt bekommt ohne dabei wahnsinnig zu werden. Wenn du deinen Innenraum in Extraszenen packst, musst du irgendwie dafür sorgen, dass die in der richtigen Stelle geladen werden, und zum Editieren wäre etwas Editor-Code hilfreich, damit du vernünftig an Außen und Innen gleichzeitig arbeiten kannst.

Eine Alternative wären stinknormale Prefabs. Du kannst bei mehreren gleichen Innenräumen nested Prefabs benutzen (also Prefabs von den Möbeln als Kinder eines Innenraum-Prefabs) oder einfach immer wieder neu zusammenstellen. Was da die Performance angeht, gilt wie immer: Erst drum Sorgen machen, wenn's zum Problem wird. Und wenn das der Fall wird, kannst du machen was @chrische5 sagt. Einfach das Root-GameObject des Hauses mit SetActive an- und ausschalten, wenn das Haus betreten und verlassen wird.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo ihr zwei,

Erstmal wieder danke für die schnellen Antworten,freut mich sehr, dass man hier schnell Hilfe findet.😊

Jetzt zum Thema, ohjee ,dass klingt ja alles komplizierter als ich dachte...

Vorab viell. nochmal zum Verständnis. Ich möchte ein 2D TopDown Spiel im Sinne von "Zelda (SNES)" zum Leben erwecken.Ich arbeite mit eigenen Tiles die ich schon gepixelt habe und meine Map ist schon so gut wie fertig.

Und jetzt hab ich halt mein kleines Häuschen auf der Map (erste Scene) und möchte ins Haus.

Aber ich denk ich werde dass mit den SetActive testen. Klingt für mich einfacher😁 bin leider noch ziemlich am Anfang mit dem Scripting.

Danke euch beiden nochmals.

Gruß Steve

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo

 

Mutmaßlich kann man auch komplette Layer Active setzen. Eventuell kannst du außerhalb und innerhalb verschiedenen LAyern oder Tags zuweisen und entsprechend aktiv und ncihtaktiv setzen. Ich bin selbst noch neu bei unity, aber das wäre zumindest meine erste Idee.

 

Christoph

Link zu diesem Kommentar
Auf anderen Seiten teilen

Finger weg von Tags, ganz allgemein. Die Dinger sind am Anfang einfacher und beißen dafür einen später IMMER. Layer hat man nur begrenzt, die sollte man nur dann benutzen, wenn man es wirklich braucht.

@xDeejox Trigger in den Türrahmen oder eine Interaktions-Komponente ("Drücke A zum Öffnen"), die das Root-GameObject des Innenraumes, also dem GameObject, dem alle Möbel usw. untergeordnet sind, mit SetActive an- und ausschaltet - das ist schon eine sehr gute Lösung, wenn die Gebäude in die Welt integriert sein sollen. Allerdings erwähntest du ja gerade, dass du dich an den alten 2D-Zelda-Teilen orientieren willst, und da wird ja deine Szene schwarz, und dann erscheint aus der Dunkelheit die nächste Szene. Das ist eindeutig ein guter Fall für einzelne Szenen. Wenn du das mal mit Paper Mario vom N64 vergleichst, da klappt das Gebäude auseinander und der Innenraum ist präzise in der Welt platziert. Da wäre das recht viel Aufwand, den man sich vermutlich sparen könnte.

Also... Wenn das genau wie bei A Link to the Past werden soll, dann würde ich verschiedene Szenen laden.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich schmeiss mich mal ungefragt in die Runde. Ich arbeite derzeit selber an einem Spiel wo man Gebäude betreten kann und habe auch alles in einer Scene, weils einfach praktisch ist, weil man so Game Manager dingens nicht Scene übergreifend machen muss.

Also ich handhabe das so, dass ich den Innenbereich einfach weit weg von der eigentlichen Map platziere und mich dann beim betreten entsprechend mit den Koordinaten dort hin versetze. Wie schon erwähnt setze ich ein trigger im Innenbereich der den ganzen schnörkel krims krams aktiviert, damit wenn ich nicht da bin, nicht zu viel berechnet werden muss. Klappt mit SetActive ganz gut! Einfach ein Parent Objekt erstellen wo der ganze Innenbereich drin ist und gut ist.
Den Übergang gestalte ich mit einer einfachen animation via Sprite im Canvas. Damit verdekt man den ruckartigen wechsel der Position ganz gut.

Ich würde in deinem Fall nicht für jeden Innenbereich eine einzelne Scene machen. Viele Spiele verwenden alles mögliche in einer Scene, damit man nur eine Ladesequenz hat, z.B. ist in gta5 der ganze Prolog immer im game vorhanden..

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Jomnitech danke ,

Sowas in der Art hab ich mir ja auch überlegt gehabt und wusste bloß nicht wie man es umsetzen kann.

Aber dass ist denkmal einfacher wie wenn ich zig. Scenen habe etc. Meine Frage jetzt noch was meinst du mit Trigger, eine Art collider sobald ich den berühre,dass dann alles übern ein Script wieder aktiviert wird? Und wenn ich den Raum verlassen alles wieder deaktiviert?

Bin noch ned so erfahren in Scripten. Benutze Unity erst seid zwei Wochen und hab schon stundenlang mir Tutorials reingezogen 😁

Hab meine Map fertig, fürs erste und jetzt kommt dass schwierigste die Feinheiten und das Scripten 🙄

Grüße steve

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox

Also ich habe das so gemacht:

Für den Teleporter habe ich einmal ein EmptyGameobject, welches zwei Cubes als Child hat. Nennen wir sie CubeA und CubeB, jeder Cube hat einmal ein Collider und ist als Trigger und dazu noch das Script.

Das kannst du dann später als PreFab verwenden und einfach CubeA und CubeB dort hin setzen wo du hin und her möchtest.

Das Script kann eigentlich rechts simpel sein. z.B:

public class Teleport : MonoBehaviour
{
    public Transform otherTeleporter;

    private void OnTriggerEnter(Collider other)
    {
        other.transform.position = otherTeleporter.position;
    }
}

Wichtig ist dabei folgendes:

1. In die Transform referenz beim Script, ziehst du bei CubeA den CubeB rein und umgekehrt.

2. Das Teleporter Objekt auf ein Separates Layer setzen. Kannst ja ein erstellen das z.B. teleport heisst. In der Physikeinstellungen entprechend einstellen, das nur der Spieler mit dem Teleporter Layer interagieren kann, damit nicht alles mögliche teleportiert wird. Der Spieler sollte natürlich auch ein eigenes Layer (z.B. Player) haben🙃

3. Beim Teleporter Objekt setzt du den BoxCollider im Inspektor das Center ausserhalb des Meshes. Da dort der Mittelpunkt liegt,  würdest du sonst beim teleportieren genau in den anderen trigger teleportiert werden und wirst somit unendlich hin und her geportet. Den Meshrenderer kannst du natürlich wenn alles passt deaktivieren, dient nur zur orientierung, oder du setzt dir ein Icon im Inspektor.

4. Wenn dein Spieler über keinen Rigidbody verfügt, musst du bei CubeA und CubB einen erstellen, sonst funktionieren die Trigger nicht. In dem Fall die Rigidbody einfach auf Kinematic setzen.

 

Das ganze kannst du natürlich noch mit überblend-Animationen verschönern.

----------

Das mit dem Raum aktivieren und deaktivieren habe ich so gelöst, das der Raum selber einen BoxCollider hat. Dieser hat wiederum ein eigenes Script und aktiviert bei TriggerEnter alles was ich haben möchte und bei TriggerExit, deaktiviert er es wider. Dazu einfach ein emptyGameobjekt erstellen, und alles was im raum akti-deaktiviert werden soll da darunter setzen.

Dem Raum selber dann den besagten Collider geben und ein kleines Script. Kann z.B. so aussehen:

public class EnableDisableTrigger : MonoBehaviour {
    public GameObject target;


    private void OnTriggerEnter(Collider other)
    {
        target.SetActive(true);

    }
    private void OnTriggerExit(Collider other)
    {
        target.SetActive(false);


    }
}

bei Target dann einfach das EmptyGameobject reinziehen.

----

Hoffe ist halbwegs verständlich was ich meine 🙃

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox

Die Cubes waren hier nur ein Beispiel. In 2d Spielen arbeitest du dann mit der 2d Physic, dort wären es dann BoxCollider2d. Ob das jetzt aber ein Box oder Circle oder gar ein Polygon Collider ist, ist völlig egal. Es definiert nur den Bereich der betreten bzw. verlassen werden muss, damit das OnTriggerEnter(bei 2d Physic wäre es dann OnTriggerEnter2D) Funktion ausgeführt wird.

Wenn du ein Objekt hast, mit dem Script drauf und einem Collider(egal welcher Art), wird beim betreten des Colliders, das Event(OnTriggerEnter2D) im Script beim gleichen Objekt ausgeführt.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Jomnitech so Teleport klappt, na endlichen versuchen,aber wer sucht der findet😁 hab nämlich kein rigidbody sondern ein Script dafür,bis ich des endlich Mal gecheckt hab🙄.

Aber anderes Problem hab ich noch. Wie du oben schon erwähnt hast,dass wenn ich die pivot nicht verschiebe,werde ich unendlich hin und her geportetet,genau dass Problem hab ich, aber hab die pivots auch raus genommen und trotzdem.. gibt's da ne andere Lösung für 2D?

Danke schonmal im vorraus und vielen Dank nochmals für die hilfreichen Tipps. Bin so stolz auf mein Teleport Script 😅

Gruß steve

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox

vor 9 Stunden schrieb xDeejox:

hab nämlich kein rigidbody sondern ein Script dafür,bis ich des endlich Mal gecheckt hab🙄.

Hab ich aber erwähnt 😛

vor 9 Stunden schrieb xDeejox:

Aber anderes Problem hab ich noch. Wie du oben schon erwähnt hast,dass wenn ich die pivot nicht verschiebe

pivot ist hald zentrum des Sprites, nicht zentrum des Objekts 🙃
Aber um nicht unnötig zu verkomplizieren, es gibt eine simple Lösung. Du kannst deine Pivots usw. alles auf 0 lassen und erstellst einfach noch ein unterobjekt unter dein TeleporterA(CubeA) und TeleporterB(CubeB ) Objekt, oder wie auch immer du die beiden genannt hast.

Den Teleporter mit dem Trigger drauf schiebst du dann genau dort hin wo die Tür oder so ist. das Unterobjekt(nennen wirs TeleporterChildA und TeleporterChildB)  davon, schiebst du dann dort hin wo man sein soll wenn man zurückkommt, also etwas ausserhalb des Trigger-Ojekts. (Man könnte auch das script erweitern das erst geschaut wird ob man den trigger verlassen hat bis man erneut portet, aber will das jetzt nicht verkomplizieren).

Jetzt ziehst du in das Script(bei otherTeleporter) beim Teleporter A einfach das TeleporterChildB hinein und bei TeleporterB das TeleporterChildA.
Nun sind dies die Punkte wo du landest wenn du den Teleporter Trigger betrittst.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Jomnitech

Guten Morgen, 

Okay dass wäre viell. Eine Lösung. 

Die andere wie ich es glaub besser finde wäre mit nem boolschen wert, 

Könntest du mir dies erklären, find im Netz leider ned so dass richtige. 

So dass es, wie du kurz erwähnt hast, abfragt ob ich runter bin und dann erst wieder aktiviert. 

Danke schonmal im vorraus 

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox

Kann man alles machen :)

Könnte dann so aussehen:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Teleporter : MonoBehaviour
{
    [Header("Hier Zielort Teleporter einfuegen")]
    public GameObject otherTeleporter; // Im Inspektor den Zielteleporter hier einfuegen.
    private Teleporter scrTeleport;
    [HideInInspector]public bool hasTeleportet = false;

    private void Start()
    {
        scrTeleport = otherTeleporter.GetComponent<Teleporter>(); 
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(scrTeleport != null)
        {
            if (!hasTeleportet) // Checkt ob bereits teleportiert wurde. Falls ja wird erst wieder aktiv wenn der Triggerbereich verlassen wird.
            {
                scrTeleport.hasTeleportet = true;
                collision.transform.position = otherTeleporter.transform.position;  // setzt den Spieler an den Ort des anderen Teleporter
            }
        }
        else
        {
            Debug.Log(this.name + "Teleporter fehlt");  //Fehlermeldung falls kein Teleporter im Inspektor eingefuegt wurde.
        }
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        hasTeleportet = false;   // Setzt den Teleporter zurueck, wenn der Triggerbereich verlassen wurde.
    }
}

Hierfür benötigst du folgendes:

- Ein Objekt mit einem 2dCollider. (Häkchen bei isTrigger nicht vergessen)

- Das Obige Script auf diesem Objekt.

Thats it. Kannst du dann z.B. als Prefab abspeichern (einfach aus der Scene unten in die Leiste ziehen.)

In der Scene benötigst du dann mindestens zwei Teleporter Objekte, damit du dann auch wo hin kannst ;), du ziehst dann einfach den Zielort Teleporter in das freie Feld.

Habe möglichst alles Kommentiert, damit du auch weisst was passiert, sollst ja auch was lernen 😛

 

Habe dir noch ein Demo Package angehängt, damit du besser verstehst wie es gedacht ist. Das Package  unter Assets > Import Package importieren. Mach am besten ein neues Projekt und importier es dort, damit du dir das aktuelle Spiel nicht ev. verstellst.

Hoffe das hilft dir weiter. Falls du Fragen hast, immer her damit.

TopDownPackage.unitypackage

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Jomnitech funktioniert leider nicht🙄

Deine Demo perfekt, so soll es aussehen.

Aber bei mir leider Ebbe...

Das Problem an der ganzen Sache ist , ich benutze kein Rigidbody für mein Player. Hab ihn dann auch Mal zugefügt geht trotzdem nicht.

Ich verwende momentan die Scripts aus nem Tutorial von Udemy und da hat er ne neue Basisklasse erstellt für den Hero collider. Denk dass es daran liegt.

Aber wie ich umscripten kann,dauert wohl noch ne Weile...

Ich bedanke mich trotzdem herzlich für die Hilfe und die Tipps. Werd es denk Mal mit der einfachen Variante machen 😁 fürs erste Spiel..geht's ja 

Gruß steven

Link zu diesem Kommentar
Auf anderen Seiten teilen

@xDeejox

vor 7 Stunden schrieb xDeejox:

Das Problem an der ganzen Sache ist , ich benutze kein Rigidbody für mein Player. Hab ihn dann auch Mal zugefügt geht trotzdem nicht.

Der Rigidbody ist nur eine Komponente, ob du den für deine Bewegung verwendest, oder nur für das Triggerverhalten ist im Prinzip egal. Du kannst problemlos einen Rigidbody hinzufügen den auf Kinematic setzen und dein Spieler weiterhin über Udemy Script über die Transforms bewegen, dazu musst du nichts "umscripten".

vor 7 Stunden schrieb xDeejox:

Hab ihn dann auch Mal zugefügt geht trotzdem nicht.

Wenn sich da nix tut, hätte ich gesagt das der Layer der dem Spieler zugewiesen ist und der Layer der dein Teleporter hat, in der Physic2d Einstellungen nicht miteinander reagieren.
In dem Fall einfach mal schauen welcher Layer dem Spielder und welcher Layer dem Teleporter zugewiesen ist und ob die sich in den Einstellungen(Edit>Project Settings>Physic2d) kreuzen.

layers.thumb.png.bec0bdfdea56ecb0124db80aff855cfd.png

-------------------------------------------------------------------------------------------------------------------------------------------

Variante 2

-------------------------------------------------------------------------------------------------------------------------------------------

Falls du aber gänzlich auf die Physic verzichten möchtest, kann man das auch tun. Dazu hat @Sascha mir mal was schickes geschrieben. Das funktioniert dann über eine Distanzabfrage. Nachteil hierbei, du kannst keinen beliebigen Bereich auswählen, sondern hald eben nur den Umkreis abfragen.
Originalbeitrag findest du hier:

 

Ich hab das mal auf 2d runtergebrochen, sieht dann etwa so aus:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TeleportRadius : MonoBehaviour
{
    [Header("Hier Zielort Teleporter einfuegen")]
    public GameObject otherTeleporter; // Im Inspektor den Zielteleporter hier einfuegen.
    [Header("Hier den Spieler einfuegen")]
    public Transform player;        // Referenz zum Spieler ob er in der naehe ist.
    [Header("legt den Bereich fest ab wo der Teleporter funtioniert")]
    public float teleporterRadius = 1f;
    private TeleportRadius scrTeleport;
    [HideInInspector] public bool hasTeleportet = false;

    private void Start()
    {
        scrTeleport = otherTeleporter.GetComponent<TeleportRadius>();
    }

    public static bool CheckIfCloserThan(Vector2 a, Vector2 b, float maxDistance)
    {
        var maxDistanceSquared = maxDistance * maxDistance;

        var distanceSquared = (a.x - b.x) * (a.x - b.x) +
                              (a.y - b.y) * (a.y - b.y);  


        return distanceSquared <= maxDistanceSquared;
    }

    private void FixedUpdate()
    {

        var isInside = CheckIfCloserThan(transform.position, player.position, teleporterRadius);

        if (isInside && !hasTeleportet)
        {
            OnEnterRange();
        }
        else if (!isInside && hasTeleportet)
        {
            OnExitRange();
        }

    }

    private void OnEnterRange()
    {
        scrTeleport.hasTeleportet = true;
        player.transform.position = otherTeleporter.transform.position;
    }
    private void OnExitRange()
    {

        hasTeleportet = false;
    }


    // Zeichnet einen Kreis der so gross ist wie der "Trigger" Bereich
    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(transform.position, teleporterRadius);
    }
}

In dieser Variante brauchst du weder Layer noch Rigidbodys noch sonst was. Alles was du brauchst ist zusätzlich zur Referenz zum anderen Teleporter, auch eine Referenz zum Spieler.
Diesen einfach in das entsprechende Feld reinziehen. Je nach dem wie gross bzw. wie viele Teleporter du am Ende im Spiel hast, kann man das auch automatisieren, für den Anfang aber lassen wir das mal.

Wichtig zu wissen ist auch, das erst dann teleportiert wird, wenn der Mittelpunkt deines Spielers im Kreis ist.

DemoPackage findest du im Anhang.

TopDownRangeTeleporter.unitypackage

Link zu diesem Kommentar
Auf anderen Seiten teilen

@Jomnitech So da wäre ich wieder, hab ein bissle auf mich warten lassen 😉

War ein bissle auf und ab, aber gute Neuigkeiten ich hab mein TeleportScript. 

Die schlechte Nachricht, der Script von dir hat leider nicht funktioniert, ich bin da viell. noch zu unerfahren um

es selbst zulösen. Hab mein Dozenten angeschrieben und der hat es mir ermöglicht, dass es auch ohne Rigidbody funktioniert.

Aber ich danke dir trotzdem für all deine Mühen und Ideen. Wenn ich mal wieder ein Problem habe, wende ich mich einfach gleich an dir.

Gruß Steven

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...