Jump to content
Unity Insider Forum

Jolinah

Members
  • Content count

    9
  • Joined

  • Last visited

  • Days Won

    3

Jolinah last won the day on October 14

Jolinah had the most liked content!

Community Reputation

3 Neutral

About Jolinah

Contact Methods

  • Website URL
    http://www.michael-zehr.ch

Profile Information

  • Gender
    Male
  1. Jolinah

    Inputfield Inhalt ind UI-Text ausgeben

    Menu Editor > Preferences > External Tools > External Script Editor > Browse... Dann kommt ein Dialog in dem du selber nach der Exe von MonoDevelop suchen musst. Das befindet sich normal im Ordner von Unity, z.B. C:\Programme\Unity\MonoDevelop\MonoDevelop.exe. Dann müsste es wieder funktionieren. Was das Script angeht: Mein Code sollte zumindest deinen Fehler beheben. Je nachdem was du genau bezwecken willst, stellt sich die Frage wann der Text vom InputField in das Text übernommen werden soll. Wenn sich das jedes Frame auf den aktuellsten Stand aktualisieren soll, dann muss der Code anstatt in die Methode Awake() in Update(): void Update() { T_Name.text = InputField1.text; } Und nicht vergessen, die Felder auch im Inspector mit der Maus zuzuweisen.
  2. Jolinah

    Inputfield Inhalt ind UI-Text ausgeben

    Hallo, das Text-Element hat wie das InputField ebenfalls ein text-Property. Du willst ja den Text des Text-Elements festlegen, nicht das Element selber verändern: T_Name.text = InputField1.text; Hoffe das hilft
  3. Hallo, ich glaube da fehlt noch das eulerAngles nach rotation Quaternion.Euler(shotSpawnGun.rotation.eulerAngles.x, shotSpawnGun.rotation.eulerAngles.y, shotSpawnGun.rotation.eulerAngles.z)
  4. Hallo, da der AlarmManager nur 1 inSicht hat, konkurrieren sich beide Kameras. Die eine setzt AlarmManager.inSicht auf false, da der Spieler nicht sichtbar ist und die andere auf true, da der Spieler sichtbar ist. Abhängig davon, welches iUpdate (der beiden Kameras) als letztes aufgerufen wird gilt dann dieser Wert (und in deinem Fall scheint das false zu sein). Um das zu lösen gibt es mehrere Möglichkeiten: z.B. Events oder man setzt inSicht des AlarmManagers jedes Frame oder alle x Sekunden am Anfang auf false und die Kameras setzen es höchstens auf true, aber niemals auf false.
  5. Jolinah

    UnloadSceneAsynchron

    Sorry, für die späte Antwort Das Problem ist, dass SceneManager.GetSceneByName nur geladene Szenen findet. In LoadScreen() startest du aber 2 Coroutinen gleichzeitig und versuchst auch die Szene bereits aktiv zu setzen, während sie noch am Laden ist. Ich würde dir raten, dort nur die Coroutine Anzeige() zu starten. Das LoadingScreen() würde ich dann innerhalb der Methode Anzeige() anstelle von // Warten bis der Ladezyklus beendet ist do { yield return new WaitForFixedUpdate(); } while (async.progress < 0.9f); aufrufen, mit: yield return StartCoroutine(LoadingScreen(scene)); Auf diese Weise wartet Unity ähnlich wie bei yield return new WaitForSeconds() nicht eine bestimmte Anzahl Sekunden, sondern so lange bis die andere Coroutine fertig ist. Dann anstelle von // Scene freigeben async.allowSceneActivation = true; einfach die Szene aktivieren, da sie ja nun geladen wurde: // Scene aktivieren SceneManager.SetActiveScene(SceneManager.GetSceneByName(scene)); Ich hoffe das hilft, falls du das Problem nicht bereits selber lösen konntest
  6. Jolinah

    UnloadSceneAsynchron

    Hi, wie wird das neue Level geladen? Ich nehme an, es gibt eine Szene mit dem Ladebildschirm und während dieser wird das eigentliche Level asynchron geladen? Dann muss die Szene mit dem Ladebildschirm vermutlich synchron geladen werden oder zumindest sobald sie geladen ist, auch als aktive Szene markiert werden (SceneManager.SetActiveScene). Wobei das natürlich auch automatisch passieren sollte, sobald nur noch 1 Szene geladen ist (sprich das Intro entladen wurde). Intressant dürfte auch der Parameter LoadSceneMode von LoadScene sein. Dort kannst du angeben dass du eine neue Szene laden willst (die mit dem Ladebildschirm) und das die einzige sein soll (LoadSceneMode.Single). Dann werden automatisch alle anderen entladen.
  7. Hm, schade.. Ich denke Asset Bundles machen vor allem Sinn, wenn man sie asynchron laden kann, während man vorher noch etwas anderes anzeigt. Alle in einer Scene verlinkten Prefabs werden beim Laden der Scene halt auch geladen. Heisst, wenn die 150 public Felder auf Prefabs verweisen, werden die alle geladen. Da könnte man nur die wichtigsten direkt verlinken und die restlichen eben erst wenn sie wirklich benötigt werden laden oder schon von Anfang an laden, jedoch asynchron.
  8. Hallo, Zuerst zur zweiten Frage, da die etwas einfacher zu beantworten ist: Im neuen UNet (mit der High Level API) gibt es Server, Host und Client. Ein Server ist ein dedizierter Server, ein Host ist dagegen ein Server mit einem lokalen Spieler. Das einfachste Setup ist ein GameObject mit einem angehängten NetworkManager-Script und zusätzlich dem NetworkManagerHUD-Script zu erstellen. Dann wird ein Prefab mit einem NetworkIdentity-Script benötigt, welches man beim NetworkManager als Spielerobjekt zuweist. Ausserdem muss man noch eine Online- und eine Offline-Szene erstellen und dem NetworkManager zuweisen. Sobald man dann das Spiel startet und Server/Host im GUI auswählt, wird die Online-Szene geladen und beim Host das Spieler-Objekt erzeugt (beim Server natürlich nicht, da es noch keinen Client gibt). Und nun zur anderen Frage: Grundsätzlich ist UNet ein Server/Client-Modell und es ist durchaus möglich die Autorität dem Server zu überlassen. In Tutorials zeigt und empfiehlt Unity jedoch meistens das Modell mit der Client-Autorität, vermutlich weil es für Anfänger halt wesentlich einfacher ist. Die Server-Autorität ist wirklich ein komplexes Thema (zumindest bei schnellen Action-Games). In Spielen wie Half-Life etc. wird meistens die Kombination von Client Prediction (auf dem Client) und Lag Compensation (auf dem Server) angewendet. Es gibt dazu auch von Valve einen Artikel, den ich sehr empfehlen kann: https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization Grob zusammengefasst: Der Client sammelt tatsächlich alle Inputs zusammen mit der deltaTime und der absoluten Zeit bzw. Netzwerkzeit. Server und Client teilen sich die exakt gleiche Physik und Update-Logik. Der Client führt die Physik für jedes Input sofort lokal aus (Spieler bewegt sich lokal ohne Lag). Ausserdem schickt er diese Inputs an den Server, welcher die gleichen Inputs für die gleiche deltaTime abarbeitet und in Form von Status-Updates (Position etc.) bestätigt. Der Client verwirft die gesammelten Inputs nicht sofort nach dem Senden, sondern behält diese noch etwas länger. Empfängt der Client nun vom Server ein Status-Update, dann steht dort drin neben der Position etc. auch welches das letzte vom Client abgearbeitete Input war (z.B. eine Id, oder die Netzwerkzeit). Da der letzte verarbeitete Input aufgrund des Lags in der Vergangenheit liegen muss, heisst das auch dass der Client in der zwischenzeit vielleicht 5 weitere Inputs gesammelt und verarbeitet hat. Also setzt man den Spieler nun an die vom Server gemeldete Position, aber arbeitet die 5 Inputs die zuvor schonmal abgearbeitet wurden noch einmal ausgehend von der Server-Position ab. Das heisst im Endeffekt: Der Server korrigiert den Client zwar, der Client versucht jedoch das Lag zu umgehen, indem er aufgrund der Inputs vorausrechnet wo er sich eigentlich befinden müsste, wenn er einen Ping von 0ms hätte. Falls es bei den Korrekturen zu kleinen Rucklern kommt, kann man sich auch die Abweichung merken und diese über die Zeit ausgleichen statt sofort (Interpolation). Die Lag Compensation findet hingegen auf dem Server statt. Diese dient dazu, dass Spieler exakt auf andere Spieler zielen können und nicht vorauszielen müssen. Es wird davon ausgegangen, dass alle nicht lokalen Spieler beim Client interpoliert werden (das heisst z.B. 100ms in der Vergangenheit dargestellt werden, dafür flüssig, ohne Ruckler). Der lokale Spieler befindet sich aufgrund der Client Prediction in der Gegenwart (vom Server aus gesehen, sogar in der Zukunft), während sich nicht lokale Spieler 100ms in der Vergangenheit befinden... Der Server speichert zu diesem Zweck für eine bestimmte Zeit lang alle Welt-Updates (Positionen aller Spieler in der Welt, Zeitpunkt etc.). Empfängt er nun von einem Client ein Input das verarbeitet werden soll, versetzt er zuerst alle anderen Spieler in die Vergangenheit zurück (sei es für Kollisionen oder Raycasts). Dafür muss man die Latenz des Clients kennen, sowie dessen verwendete Interpolationszeit für nicht lokale Spieler (z.B. 100ms). Man rechnet also die Input-Zeit minus die Latenz minus die Interpolationszeit. In diese Zeit versetzt man alle anderen Spieler zurück, indem man die zwei zwischengespeicherten Welt-Updates heraussucht die direkt vor dieser Zeit und danach liegen. Zwischen diesen beiden Updates werden die Positionen der anderen Spieler aufgrund der berechneten Zeit dann interpoliert. Sind alle anderen Spieler zurückversetzt wird nun das Input verarbeitet. Danach werden die anderen Spieler jedoch wieder an die ursprüngliche Position (Gegenwart) versetzt. Den lokalen Spieler lässt man wo er ist. Also schon sehr komplex das Ganze... Hier noch ein paar Unity-spezifische Tipps wie man die Server-Autorität mit der High Level API umsetzen kann: Es empfiehlt sich eine eigene Klasse zu erstellen die vom NetworkManager ableitet und einige Methoden überschreibt. Unity bietet die Möglichkeit von ClientRPCs (Server zu Client) und Commands (Client zu Server). Es ist natürlich verlockend die Client Inputs via Commands zu senden. Aus Gründen der Performance empfiehlt es sich jedoch eigene "Messages" zu erstellen, die von der Klasse MessageBase ableiten. Im eigenen NetworkManager kann man die Methode OnStartServer überschreiben und dort die Message registrieren mit: NetworkServer.RegisterHandler(...) Beim Client (z.B. innerhalb eines NetworkBehaviours) kann man die eigenen Messages dann senden via connectionToServer.Send(messageId, message) Ich hoffe das hilft dir etwas weiter
  9. Hallo zusammen, mein erster Post hier, obwohl ich schon länger registriert bin Das kann durchaus an der Anzahl Assets im Resources-Ordner liegen. Denn alle Ressourcen werden beim Kompilieren in eine einzige Datei geschrieben. Diese Datei enthält auch einen Index. Der Index dient dazu die Resources-Pfade aufzulösen, so dass Unity weiss, wo sich das Objekt in der Datei befindet. Das Problem ist jedoch, dass der Index mit zunehmender Anzahl an Assets nicht linear wächst, sondern immer grösser wird. Dies betrifft leider auch die Ladezeiten des Index. Die Assets selber werden beim Start nicht geladen, der Index jedoch schon. Ich weiss jetzt nicht wie viele Assets du im Resources-Ordner hast, aber Unity meint zumindest dass es bei 10'000 Assets schon mal ein paar Sekunden dauern könne bei älteren Mobilgeräten. Generell rät Unity in den meisten Fällen davon ab, das Resources-System überhaupt noch zu verwenden ("Best Practices for the Resources System: Dont' use it."). Neuerdings würde man das wohl eher über AssetBundles lösen, die z.B. von einem Webserver oder direkt vom Dateisystem nachgeladen werden können. Allerdings kenne ich mich damit auch noch nicht so gut aus. Quelle: https://unity3d.com/de/learn/tutorials/topics/best-practices/resources-folder PS: Wenn ich das im Artikel richtig verstanden habe, wäre eine Möglichkeit ein Script zu erstellen, welches eine Liste/Array von Prefabs referenziert. Dann erstellst du ein Empty-Objekt mit diesem Script drauf, machst davon ein Prefab und fügst nur dieses Prefab in den Resources-Ordner ein, während alle anderen Prefabs ausserhalb vom Resources-Ordner sind. Dann kann man mit Resources.Load() dieses Script-Objekt mit allen referenzierten Prefabs laden. Weil die Prefabs davon referenziert werden, werden automatisch auch die Prefabs mitgeladen. Da der Resources-Ordner dann sehr klein ist, sollte dies das Laden der - fast leeren - Szene kaum beeinträchtigen.
×