• Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011

Leaderboard


Popular Content

Showing most liked content since 07/18/2017 in all areas

  1. 6 likes
    C# ist schon seit langer Zeit das Mittel der Wahl für Programmieren für Unity. Der Support für Boo wurde gänzlich abgeschafft, und Unitys JavaScript-Variante beschert einem mehr Probleme als Vorteile. Leider stellt C# eine etwas größere Einstiegshürde dar als "UnityScript", aber nach eventuellen anfänglichen Scherereien wird es immer einfacher zu verwenden. Dieses Tutorial richtet sich an reine Programmieranfänger, aber auch Erfahrenere, die neu in Unity sind, können etwas davon haben. Dieses Tutorial ist weniger ein "Wie mache ich XY", als mehr eine generelle Einführung, die alle folgenden Schritte in der Welt von C# in Unity (besser) verstehbar machen soll. Am Ende wird also kein großartiges Ergebnis zum Zeigen vorliegen, aber dafür solltest du ein gutes Verständnis dafür haben, was in Unity überhaupt passiert. Mein Code als Komponente Wer dieses Tutorial liest, hat vermutlich den grundlegenden Workflow des Unity-Editors bereits vor Augen gehabt. Objekte in einer Szene (GameObjects) bestehen aus einer Reihe von Komponenten, die das GameObject ausmachen. So ist ein GameObject mit einem Collider etwas, wogegen andere Objekte prallen können, und eines mit MeshRenderer und MeshFilter ist ein sichtbares 3D-Modell. Folglich ist ein GameObject mit MeshRenderer, MeshFilter und Collider ein sichtbares 3D-Objekt, mit dem man kollidieren kann. Ein GameObject ist also die Summe aller seiner Komponenten. Für jedes Spiel muss das, was passieren soll, programmiert werden. Im Unity-Kontext kommt der Code, den man dabei schreibt, in Form von Komponenten zum Einsatz. Man schreibt also etwas Code in eine Datei und fügt diesen als Komponente zu einem GameObject hinzu. Diese Scripts sind größtenteils dazu da, das GameObject, dem sie hinzugefügt werden, zu beeinflussen. Ein Beispiel wäre ein Script, das das Objekt rotieren lässt. Man nehme also einen MeshRenderer, einen MeshFilter, einen Collider und dazu dieses Script als Komponente. Das ergebnis ist ein sichtbares 3D-Objekt, mit dem man kollidieren kann und das sich dreht. Diese Grundidee, in welcher Form ein Script das Spiel, das man baut, formt und beeinflusst, ist immer im Hinterkopf zu behalten. Mein erstes Script Um ein neues Script zu erstellen, einfach mit Rechts in die Assets (oder oben links aus "Assets") klicken, dann auf "Create", dann "C# Script". Die entstandene Script-Datei kann und sollte man direkt vernünftig benennen. Dabei ist es nicht unsinnvoll, sich an Unitys Namensgebung zu orientieren, denn der Dateiname wird gleichzeitig der Name der Komponente. Neben "MeshRenderer", "Collider" und "Light" würde also "SimpleRotation" oder "SimpleRotator" passen. Öffnet man das Script, wird der eingestellte Script-Editor gestartet. Zu empfehlen ist Visual Studio, aber hier kann man nach eigenen Präferenzen gehen. Was man dann sieht, ist in etwa folgendes: using UnityEngine; using System.Collections; public class ScriptName : MonoBehaviour { // Use this for initialisation void Start() { } // Update is called once per frame void Update() { } } Sehen wir uns die Einzelteile davon einmal an, damit wir anfangen können, darin zu arbeiten. Am Anfang stehen diese beiden Zeilen: using UnityEngine; using System.Collections; Diese Zeilen heißen "Imports" oder "Using-Statements". Sie geben für den Rest des Codes an, was alles an bereits existierendem Code bekannt sein soll. Unity ist ein riesiger Haufen Code, den unser Code kennen muss, damit man damit arbeiten kann. Die Light-Komponente z.B. ist irgendwo in "UnityEngine" vorhanden, und wenn man von einer solchen Komponente die Farbe ändern will, dann muss bekannt sein, was ein Licht überhaupt ist. Es ist also etwa so, als würde ein Schullehrer ein neues Thema anfangen und zum Beginn der Stunde einige vorherige Themen in's Gedächtnis rufen, auf denen der neue Stoff aufbaut. System.Collections ist standardmäßig mitimportiert, wird aber erst einmal gar nicht gebraucht. Diese Zeile kann man sogar problemlos löschen, bevor man weiter macht. Als nächstes folget ein Haufen Begriffe, gefolgt von einem Rumpf. Einen Rumpf erkennt man immer an den geschweiften Klammern { } . public class ScriptName : MonoBehaviour { // Das hier ist im Rumpf } Der C#-Standard ist eigentlich, die geschweifte Klammer in die nächste Zeile zu machen. Ist absolut Geschmackssache - bei mir sieht das jedenfalls so aus: public class ScriptName : MonoBehaviour { // Das hier ist im Rumpf } Wir sehen hier also etwas Text, gefolgt von einem Rumpf. In den allermeisten Fällen ist das, was vor dem Rumpf steht, mit dem Rumpf verbunden, oder besser: Der Rumpf gehört zu diesem Text. Was also sagt dieser Text aus? public class ScriptName : MonoBehaviour Zuerst einmal steht da "public class". Das public können wir jetzt erstmal ignorieren - es steht da und macht irgendetwas. "class" ist da schon wichtiger - es sagt aus, dass im folgenden Rumpf eine so genannte Klasse deklariert wird. Eine Klasse ist ein Begriff aus der Objektorientierten Programmierung und ist eine Art Bauplan für Objekte. Der Bildschirm vor dir ist sozusagen ein Objekt (oder "Instanz" oder "Exemplar") der Klasse "Bildschirm". Oder vielleicht der Klasse "Flachbildschirm", je nach dem, wie spezifisch da deklariert wurde. In unserem aktuellen Spezialfall ist ein Objekt eine Komponente. Man kann mehreren GameObjects eine Light-Komponente geben, und sie sind alle mehr oder weniger gleich. Sie alle haben eine Farbe, eine Intensität und mehr Eigenschaften, und sie alle machen auf irgendeine Weise Licht in der Szene. Und doch können sie alle unterschiedlich sein: Das eine Licht ist rot, das andere blau. Es handelt sich hierbei um verschiedene Objekte, aber der grundlegende Aufbaum, also die Klasse, ist immer dieselbe: Light. Wann immer wir in einer objektorienterten Sprache wie C# Code schreiben, existiert dieser in Form von Klassen. Jedes Script ist eine Klasse und jedes Mal, wenn wir das Script zu einem GameObject hinzufügen, wird ein neues Objekt, also eine neue Komponente dieser Klasse erstellt, die dann auf diesem GameObject existiert, bis sie oder das GameObject wieder gelöscht werden. Der nächste Begriff kommt uns bekannt vor: Es ist der Dateiname und damit der Name der Klasse, die wir hier schreiben wollen. Anschließend steht da noch etwas kryptisches: : MonoBehaviour Hier steckt eine ganze Menge drin, aber zu diesem Zeitpunkt kann man diesen Teil vereinfachen und sagen: Dieser Ausdruck sorgt dafür, dass Objekte unserer Klasse auch wirklich Komponenten sind. Löscht man diesen Teil, kann man das Script anschließend nicht mehr zu einem GameObject hinzufügen. Damit haben wir jetzt die Klassendefinition gesehen. Der darauffolgende Rumpf wird alle möglichen Informationen über unsere Klasse enthalten, so wie der Rumpf der Light-Klasse irgendwo in UnityEngine den Code enthält, der Objekte anleuchtet und der angibt, dass eine Lichtkomponente eine Farbeigenschaft hat. Im Rumpf stehen bereits irgendwelche Dinge, die wir uns gleich ansehen werden. Zuerst einmal gehen wir aber zurück in den Editor und sehen uns eine wichtige Kleinigkeit an - und zwar, wie man ein Script einem GameObject hinzufügt. Das ist denkbar einfach: Per Drag & Drop kann man die Datei auf den leeren Platz eines GameObjects im Inspektor ziehen; unter die anderen Komponenten. Man kann sie auch auf das GameObject in der Hierarchie ziehen oder den "Add Component"-Button im Inspektor benutzen. Scripts sind standardmäßig in der Kategorie "Scripts". Methoden Zwei Absätze weiter oben habe ich zwei Beispiele dafür gegeben, was in einer Klasse drinsteht: Die Light-Komponente leuchtet Objekte an, sie tut etwas, und sie hat eine Fabreigenschaft, sie ist irgendwie. Diese beiden Dinge, "wie es ist" und "was es tut" sind genau die beiden Bausteine, aus denen eine Klasse aufgebaut ist. Fangen wir an mit "was es tut". Die Abläufe dessen, was ein Objekt tut, sind in so genannten Methoden deklariert. Von denen hat unser neues Script bereits zwei: // Use this for initialisation void Start() { } // Update is called once per frame void Update() { } Eine leere Methode ist nicht ganz unähnlich einer leeren Klasse aufgebaut. Wieder haben wir einnige Worte, gefolgt von einem Rumpf. Diese beiden Methoden heißen Start und Update. Bei beiden steht vorher "void" und beide haben danach runde Klammern ohne etwas darin. Beides wird für uns erst später relevant und kann daher ignoriert werden. Interessant sind für uns die Namen der Methoden, aber dazu gleich mehr. Eine Methode ist grundätzlich eine Reihe von Anweisungen, die nacheinander ausgeführt werden, wenn die Methode aufgerufen wird. Eine Methode aufzurufen ist verlgleichbar damit, einen Knopf bei einem Gerät zu drücken. Plötzlich passieren im Gerät irgendwelche Dinge, und vielleicht kommt sogar ein sichtbares Ergebnis heraus, zum Beispiel eine Flasche Wasser. Allem voran steht aber das Drücken des Knopfes, oder eben das Aufrufen der Methode. Um eine Methode aufzurufen, ist es sozusagen erst einmal nur nötig, ihren Namen zu schreiben. Das testen wir gleich, aber vorher sehen wir uns die beiden Methoden an, die wir schon haben. Über den Methoden stehen so genannte Kommentare. Alles, was rechts von "//" steht, ist ein Kommentar und wird vom Computer komplett ignoriert. Man kann dort also alles hinschreiben, was den Code erklärt, wenn gewünscht auch auf deutsch. Die beiden Kommentare über unseren Methoden beschreiben eine Besonderheit, wenn man mit Unity entwickelt. Anhand ihrer Namen nimmt sich Unity das Recht, diese Methoden geradezu magisch im richtigen Moment aufzurufen. Eine Methode mit dem Namen "Start" wird einmalig aufgerufen, wenn das Objekt neu entsteht - das versteht sich inklusive aller Objekte zum Start des Spiels. Innerhalb eines Methodenrumpfs können jetzt unter anderem weitere Methoden aufgerufen werden. So entsteht eine sinnvolle Kette von Abläufen. Die verschiedenen Objekte werden hierbei wie eine Firmenhierarchie: Ein Kunde ruft in einer Firma an und bestellt eine Dienstleistung. Die Sekretärin informiert die Chefin. Die Chefin schickt einen Mitarbeiter los. Jede dieser Interaktionen ist eine mögliche Metapher für jeweils einen Methodenaufruf, und die verscheidenen Leute sind die Objekte. Wir bauen jetzt eine ganz simple Kette und fügen folgenden Code in die Start-Methode ein: // Use this for initialisation void Start() { Debug.Log("Hallo!"); } Debug.Log ist eine bestimmte Methode. Warum sie so heißt, wie sie heißt und wieso da ein Punkt drinsteckt, ist erst einmal egal. Die runden Klammern deuten den Methodenaufruf an. In den Klammern steht dieses Mal allerdings etwas. In den Anführungszeichen steht ein String, eine Zeichenkette, also etwas, das Worte, Sätze oder ganze Texte beinhalten kann. Debug.Log nimmt diesen String und schreibt ihn in Unitys Konsole. Am Ende jeder Anweisung wie dieser steht ein Semikolon ; , das die Anweisung beendet. Speichere das Script und ab zurück zu Unity. Stelle sicher, dass irgendein Objekt in der Szene das Script als Komponente hat und starte das Spiel. Du müsstest in der Konsole (Strg + Shift + C) und ganz unten links im Editor das "Hallo!" sehen können. Hier hat also Unity Start() aufgerufen und in Start wurde dann wieder Debug.Log aufgerufen. Der String in den Klammern nennt sich dabei Parameter. Ein Parameter spezifiziert genauer, was eine Methode tun soll. Während bei einigen Tätigkeiten keine Parameter nötig sind (z.B. "starte das Auto"), benötigen einige andere genauere Angaben, wie sie im jeweiligen Moment zu funktionieren haben (z.B. "Tritt das Gaspedal" - aber wie doll?). Bei Debug.Log muss angegeben werden, was genau in die Konsole geschrieben werden soll. Würde man der Methode nichts geben, also die runden Klammern leer lassen, würde der ganze Aufruf keinen Sinn mehr ergeben und der Code wird als fehlerhaft erkannt. Jetzt machen wir aber mal etwas Unity-bezogenes. Das Drehskript Wir bauen jetzt ein Skript, das das Objekt dreht, auf dem es als Komponente liegt. Zuerst machen wir das in der Start-Methode. Unser Objekt wird also einmalig zum Spielstart auf eine bestimmte Drehung gesetzt und bleibt dann so. Wenn es um Position oder Rotation geht, ist immer die Transform-Komponente wichtig. Sie ist immer ganz oben in der Komponentenliste und beim Verschieben oder Drehen eines Objekts geht es immer um ihre Felder. Sie hat außerdem die Besonderheit, dass jedes GameObject genau eine davon hat. Die Transform-Komponente kann man ansprechen, indem man einfach transform schreibt: void Start() { transform.Rotate(20, 20, 20); } Woah, jetzt aber mal langsam! Wir sehen hier wieder einen Methodenaufruf, zu erkennen an den Klammern nach einem Methodennamen (Rotate). Doch vor dem Methodennamen steht jetzt transform und dazwischen ein Punkt! Der Punkt ist extrem wichtig. Er erlaubt es, Methoden von anderen Objekten aufzurufen. Die Methode Rotate ist Teil der Klasse "Transform", also der Klasse, die als Bauplan für die Transform-Komponenten dient, die auf den GameObjects liegen. Um nun ein bestimmtes Objekt zu drehen, muss man angeben, welches Objekt das überhaupt ist. Beachte hierbei, dass ich nicht einmal von GameObjects rede, sondern von Objekten im programmiertechnischen Sinne. Die Transform-Komponente unseres GameObjects ist ein solches Objekt. Mit dem Punkt vereint man nun zwei Dinge: Zur linken steht das Objekt, von dem man etwas will, und rechts steht der Name der Methode, also das, was man vom Objekt will. In diesem Fall also: Ich will, dass sich unsere Transform-Komponente dreht. In den Klammern sind dieses Mal gleich drei Parameter. Diese entsprechen den drei Achsen, um die ein Objekt gedreht werden kann. Der Reihenfolge nach X, Y, und Z. Dieses Skript kannst du jetzt ausprobieren und nach Belieben die Zahlen ändern. Als nächstes wollen wir, dass sich das Objekt durchgehend immer weiter dreht, womit wir dem Ende dieses ersten Einstiegs nahe kommen. Wie in den Kommentaren im Code angedeutet, wird Update immer und immer wieder aufgerufen. Genauer: Es werden alle Update-Methoden von allen Komponenten auf allen GameObjects in der Szene aufgerufen, und danach wird das Bild neu gemalt. Der Ablauf ist eigentlich etwas komplexer, aber das ist das grundlegende Prinzip. Update findet auf jedem Objekt also genau so oft statt wie das Bild neu gezeichnet wird, also abhängig von den FPS des Spiels. Verschiebe nun einfach die Zeile mit transform.Rotate von Start() nach Update(), also in dessen Rumpf, speichere das Script und teste das Spiel. Dein Objekt dreht sich nun immer weiter, weil es in jedem Frame, also in jedem Update ein bisschen weiter gedreht wird. Aber warte mal... wenn das Spiel jetzt doppelt so viele FPS hast, dann wird Update doppelt so oft aufgerufen! Und wenn es sich doppelt so oft gleich weit dreht, dann dreht es sich doppelt so schnell! Hierfür gibt es Abhilfe: Time.deltaTime. Wie an den nicht vorhandenen Klammern zu erkennen, handelt es sich hier nicht um einen Methodenaufruf, sondern um eine so genannte Eigenschaft. Eine Eigenschaft stellt einen einzelnen Wert dar. Ein Beispiel dafür wäre wieder die Farbe einer Light-Komponente. Time.deltaTime allerdings gehört zu keinem Objekt - wie das kommt, ist allerdings etwas für ein anderes Kapitel. Time.deltaTime hat als Wert nicht etwa rot oder blau, sondern einen Zahlenwert; genauer: Die Zeit seit dem letzten Frame in Sekunden, inklusive Nachkommastellen. Diese Zahl ist also halb so groß, wenn wir doppelt so viele FPS haben, und umgekehrt. Wenn wir Time.deltaTime mit einer beliebigen Zahl multiplizieren, so bedeuetet das quasi "pro Sekunde". Wenn wir wegen hoher FPS doppelt so oft drehen, aber dafür jedes Mal nur halb so weit, dann haben wir eine konstante Rotation unabhängig von der Framerate. Multiplikation funktioniert, wie zu erwarten, mit dem *-Operator: void Update() { transform.Rotate(0, 20 * Time.deltaTime, 0); } Von hier aus gibt es noch jede Menge zu erzählen, bevor man so richtig loslegen kann. Ich hoffe allerdings, dass dieser Text hilft, zu verstehen, was man da genau schreibt, wenn man C# codet, und wie die Begriffe richtig heißen. Mal sehen, ob ich die Zeit finde, von hier aus kleinere Tutorials zu schreiben, die auf diesem aufbauen. Bis dahin kannst du hoffentlich andere Tutorials mit diesem hier kombinieren, um weiter zu kommen. Auf lange Sicht soll dieser Text und die darauf folgenden aber unsere JS-Tutorials ersetzen. Bis dahin!
  2. 5 likes
    Hier mal ein kliener Einblick in das Intro und das Menü meiner Pinball-Collection. Wenn ihr aufpasst, seht ihr die Themen der nächsten Flippertische.
  3. 3 likes
    Hey Leute, ich wollte euch schonmal einen kleinen Ausschnitt aus meinen neuen Game zeigen. Der Prototype steht schonmal soweit *Graphic's sind nur reine blocker-grahics. Wird natürlich noch hübscher später
  4. 3 likes
    Das ist zwar kein Bild sondern ein Video, aber man kann diesen Shader nur so gut zeigen ( 33 MB mp4). https://streamable.com/434jb Hintergrund: Ich arbeite seit dem Wochenende an der Portierung eines Bloodshader von NVidea und dies ist das bisherige Ergebnis. Leider ist die Portierung nicht zu 100% geglückt, aber ich habe zumindest große Teile davon in Unity umsetzen können. Der Shader simuliert den Fluss einer Flüssigkeit entlang einer Oberfläche unter Berücksichtigung einer Normalmap und der Gravitation. Leider konnte ich bisher die Richtung der Gravitation nicht dynamisch gestalten, da hier scheinbar eine Umrechnung innerhalb des Shader nicht funktioniert. Weitere Fortschritte: Der Gravitationsvektor wird nun über den Mesh bestimmt. https://streamable.com/u36u7
  5. 2 likes
    Ich werden diesen Thread hier als kleinen Info und Dev - Blog für mein Projekt nutzen. Ich stimme diesem Beitrag hier voll und ganz zu: Projektvorstellung Was ist Enum? Enum hat viele Namen. Es wurde noch nicht darüber entschieden welchen Namen es später tragen wird. Enum wird ein MMO dessen Terrain auf einer Voxel-Engine basieren wird. Dazu wird Voxelfarm verwendet. Voxelfarm wird in naher Zukunft noch eine große Rolle spielen. Es wird ständig weiter entwickelt und bietet dem Nutzer schon jetzt unglaubliche Möglichkeiten. Denn es kann weit mehr als nur Würfel darstellen: Voxelfarm Showcase So bietet Voxelfarm die Möglichkeit, ein der Realität entsprechendes farmen von Ressourcen und bauen von Gebäuden zu ermöglichen. Und das in einer sehr schönen und großen Welt. Koppelt man dies - mit unzähligen Spielmechaniken, welche eine demokratische Ökonomie(Grundstücksverwaltung, Stadtrat, Berufe, Versorgung...) ermöglichen. - mit einem noch nie dagewesenem Crafting-System unter Verwendung von Obi Fluids https://www.assetstore.unity3d.com/en/#!/content/63067 - Smartfoxserver als MMO Network-Engine. Zu 100% gegen Hacking geschützt. - Einem Ethereum Token als Währung. Der im Spiel erspielt werden kann und in Echtgeld umgewandelt und auch anders herum. Erhält man als Ergebnis ein Spiel das die Kombination vieler erfolgreicher Titel darstellt. Und das Ziel von Enum. Doch kommen wir zurück zu dieser Realität, wie sieht es aus mit Enum? Nunja, hinter Enum stehe momentan nur Ich. Alle gewünschten Features zu implementieren ist für mich als Einzelperson wohl in den nächsten 10 Jahren nicht möglich. Dennoch arbeite ich wenn immer ich Zeit finde an dem Projekt und mache stetig Fortschritte. Wenn Interesse besteht an Enum mit zu entwickeln schau doch mal hier rein: Klick. Aktuelle Probleme von Enum: - Das "Konzept" existiert zu großen Teilen (noch) nur in meinem Kopf, ist aber voll umsetzbar. - Das vollständige implementieren von Voxelfarm erfordert momentan noch einen Umfang dem ich nicht gerecht werden kann. (Voxelfarm Plugin umschreiben in C++ wozu vollständiges verstehen von Voxelfarm vorrausgesetzt ist, was aufgrund spärlicher Dokumentation schwer fällt) Ich warte auf Updates... - Der Netcode besteht momentan nur aus einer simplen statischen Interpolation. Aktueller Stand von Enum: - Smartfoxserver ist bereits implementiert. - Severbasierter Login inkl. Datenbank - Inventar, Character Stats usw. ebenfalls schon über Datenbank - Multyplayer mit bescheidenem Netcode aber voll MMO tauglich (AoI, TCP/UDP, Spielerposition, Itemposition, Statussynchronisierung, Chat usw.(100% Hack sicher, Spieler sendet nur Tasten an den Server) - Als Terrain ist noch Cubiquity implementiert. - Der Server läuft momentan schon auf einem Linux VPS. (Wegen Voxelfarm, wechsel zu Windows VPS) - Kleinigkeiten... Kleine Demo(Kein lokaler Server! Server steht bei Strato). Alle Assets inkl. das Voxel-Terrain sind Free-Assets. Das Schachbrett hat 4€ im Asset Store gekostet: Meine aktuelle Baustelle: - Das UI Alpha tauglich machen. Dazu gehören viele neben Baustellen wie das komplette Item-System(Inventory, Looten/Droppen, Kisten, Equipment uvm.), Chat, Character Stats usw. Ich mache alles selbst in C#. Keine UI Assets oder ähnliches. Im Anhang ein kleines Preview vom Inventar(Drag&Drop und Auto-Stack funktionieren schon, man sieht leider den Cursor nicht). Nächste Woche gibt es vielleicht schon ein Video. Ich rechne mit einer funktionsfähigen Voxelfarm Implementierung und Fertigstellung des UI in den kommenden 4 Monaten. MfG. Infinum PS: Es gibt noch viel zu editieren(in diesem Thread).
  6. 2 likes
    Eigentlich kann man das ja machen wie man will. Die meisten Games richten sich aber nach dem AD&D Regelwerk, wo die Stufenerhöhung ungefähr eine Verdoppelung der Punkte benötigt. Angefangen wird mit 2000 Punkten und jede weitere Stufe braucht man dann doppelt so viel wie zur momentanen Stufe. Ab dem Level 10 ist es dann aber gleichbleibend, also alle 250.000 Punkte bekommt man die nächste Stufe. Hier mal ein Link zur Regel: http://rollenspiel.doogle.de/cms/upload/mondseekampagne/AD_D_Tabellen.pdf Auf der Seite 10 der PDF sind die Werte dargestellt. Natürlich kann man das modifizieren und seinem Spiel anpassen. Wenn du z.B. nicht willst, dass man zu schnell aufsteigt, dann kann man die nötigen Punkte auch verdreifachen oder aber die Erfahrungspunkte, die man für etwas bekommt einfach reduzieren. Man kann auch sagen, dass es ein maximales Level gibt und danach nicht mehr aufsteigen kann. Da gibt es unheimlich viele Möglichkeiten. Ich würde mit der Verdoppelung der Punkte anfangen und dann einfach mal schauen, wie sich das Spiel weiter entwickelt und gegebenenfalls anpassen. Das in eine Formel zu bringen ist nicht so schwer. Du musst halt die erste Stufe ( also z.B. die 2000 Punkte) immer mit dem ist-Level multiplizieren und das Ergebnis zum NextLevel machen. Haste die Zahl erreicht oder überschritten, steigst du ein Level auf und somit ist dein ist-Level für die Berechnung auch um eins gestiegen. Wieveiel HP man je Level dazu bekommt kannst du auch im PDF nachlesen oder du machst dir selber Gedanken darüber. Das hängt ja alles davon ab, wieviel Schaden man nehmen kann und was der Basiswert deiner Figur ist.
  7. 2 likes
    Ein Update zu ein paar Neuerungen: Version: 0.183 Entwicklerforum: Canyonbreed Forum Schon öfters vorgeschlagen und endlich umgesetzt: Die Lootkiste Auch wenn sie schon rudimentär in der Demoversion enthalten ist (Müllcontainer, Medikits...), haben wir nun eine komplexere Lootkiste im Spiel. Die Features: Je nach Wertigkeit, mehrere unterschiedliche Items. Je nach Wertigkeit kann die Kiste auch verschlossen sein, die mit einem Tool/Schlüssel geöffnet werden kann. Schlüssel oder Keycards verbrauchen sich beim öffnen, haben aber eine 100%ige Chance, die Kiste zu öffnen. Wird die Kiste mit einem Alternativwerkzeug (Hacktool / Dietrich) bearbeitet, verbraucht sich das Werkzeug auch. Die Chance, die Kiste zu öffnen, ist hier aber deutlich niedriger. Schlüssel/Keycards sind entsprechend selten im Loot zu finden. Tools, um die Kisten zu knacken können, sind herstellbar, was das Ressourcensammeln und das Craften weiter aufwertet. Wenn ein Spieler eine geschlossene Kiste aufschliesst, können andere Spieler sie nicht einfach looten. Ich denke daß ist eine sinnvolle Mechanik um Stress zu vermeiden. Dennoch könnte ein anderer Spieler, der den passenden "Schlüssel" für die Kiste hat, sie ebenfalls für sich aufschliessen. Das Risiko einen Schlüssel zu verlieren, trägt dann der zweite Spieler, weil der erste Spieler ja bereits die Kiste lootet. Wie sich diese Mechanik im Spielbetrieb auswirkt, muss in weiteren Testläufen abgewogen werden. ---- Erweiterte Teleporterfunktionen Teleporter bzw. Fahrstühle, die technisch gesehen wie Teleporter funktionieren sind um ein paar Funktionen erweitert worden, die als Voraussetzungen deklariert werden können: Erforderliche Schlüsselkarte Erforderlicher Mindestlevel des Spielers Maximallevel des Spielers Erforderliche erledigte Quest Erforderliches Item (Einmalschlüsselkarte, Überbrückungskabel oder Tool) Erforderliche Credits --- Buff- und Debuff Flächen Es gibt nun Bereiche/Flächen, die sowohl positiven als auch negativen Einfluss auf den Spieler haben. Einfachstes Beispiel: Feuerfläche. Befindet man sich in so einem Bereich, erleidet der Spieler Schaden. Diese Flächen können mit unterschiedlichsten Attributen versehen werden: Featureliste: Einfluss auf Schutzschildregeneration (Lebenspunkte). Positiv sowie negativ. Einfluss auf Energieregeneration. Positiv sowie negativ. Blockieren der Schutzschild- und Energieregeneration. Einfluss auf Laufgeschwindigkeit. Positiv sowie negativ. Einfluss auf Attribute (Schutzschild- und Energiekapazität). Positiv sowie negativ. Optional kann ein entsprechend gelernter Skill den Spieler davor schützen. Optional kann ein entsprechendes Item den Spieler davor schützen. Beispiel: Ein sehr starkes elektromagnetisches Feld reduziert massiv die Energieregeneration und lässt die Kapazität der Energie sogar verbrauchen. Um dem entgegen zu wirken könnte der Spieler einen passiven Skill lernen, der diese Störung an seinem Cyborg absorbiert. Selbiges könnte auch mit einem entsprechendem Item funktionieren, daß man equippt haben muss.
  8. 2 likes
    Placr habe ich vorhin in ein paar Stunden zusammengebastelt. Dieses Video sagt vermutlich mehr als tausend Worte: Hier gibt's das Script: https://gist.github.com/FlaShG/00821764940d77361e0b4db2297efcf8 Einfach runterladen und in einen Editorordner schmeißen Das Häckchen in der Scene View setzen und ein Prefab oder 3D-Modell in den Assets auswählen Linksklick zum Platzieren Strg gedrückt halten zum Drehen Shift gedrückt halten um den vertikalen Offset zu verändern Rechtsklick zum Deselektieren (Gedrückt halten zum Rumfliegen geht aber, ohne dass deselektiert wird) Viel Spaß damit, Feedback wird gern gesehen.
  9. 2 likes
    Das hat anscheinend kurzfristig was genützt, allerdings scheint der Typ richtig besessen zu sein und hat gleich wieder so ein schwachsinniges Review geposted. Falls es noch jemand reporten möchte, wär ich sehr dankbar, ich hab Unity auch mal angeschrieben. Mal schauen. On-Topic: Ich möchte mit dem Style mal richtung SciFi gehen, so eine Forschungs-Expediton auf einen fremden Planeten schwebt mir da vor. Ich versorg euch mit Screenshots sobald sich wieder was tut Danke und LG holzi
  10. 2 likes
    Das eine Review da ist ja strunzfrech, hab's mal reported. Die Assets sind übrigens sehr schick - wenn ich nicht grundsätzlich keine Grafik kaufen würde, wäre das garantiert auf meiner Einkaufsliste.
  11. 2 likes
    Hey Leute! Es gibt jetzt ein günstiges Pack, welches alle Environments inkludiert! https://www.assetstore.unity3d.com/en/#!/content/91978 Hoffe es gefällt!
  12. 2 likes
    Ja schön. Aber du weißt jetzt immer noch nicht, was der Fehler war. Wenn du bei Problemen nicht die Porbleme löst, sondern einfach andere Wege gehst, wirst du nie begreifen wie die Dinge funktionieren. Ganz nach dem Motto: Ich bekomme die Pappe nicht in den Eimer rein, weil ich nicht weiß wie man die Pappe faltet. Also nehme ich jetzt einfach einen anderen Eimer. Du bist ja nun schon echt lange dabei, aber deine Lernkurve ist nicht besonders steil. Meinst du nicht, dass man das irgendwie verbessern könnte?
  13. 1 like
    Zurücksetzen müsste so gehen: private float resetTimeStamp = 0f; private void Reset() { resetTimeStamp = Time.time; } private void Update() { timer = Time.time - resetTimeStamp; int stunden = Mathf.FloorToInt(timer / 60f / 60f); int minuten = Mathf.FloorToInt(timer / 60f); int sekunden = Mathf.FloorToInt(timer - minuten * 60 - stunden * 60 * 60); Debug.Log(string.Format("{0:00}:{1:00}:{2:00}", stunden, minuten, sekunden)); }
  14. 1 like
    Ich denke da fehlt an einer bestimmten Stelle noch eine Klammersetzung, da er vermutlich das ToString() auf das GO "zahlAnzeige1" und nicht auf die Zahl selbst bezieht. Hier mal ein Versuch einer Klammersetzung: steuerung.zahlAnzeige1.GetComponentInChildren<Text>().text = (steuerung.zahlAnzeige1.GetComponent<Zahlenwert>()).zahlenwert.ToString(); Aber ist auch ziemlich unleserlicher Code und ich würde es lieber "entwirren", indem du noch einmal eine Hilfsvariable erzeugt, z.b. wie Malzbie es vorgeschlagen hat.
  15. 1 like
    Moin Moin! Geld ist Zeit also nur ein kleines Update: Das "Inventory UI" ist nahezu fertig. Vieles ist bereits auf etliche Konflikte getestet und bietet alle gewohnten Funktionen. Stacken, splitten, sortieren usw. Es gibt verschiedene Implementierungen für "Kisten". Da wären Slots und einfache Container(Grid View). Beide sind über zwei Enums (Type und subType) einschränkbar, für z.B. Equipment oder Useables. Alles wird zentral in einer Dictionary verwaltet. Ein paar Dinge sind mehrfach in unterschiedlicher Ausführung, wie z.B. das Hover-Menue und der Selektor. (Leider kein Bild) Spannender: Netcode. Ich habe begonnen eine erste Implementierung nach Link zu realisieren. Läuft ganz gut -> Client-Prediction fertig. Server-Reconciliation fertig. Entity-Interpolation fertig. Server-Prediction ist (right now) in arbeit. (Bild - oben rechts) Noch spannender: Die theoretischen Probleme der Voxelfarm-Implementierung konnte ich beseitigen. Die arbeiten am autoritativen "Climpmap View" laufen. Gerne würde ich mehr schreiben und auch eine spielbare Demo zeigen. Doch ich nutze momentan jede Sekunde möglichst effizient. Vielleicht in 1-2 Monaten. Mit freundlichen Grüßen (jegliches Design, ist, wenn überhaupt, durch Zufall entstanden. Alles Free-Assets. Ähnlichkeiten zu Minecraft sind nicht gewünscht und werden später wegfallen)
  16. 1 like
    Also, mal grundsätzlich: "Never trust the client!" - Der Client sollte keinen Hash generieren. Sondern den Hash generiert der Server und schickt ihn an den Client und der Client authorisiert sich damit am Server. - Den Hash würde ich auch rein zufällig generieren lassen und nicht aus Daten, die man theoretisch in Erfahrung bringen könnte (also Username, Passwort, etc). - Soweit ich das sehe, schickst du das Passwort im Klartext durchs Netz. Das sollte man, wenn möglich, schon gleich auf dem Client hashen. - Und das Passwort NIEMALS im Klartext in der DB speichern. (sieht so aus, als machst du das) - Warum du "WHERE username LIKE ?" machst, ist nicht nachzuvollziehen. Ich glaube, du solltest dich erst mal ein bisschen in Client/Server Kommunikation (mit Schwerpunkt PHP) aufschlauen, bevor du das "produktiv" einsetzt. Du kannst mich da gerne mal direkt anhauen. Das führt im Forum wahrscheinlich etwas zu weit und ist ja auch thematisch eher nicht so passend.
  17. 1 like
    Ich hatte soweit ich mich erinnern kann, mal das gleiche Phänomen und da lag es an einem "Fehler" der Unity-Anwendung. Es kann vorkommen, daß ein Plugin nicht entladen werden kann, oder eine Callback-Routine (typisches Beispiel "OnApplicationQuit()") beim Entladen von Unity nicht "ordnungsgemäß" beendet wird. Beides führt dazu, daß Unity im "Exit-State" hängen bleibt. Entweder man behebt diesen Fehler oder man beendet den Unity-Hauptprozeß über die Windows-API (wobei ich letzteres für keinen guten Weg finde, da hier Memoryleaks und ähnliches entstehen könnten). Ich würde einmal ein leeres Projekt builden und obigen Code damit testen, sollte der Exit bei einem leeren Projekt funktionieren , dann liegt die Ursache an den Assets (vor allem mit DLLs) oder an den Skripten des Unityprojektes.
  18. 1 like
    Hallo zusammen, ich wollte euch heute einmal ein System vorstellen, an dem ich zur Zeit arbeite. Ich suche schon seit langem nach einer Möglichkeit "Blut" in Unity realistisch darzustellen. Dafür gibt es aktuell mehrere Möglichkeiten wie beispielsweise Partikeleffekte und Decals. Was aber meiner Meinung noch fehlt, ist ein Bloodshader der Blut auf einer Oberfläche realistisch darstellt und den Blutfluss entsprechend den Gravitationsverhältnissen berechnet. Daher war mein erster Schritt einen solchen Shader zu entwickeln. Ich habe mir dabei ein Shader von NVidea als Vorbild genommen, der eine entsprechende Umsetzung gezeigt hat. Nach ersten Schritten dachte ich noch, keine Chance ich bekomme diesen Shader niemals nach Unity portiert, aber ich habe mich durchgebissen. Kurz zu der Technik des Shaders. Er erstellt für jedes Objekt (Mesh) anhand der Normalentextur und einer vorgegebenen Gravitation eine Gravitationsmap die jedes Frame neu berechnet wird. Anhand der Gravitationsmap wird letztendlich die Bluttextur berechnet und auf der Oberfläche dargestellt. Aktuell habe ich den Shadercode in den Unity-Standardshader übernommen, so daß das Blut nun als PBS-Blood-Shader dargestellt wird (quasi eine Mixtur des Bloodshaderscodes auf Grundlage des Unity-Standardshaders) mit einer berechneten Bumpmap, einem Regler für die Oberflächenbeschaffenheit und die Glanzfarbe. Die weiteren Schritte sind nun mein System weiter zu verfeinern. Da für die Darstellung des Blutes ja eine Gravitymap erstellt wird, muss jeder Mesh der das Blut darstellen soll zusätzlich gerendert werden. Hier habe ich eine Möglichkeit gefunden den Mesh ohne eine zusätzliche Kamera zu rendern, aber ich muss dieses System nun noch vereinfachen, so daß man quasi nur noch ein Skript an den betreffenden Mesh hängen muss. Das System muss zudem Skinnedmeshes und normale Meshes bei der Verarbeitung unterscheiden. Weitere zu programmierende Ergänzungen sind nun noch die Position der Textur über ein "Treffersystem" einzustellen. Der finale Schritt wäre dann einen Spieler mit mehreren Meshes darzustellen. Aktuell bin ich noch am Testen mit einzelnen Skinnedmeshes oder normalen Meshes. Hier mal ein Bild des aktuellen Shaders auf einem texturierten Frauenkörper (ist der Skinndedmesh unserer "Spielheldin" ohne ihre Ausrüstung): Und hier noch ein Video, wie der Shader auf einem Ausrüstungteil arbeitet (einfach anklicken ist ein Stream): https://streamable.com/w85ej
  19. 1 like
    UnityScript stirbt endlich: https://blogs.unity3d.com/2017/08/11/unityscripts-long-ride-off-into-the-sunset/
  20. 1 like
    Ich bin kein Netzwerkprofi, aber deine Theorie klingt für mich schlüssig. Ich kenne PUN nicht im Detail, aber deine beschriebenen Probleme kommen zum Teil daher, daß du quasi keinen authorativen Server hast, der den "Ownership" eines gespawnten Netzobjektes übernimmt und du damit immer einen Spieler als Owner bestimmen musst. Dies wird aber impliziert durch die verwendete Methodik von PUN, d.h. keinen authoritativen Server, der alle Zustände gespawnter Netzwerkobjekte definiert und vorgibt (wenn ich das richtig verstanden habe). sondern der PUN-Server stellt "nur" eine eindeutige Verbindung (PUN-Views) zwischen den Spielern (Clients) her und ordnet diese immer einer eindeutigen Identität zu (Lobby / Room / Groups / ViewID). Da dir also der Server fehlt, wird quasi immer ein Spieler zu "deinem Server" (Masterclient) und damit bestimmt auch immer ein Spieler den Zustand eines gespawnten Objektes. PS: Den (großen) Nachteil von PUN sehe ich allerdings nicht in der Methodik selbst, sondern eher in der Cheatanfälligkeit. Manipuliert ein Spieler seinen Client, kann er damit die Zustände den Spieles beeinflussen (und auch die anderen Mitspieler), was bei der Verwendung eines authorativen Server sehr erschwert wird, da hier der Server die Zustände der Clients noch einmal zusätzlich kontrollieren kann oder sogar sämtliche Zustände und "(Physik-)Simulationen" (bspw. Geschosse) selbst durchführt und damit nicht der Spieler entscheidet, ob beispielsweise ein anderer Spieler getroffen wurde. Die Clients dienen dabei mehr oder wenig nur noch als bessere "Eingabegeräte" und "Ausgabegeräte" und der Server simuliert sämtliche Zustände innerhalb des Spiels (es gibt aber denke ich auch "Teillösungen") Allerdings kostet diese Umsetzung wesentlich mehr Entwicklungsaufwand. Ich denke aber gelesen zu haben, daß auch mit Photon ein authorativer Server möglich ist: https://doc.photonengine.com/en-us/onpremise/current/reference/authoritative-server
  21. 1 like
    Ist ja alles gut und schön. Aber wenn er die Materialien oben wie unten gleich benutzt, dann liegt es nicht am Material an sich sondern an der Beleuchtung oder einem Posteffekt, der das Problem erst dann sichtbar macht. Ich sehe in den 2 Szenen ganz klar, dass der Himmel unterschiedlich ist und dass in Szene 1 mindestens ein Posteffekt aktiviert wurde. Wahrscheinlich PostProzessingBehaviour. Im oberen Bild meine ich außerdem zu erkennen, dass es kein Glanz sondern eine Spiegelung des Himmels ist, da der Himmel die gleiche Farbe hat, wie die hellen Bereiche auf dem Felsen. Somit würde ich darauf tippen, dass der Metallic Shader genutzt wurde. Metallic wäre gut, wenn etwas reflektieren soll, wie z.B. Fasser oder eben Metall. Bei einem Felsen würde ich zum Specular Shader über gehen, denn da soll maximal Glanz entstehen. Nutzt ihr eine Specular-Map, dann lässt sich die Specular-Farbe nicht mehr einstellen, denn Unity geht jetzt davon aus, dass alles über die Map kommt. Jetzt kann man eh nur noch die Smoothness einstellen. Also ob es ein breiter und diffuser oder ein enger und knackiger Glanzpunkt werden soll. ( Nutzt ihr die Map beim Metallic Shader, dann steuert man nur noch, ob die Reflektion matt mit breiten Highlights oder klar mit engen und starken Highlights ist) Welche Bereiche aber wie stark spiegeln bzw. glänzen, wird dann allein über die Textur gelöst. Evtl. müsst ihr mal mit eurer Textur rum spielen und die Bereiche einfach etwas abdunkeln. Am Besten ihr vergleicht mal die Shader der beiden Szenen, die Beleuchtung und die SkyBox und zusätzlich ob die Kamera PostProzessing macht. Und wenn ja, welche Werte und Kanäle da drin eingeschaltet sind.
  22. 1 like
    Das Glänzen kann vom Metallic-Anteil (Standard bzw. Metallic Setup) oder von der Glanzfarbe kommen (Specular-Setup). Zusätzlich hängt beides von der Oberflächenbeschaffenheit (Oberflächenglätte) ab, die jeweils im Alphachannel beschrieben wird oder über den Smoothnessregel eingestellt wird. Um das Glänzen zu verringern den Metallic-Anteil (Textur) senken oder die Oberflächenglätte senken (Regler oder Alphatextur), wobei letzteres eben nur die Spiegeleffekte verringert. Das Bild sieht mir aber eher nach eine falschen Glanzfarbe aus (oder siehe unten), in dem Fall zu viel Hellblau. Daher im Metallic-Setup den metallischen Anteil senken oder im Specular-Setup die Glanzfarbe auf "braun" umstellen. Wenn ihr allerdings den Specular-Setup verwendet, dann würde ich für Felsformationen besser den Standardshader im Metallic-Setup verwenden, da Felsen keine Glanzfarbe haben sollten. Wenn das Hellblau allerdings von der Skybox kommt (Lighting -> Scene -> Reflection Source - hier mal die Skybox rausnehmen und schauen ob das Hellblau verschwindet), dann sind wir wieder bei der Oberflächenglätte.
  23. 1 like
    Was Kerugal beschrieben hat, ist quasi die "Profilösung" aber auch dementsprechend komplex. Für eine einfachere Variante würde ich das Bild in eine 2D-Textur einlesen und diese Textur an vordefinierten Stellen mit einem Muster vergleichen. Ein Muster ist dabei nichts anderes es ein 2 dimensionales Array bzw. eine kleinere Textur. Dieses Muster legst du nun über einen vorbestimmen Abschnitt (an eine Position-XY des Bildes) und machst eine logische Verknüpfung jedes Pixels zwischen beiden Texturen. Man kann bei der logischen Verküpfung nun jeweils einen Schwellwert definieren, ab wann 2 Pixel als gleich angesehen werden. Beispielsweise könnte man hier einen Pixel mit dem Farbwert (240, 240, 240) des Originalbildes mit dem Pixel aus dem Muster (238,339, 237) als "gleich" ansehen. Bestimmt man nun für jeden Pixel des Musters diese "Gleichheit" bekommt man eine "Gesamtaussage" wie viele Pixel des Musters an der Position XY des Gesamtbildes vorhanden sind. Hat man hier eine sagen wir 95% Gleichheit kann man das Muster als "erkannt" bewerten. Zusätzlich zu dem Schwellwert der Pixel kann man ebenfalls eine gewisse "Streuung" der Pixel des Muster innerhalb des Originalbildes mit einbeziehen. Beispielsweise könnte ein Pixel des Musters ebenfalls als "gleich" gelten, wenn der Pixel im Umfeld des Pixels (die 8 Pixel um den eigentlichen Pixel herum oder einen größeren Bereich) des Originalbildes gefunden wird. Man erzeugt damit quasi eine gewisse Unschärfe bei der Mustererkennung, die aber notwendig ist, da ein Muster im Originalbild oft nur leicht verfälscht vorhanden ist.
  24. 1 like
    Es gab einen Unity Hype, der jetzt abflacht? Ist mir Beides nicht aufgefallen. Ich pausiere selber auch gerade schon seit einer Weile. Aber bei mir ist Unity auch nur eins meiner viel zu vielen Interessen. Da muss immer etwas zurück stecken... Irgendwann mach ich aber wieder weiter. Macht schon Spaß, damit zu klöppeln.
  25. 1 like
    Ich bin natürlich am schaffen. Und ich denke, die Anderen sind es auch. Aber es ist nun auch Sommer und Urlaubszeit, und da werden viele Leute lieber draußen oder verreist sein, als am Computer zu hängen. Der Roman ist Inhaber des Forums und administriert/moderiert eigentlich nicht. Aber natürlich hat er die Adminrechte, als Chef!
  26. 1 like
    Gib dem Wasser einen Tag und frage ab und frage ihn ab. z.B.: OnTriggerEnter( Collider other){ if(!other.CompareTag("Wasser")){ // ich bin nicht im Wasser und kann hüpfen } }
  27. 1 like
    Da ich momentan viel Texturen male, hab ich mal was feines zu zeigen! Ist ja schließlich ScreenshotSaturday!
  28. 1 like
    Hi, na das sieht ja jetzt richtig cool aus. Gute Arbeit!
  29. 1 like
    Ja, wäre auch der sauberste Weg (dann die Kamera aber wieder aktivieren) und die Textur sollte sogar bereits vorhanden sein bevor das 1. Mal OnGUI aufgerufen wird (siehe "Execution Order of Event Functions") Ich denke "Render()" zu verwenden macht Sinn, wenn man die Rendertexture nicht in jedem Frame rendert, sondern beispielsweise nur dann wenn der Anwender einen Button drückt oder ähnliches.
  30. 1 like
    Die Frage ist ja, ob man Render überhaupt braucht. Prinzipiell rendern wir ja sowieso im Renderzyklus, warum also nicht alles so lassen wie es ist? In dem Fall braucht man ja nur noch die RenderTexture zu setzen und diese anzuzeigen.
  31. 1 like
    Jetzt im Play-Store kostenlos Erhältlich! Google Play Nun kann man auch Tap Reminder im Play Store bekommen Könnte es gerne ausprobieren und mir feedback geben wen ihr möchtet Mfg. -John
  32. 1 like
    Sollte passen, allerdings hatte ich mir noch überlegt, daß die Kamera die Szene vermutlich immer noch 2x rendert und in der Doku nachgeschaut und siehe da dort steht, man sollte die Renderkamera deaktivieren (disable), wenn man Render() verwendet. Ansonsten rendert sie die Rendertexture auch in ihrem "normalen Renderzyklus".
  33. 1 like
    Hallo Leute, ich bin grade dabei die ganze Graphic vom Game zu überarbeiten. Hier ist schonmal ein kleiner Ausschnitt, würde mich sehr über feedback freuen Bildschirmaufnahme 2017-07-27 um 18.13.13.mov Mfg. -John
  34. 1 like
    Ja das stimmt Sascha, OnGUI wird ja mehrfach aufgerufen, ich hab mein Skript auch mal dementsprechend angepasst. Bei dem Skript von mir muss die Renderkamera über das Skript übergeben werden, sonst gibt es ein NPE. Ansonsten macht es nun am meisten Sinn dieses Skript an die Renderkamera zu hängen (dann könnte man sich die Renderkamera auch vom GO selbst holen): using UnityEngine; using System.Collections; [RequireComponent(typeof(Camera))] /// <summary> /// Skript für eine 2. Kamera, um einen Auschnitt der aktuellen Szene in einer GUI-Textur abzubilden. /// </summary> public class RenderTextureTest : MonoBehaviour { private Camera renderCam; private RenderTexture mainPreview; void Awake() { renderCam = GetComponent<Camera>(); this.mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32); renderCam.CopyFrom(Camera.main); renderCam.targetTexture = this.mainPreview; } void OnPreRender() { renderCam.Render(); } void OnGUI() { GUI.DrawTexture(new Rect(0, 100, 400, 400), renderCam.targetTexture); } }
  35. 1 like
    Mir fällt gerade auf, dass man das vielleicht echt nicht in OnGUI machen sollte. Schließlich sollte sich sowieso nichts geändert haben zwischen zwei Updates, also warum Render() in einem anderen Zyklus als Update ausführen? Außerdem muss die targetTexture nicht ständig neu zugewiesen werden. Also wieder abgeändert: using UnityEngine; [RequireComponent(typeof(Camera))] public class RenderTextureTest : MonoBehaviour { private Camera renderCam; private RenderTexture mainPreview; void Awake() { mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32); renderCam.CopyFrom(Camera.main); renderCam.targetTexture = this.mainPreview; } void OnPreRender() { this.renderCam.Render(); } void OnGUI() { GUI.DrawTexture(new Rect(0, 100, 400, 400), this.renderCam.targetTexture); } } Hab mal OnPreRender genommen, weiß nicht ob das optimal ist. Dazu muss das Skript jedenfalls direkt auf der Kamera liegen, darum RequireComponent.
  36. 1 like
    In der Zeile 167 ist das Gewünschte. fov = Mathf.Clamp(fov, 20.0f, 60.0f); 20 ist der minimale Winkel und 60 der maximale Winkel.
  37. 1 like
    Das sollte eigentlich mit dem Canvas Scaler "steuerbar" sein ("UI Scale Mode" = "Scale With Screen Size" / "Match" = 0.5). Richtig eingestellt, passt sich der Canvas und die Canvaselemente an die Größe des jeweiligen Displays an und damit bleibt die GUI (d.h. auch der Snakeknopf) in Relation gleich groß. https://docs.unity3d.com/Manual/script-CanvasScaler.html Für das Image solltest du ggf. noch "Preserve Aspect" aktivieren. Nähere Infos: https://docs.unity3d.com/Manual/HOWTO-UIMultiResolution.html
  38. 1 like
    Wenn ein Prozeß eine Datei öffnet, dann erlangt er ein "Handle" auf diese Datei. Dieses Handle ist zumeist "exklusiv" und damit kann kein anderer Prozeß mehr in diese Datei schreiben. Wenn du mit "File.Create" arbeitest, bekommst du über diese Methode bereits ein FileStream zurück. Dieses FileStream besitzt dann dieses Handle. Wenn du AppendText aufrufst, dann versucht das System sich ein weiteres Handle zu holen und dann kommt es zu diesem Konflikt. Also über File.Create sich den FileStream geben lassen und dann damit den Text schreiben, oder nach Create den Stream wieder schließen und dir mit AppendText einen neuen Stream holen.
  39. 1 like
    Kann gut am Schwerpunkt liegen, bei Fahrzeugen war es jedenfalls so. So kannst du ihn setzen, am besten am RB des Hauptbodys des Tieres (also nicht die Beine). Den Schwerpunkt am besten auf den Boden ziehen, d.h. zentriert unter dem Body des Tieres: https://docs.unity3d.com/ScriptReference/Rigidbody-centerOfMass.html Ich hab auch gelesen, man kann zusätzlich noch eine Kraft wirken lassen, die den Körper von oben Richtung Boden presst, habe ich aber noch nie gebraucht.
  40. 1 like
    Ich denke dieses Asset sollte den Job auch tun, aber ich kenne es nicht. Zumindest behauptet es eine "loopable world" erstellen zu können: https://www.assetstore.unity3d.com/en/#!/content/36486 Hier ist noch eine Methode mit 9 (seamless tiling) Quadranten beschrieben (ich denke diese Methode ist einfacher als die Methode mit dem Cube die ich oben beschrieben habe): http://answers.unity3d.com/questions/626777/endless-terrain-loop.html
  41. 1 like
    Du kannst dir die Methode auch so vorstellen: 1) Man nimmt eine Kugel und legt dafür eine bestimmte Größe fest (in Relation zu der Quadrantengröße) 2) Du legst eine bestimmte Größe für deine Quadranten fest 3) Du legst die Quadranten auf die Kugeloberfläche (Projektion) Anhand der Position des Spielers (auf dem Client) wird nun die individuelle Sicht des Spielers auf der Kugel berechnet und die passenden Quadranten um den Spieler herum positioniert.. (ich habe leider keinen Quellcode dafür, aber es ist mathematisch lösbar) https://de.wikipedia.org/wiki/UV-Koordinaten#/media/File:UVMapping.png Aber ich vermute einmal, die Welt muss nicht eine perfekte Kugel sein, es sollte auch ein Würfel reichen und damit wird das ganze wieder viel einfacher ... https://de.wikipedia.org/wiki/UV-Koordinaten#/media/File:Cube_Representative_UV_Unwrapping.png Auch wenn du einen Würfel umrundest kommst du wieder bei deiner Ausgangsposition an und der Spieler merkt nicht wirklich ob seine Welt eine Sphere oder ein Würfel ist .
  42. 1 like
    Wie bereits erwähnt, du solltest die Tier Settings prüfen und die Quality Settings. Die Tiersettings bestimmen beispielsweise ob "Forward Rendering" oder "Deferred Rendering" verwendet wird. Sollte es auf "Forward Rendering" eingestellt sein, dann werden ggf. einige Lichtquellen nur als Annäherung berechnet (kann sich auf Schatten auswirken). Zudem solltest du bei deinen Lichtquellen prüfen, ob diese auf Rendermode "Important" stehen. Auch dies kann vor allem wieder beim "Deferred Rendering" Auswirkungen auf die "Ausleuchtung" dieser Lichtquelle haben und sich damit auf den Schattenwurf auswirken. http://answers.unity3d.com/questions/1300245/unity-55-global-render-path-setting.html Zudem solltest du prüfen, ob beim Mesh der Säulen "Cast Shadows" auf "on" steht. Was man auch nie ausschließen kann, daß es ein generelles Problem mit deinen Säulen gibt, tausch diese einfach mal gegen einen Unity-Cylinder aus und schau ob diese einen Schattenwurf erzeugen ...
  43. 1 like
    Nein, du kannst Childs zu jeder Zeit erzeugen und sobald sie dem Parent untergeordnet werden, wird die relative Position des Childs quasi eingefroren. Bewegst du nun den Parent, dann bewegt sich das Child auf seiner (eingefrorenen) relativen Position mit. Das Einzige was mir noch einfällt wäre, ob evtl. ein RB an den Raketen hängt und der RB die Raketen aus seiner Position zieht... Ist dem so, dann könntest du noch bei dem RB unter Constraints die Position und Rotation fixieren.
  44. 1 like
    Hi. Ich weiß nicht ob meine Augen vielleicht etwas anfällig sind, aber bei mir entsteht die Optische Täuschung die bei einem Hermann Gitter entsteht. MfG Felix
  45. 1 like
    Schwer zu sagen, wo hier genau das Problem liegt, ich würde mal im Inspektor schauen, ob die Raketen sich dann auch tatsächlich unter dem Spielertransform befinden. Für die bessere Lesbarkeit des Codes würde ich es erst einmal so machen: GameObject newRocketL = Instantiate(_RObj, _RSpawnL.position, Quaternion.identity) as GameObject; newRocketL.transform.parent = _RSpawnL; // Ist hier RSpawnL als Position richtig (oder _RSpawnR) ? GameObject newRocketR = Instantiate(_RObj, _RSpawnL.position, Quaternion.identity) as GameObject; newRocketR.transform.parent = _RSpawnR; // Unterbrechen und schauen wo sich die Childs befinden Debug.Break(); Zudem würde ich zusätzlich schauen, ob sich die Positionen der beiden Child's während des Gameplays verändern, daß sollten sie nämlich nicht.
  46. 1 like
    Hab noch mal eine ganze Weile gegoogelt und werde es über den Editor versuchen. So kann ich vielleicht auch gleich eine Sprite-Map aus mehreren Sprites generieren um zusätzlich Ressourcen zu sparen. Zudem könnte ich den Editor auch so erweitern, das ich gleich die Daten für die einzelnen Objekte setzen kann, z.B. als ScriptableObjekt. Danke für Eure Tipps.
  47. 1 like
    Hab es nicht ausprobiert aber sieht ja ganz solide aus. vielleicht ein bischen Farblos, ich würde geometrische Formen mit verschiedenen Farben nehmen
  48. 1 like
    Auf was für einem Boden "steht" denn dein Spieler? Sollte es ein Terrain sein, einmal den Parameter "Thickness" kontrollieren, der sollte auf "1" stehen (wir hatten schon einmal einen Fall, wo dieser Wert "verstellt" war). Solltest du kein Terrain verwenden, könnte es trotzdem auch ein Problem mit deinem Bodencollider geben. Zudem ist dein Gravitywert sehr hoch, "9.8" sollte hier genügen (ich bin mir nicht sicher, ob irgendwann ein zu hoher Wert den Boden innerhalb eines Frames "durchschlägt"). Zu guter Letzt würde ich aus der "Update"-Methode eine "FixedUpdate"-Methode machen, da der CC sich bei deinem Problem gegen einen Collider bewegt und die "Update"-Methode hier Probleme machen könnte, da sie "unter dem Radar" der Physikengine agiert (d.h. du schiebst damit den CC ohne das es die Physikengine mitbekommt durch den Boden hindurch). Und ich sehe gerade: transform.Translate(MoveVector * Time.deltaTime * Speed); Hier bewegst du den CC über "Translate" innerhalb der Updatemethode und daß sollte man keinesfalls nicht tun. Hier mal einige allgemeingültige Regeln bei der Verwendung eines CCs: 1) Spielerinput in der Updatemethode erfassen 2) Rotationen über transform innerhalb der Fixedupdate-Methode. 3) Move Aufrufe innerhalb der Fixedupdate-Methode. 4) Keine Verwendung von transform.Translate oder transform.position (bei der Fortbewegung) Abschließend, noch eine wichtige Änderung des Quellcodes (siehe MoveVector.y): if (Player.isGrounded) { MoveVector.y = 0; // wenn am Boden keine Bewegung in Richtung Boden MoveVector.x = Input.GetAxis("Horizontal"); MoveVector.z = Input.GetAxis("Vertical"); TurnVector.y = Input.GetAxis("Mouse X"); transform.Translate(MoveVector * Time.deltaTime * Speed); transform.Rotate(TurnVector * Time.deltaTime * Turn); if (Input.GetButton("Jump")) MoveVector.y = Jump; } Zudem bin ich mir nicht sicher, ob der Rest deines Quellcodes korrekt ist. Wenn dein Spieler in der Luft ist auf den MoveVector jedesmal erneut ein TransformDirection anzuwenden erscheint mir falsch... Hier ein zumindest halbwegs korrektes Beispiel (Fixedupdate wurde nicht beachtet) aus der Unitydoku: https://docs.unity3d.com/ScriptReference/CharacterController.Move.html
  49. 1 like
    ja sehr geil .. gut gelungene Animationen und Charactere ...evtl. würde ich das Shading der Chars noch etwas anpassen ..damit diese nicht so "dreckig/dunkel" wirken. was man auch noch machen kann sind die chars auch noch als normal rausrendern .. dann könntest du dynamische beleuchtung machen ?! müsste man mal testen.
  50. 1 like
    Ich würde mir an deiner Stelle in gutes (Video)Tutorial suchen (z.b. RPG Tutorial) und dieses durchgehen und versuchen zu darüber lernen, wenn du diese Prinzipien verstanden hast, dann kommst du auch mit dem Spieltyp oben weiter. Ich glaube ein Mentor zu finden wird schwierig, viele Leute haben eigene Projekte und entsprechend wenig Zeit.