Entwickle eine bewegende Welt

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

Die Schaffung von Bewegung in jeder Umgebung innerhalb eines Erlebnisses hilft, es sofort realistischer und immersiver in unsere Welt zu fühlen, sei es durch die Bewegung von Umgebungsbäumen, reaktive Türen aus der Interaktion mit dem Spieler oder sogar Kisten, die sich bewegen, wenn sie darauf stoßen.Studio hat viele einzigartige Methoden, um Bewegung zu erzeugen, um die Welten lebendiger zu fühlen, einschließlich eines Physiksystems, TweenService , und Animationen, und die Analyse der spezifischen Bedürfnisse deiner Erfahrung kann dir helfen, zu bestimmen, welche zu verwenden ist.In diesem Abschnitt zeigen wir, wie wir festgestellt haben, welche Art von Bewegung wir in Studio erstellen wollten, und welche Werkzeuge wir verwendet haben, um diese unterschiedlichen Ziele zu erreichen.

Erstelle den Sturm

Der Sturm durchlief viele Iterationen, bevor wir uns auf das einigten, was live in The Mystery of Duvall Drive ist.Früh dachten wir an den Sturm als einen riesigen Obsidianpfeiler, und in späteren Iterationen hielten wir ihn für ein riesiges Portal in den korrupten Platz.Nachdem wir mit vielen verschiedenen Stürmen mit einzigartigem Look und Gefühl experimentiert hatten, landeten wir bei einem Sturm mit einem kleineren zentralen "Auge", weil:

  • Der Sturm sollte den Spielern ein Gefühl für die Auswirkungen dieses Ereignisses auf die Welt geben, einschließlich von Bäumen, die wehen und Trümmer fliegen.
  • Der sich drehende Wirbel der Wolke selbst sollte den Spielern einen Blick in das zentrale Portal werfen, ohne alles zu offenbaren .Dies würde Spieler ermutigen, näher zu untersuchen, um zu sehen, was passiert.
  • Der engeren Punkt des Lichts würde es uns ermöglichen, uns auf die Zusammensetzung des Hauses zu konzentrieren, was sowohl der Hauptcharakter als auch der Ort ist, an dem sich das meiste Spiel geschieht.

Um den Sturm dynamisch, aggressiv und sich ständig in seiner Umgebung fühlen zu lassen, verwendeten wir die folgenden Systeme und Funktionen:

  1. TweenService - Für die Bewegung in der Cloud.
  2. Beleuchtungsänderungen - Für die Erstellung der Wolke zum Wolkenblitz.
  3. Strahlen - Für die "volumetrische Beleuchtung" und die Blitze.
  4. Partikel-Emitter > - Für Trümmer, die bis zum Portal fliegen und aufgrund des Windes herumfliegen.
  5. Animationen - Für die Bäume, die im Wind wehten.

Füge Wolken mit Texturen hinzu

Während dynamische Wolken großartig für normale, hochrealistische Wolken mit hoher Höhe sind, brauchten wir etwas, das dramatisch war und das wir stärker lenken und gestalten/anpassenkonnten.Um dies zu tun, haben wir Oberflächenaussehen-Objekte mit halber Transparenz auf eine Reihe schwer gestapelter und übereinanderliegender Wolkenmeshes angewendet, um eine Cloudabdeckung zu simulieren.Warum haben wir sie gestapelt und so schwer übereinander gelegt? Weil wenn sich jedes Wolkennetz mit unterschiedlichen Geschwindigkeiten bewegt, sich darin kreuzen und Wolkenformen erzeugen, die hinein und heraus gehen.Dieser Prozess ließ die Wolken ein bisschen dynamischer und natürlicher wirken, obwohl sie nur drehende Scheiben sind.Es war auch wichtig, dass die Wolken halbtransparent waren, weil wir wollten, dass Spieler durch sie sehen können, etwas Helliges in der Mitte zu sehen, bevor sie das Haus erreichten!

Ein einzelnes Cloud-Mesh.
>

Mehrschichtige Wolkennetze ohne ihre Texturen!
>

Da jedes Wolkennetz massiv sein musste, um das Haus vollständig zu umgeben und zu vermitteln, wie gewaltig der Sturm war, wussten wir, dass wir die Textur, die wir auf den einzelnen Wolkennetzen verwenden wollten, verfliesen mussten, damit sie sich auf der gesamten Oberfläche des Meshstark wiederholte.Wir haben die Materialien, die wir für die Cloud hergestellt haben, auf diesen einfachen Teilen getestet und dann auf den Vortex angewendet!

Im Gegensatz zu PartikelEmittern oder Strahlen ermöglichten uns Meshes, Licht von jedem Netz abprallen zu lassen, was wichtig war, als wir Cloud-zu-Cloud-Blitze implementieren wollten.Wir haben auch im Drehen modelliert, damit das Licht, das von ihm abprallt, so aussehen würde, als hätte es Tiefe! Dies war besonders wichtig in Situationen, in denen die Leistungsanforderungen des Erlebnisses die Qualitätslevel unserer Oberflächenaussehensobjekte senkten.

Sobald wir mit dem Hinzufügen von Beleuchtung begonnen hatten, mussten wir Details zu den Meshes hinzufügen, um sie besser auf Beleuchtung zu reagieren zu lassen!

Wolkennetze drehen

Nachdem wir mit dem allgemeinen visuellen Erscheinungsbild der Wolken zufrieden waren, mussten wir sie in Bewegung bringen! Wir hatten die allgemeinen Formen jedes Wolkenlagers vor Ort, aber es dauerte einige Versuche und Fehler, um sicherzustellen, dass der drehende Effekt in der Praxis gut aussieht.Wir haben zunächst versucht, Einschränkungen zu verwenden, um Geschwindigkeit einzuführen, die die Wolken physisch Verschiebungswerkzeugwürde.Dies war schwieriger als wir es später wiederholen wollten, und der Spieler würde nie damit interagieren, also brauchten wir es nicht so genau in seiner Bewegung zu sein.

Wir wollten eine einfach zu verwendende Methode, um Instanzen zu drehen, die entweder zu weit weg waren, um interagierbar zu sein, wie Wolken, oder zu klein oder dekorativ, um für Spielen/Physik wichtig zu sein, wie kleine Lampen im Innenraum.Wir entschieden uns für die Verwendung eines LocalScript, um die Client-Server-Bandbreite zu reduzieren, eine glattere Bewegung zu ermöglichen und jedem Cloud-Mesh die Möglichkeit zu geben, eine unterschiedliche Rotationsrate und Verzögerung zu haben.Um es allgemeiner zu machen, haben wir auch möglich gemacht, die Achse der Rotation anzugeben.Es ist möglich, 3 Attribute zu verwenden, aber für unseren Fall verwendeten wir 3 Werte: Axis , Delay und Speed .

Wie in vielen Fällen in der Demo verwendeten wir ein LocalSpaceRotation-Tag, um betroffene Instanzen in Studio mit einem Plug-inverwalten zu können.Wir verwendeten nur eine einzige LocalScript, die alle mit Tags versehenen Instanzen verwaltete, indem sie die CollectionService verwendete, so dass wir keine Menge an Skripten hatten, die während des Entwicklungsprozesses aufrechterhalten mussten.

In unserer Demo werden Teile der Welt aus der ServerStorage in den Arbeitsbereich kopiert, wie es nötig ist, also mussten wir Fälle handhaben, in denen gekennzeichnete Objekte erstellt und zerstört wurden.Mit LocalScripts müssen wir uns auch der Streaming bewusst sein, wo Meshes und ihre Kindervale möglicherweise hinein und heraus gestreamt werden.Wir haben zuerst platzierte Objekte in der Init()-Funktion verarbeitet und sie mit CollectionService.GetInstanceAddedSignal und CollectionService.GetInstanceRemovedSignal verbunden, um für markierte Objekte neu erstellte/zerstörte Objekte zu verarbeiten.Die gleiche SetupObj -Funktion wurde verwendet, um neue Objekte in Init() und in CollectionService.GetInstanceAddedSignal zu initialisieren.


local function Init()
for _, obj in CollectionService:GetTagged("LocalSpaceRotation") do
if obj:IsDescendantOf(workspace) then
SetupObj(obj)
end
end
end
CollectionService:GetInstanceAddedSignal("LocalSpaceRotation"):Connect(function(obj)
objInfoQueue[obj] = true
end)
CollectionService:GetInstanceRemovedSignal("LocalSpaceRotation"):Connect(function(obj)
if objInfo[obj] then
objInfo[obj] = nil
if objInfoQueue[obj] then
objInfoQueue[obj] = nil
end
end
end)
Init()

objInfo ist eine Karte, die Informationen für alle relevanten Objekte enthält, wie ihre Rotationsgeschwindigkeit und ihre Achse.Beachten Sie, dass wir nicht sofort SetupObj von CollectionService.GetInstanceAddedSignal anrufen, aber wir haben ein Objekt in objInfoQueue hinzugefügt.Mit Streaming- und Klonobjekten auf dem Server, wenn CollectionService.GetInstanceAddedSignal aufgerufen wird, haben wir möglicherweise noch nicht unsere Axis , Delay und Speed Werte, also fügen wir das Objekt in eine Warteschlange ein und rufen die Funktion SetupObj auf nachfolgenden Frames von der Update -Funktion, bis die Werte da sind und wir sie in pro Objekt "Info"-Struktur lesen können.

Wir drehten die Instanzen in der Update Funktion, die mit dem Herzschlag verbunden ist.Wir haben die Eltern-Transform (parentTransform) erhalten, eine neue Rotationswinkel ( curObjInfo.curAngle ) basierend auf der Rotationsgeschwindigkeit dieses Objekts gesammelt, die lokale Transformation ( rotatedLocalCFrame) ) berechnet und sie schließlich auf die CFrame festgelegt.Beachten Sie, dass sowohl der Eltern als auch das Objekt ein Model oder MeshPart sein kann, also mussten wir IsA("Modell") überprüfen und entweder ein PrimaryPart.CFrame oder CFrame verwenden.


local parentTransform
if parentObj:IsA("Model") then
if not parentObj.PrimaryPart then
-- die primäre teile könnten noch nicht gestreamt werden
continue -- warte, bis der primäre teil repliziert wird
end
parentTransform = parentObj.PrimaryPart.CFrame
else
parentTransform = parentObj.CFrame
end
curObjInfo.curAngle += dT * curObjInfo.timeToAngle
local rotatedLocalCFrame = curObjInfo.origLocalCFrame * CFrame.Angles( curObjInfo.axisMask.X * curObjInfo.curAngle, curObjInfo.axisMask.Y * curObjInfo.curAngle, curObjInfo.axisMask.Z * curObjInfo.curAngle )
if obj:IsA("Model") then
obj.PrimaryPart.CFrame = parentTransform * rotatedLocalCFrame
else
obj.CFrame = parentTransform * rotatedLocalCFrame
end

Wir haben nach einem gültigen Model.PrimaryPart gesucht, um zum Streaming verwendet zu werden.Wenn ein Update auf unserem Objekt aufgerufen wurde, während ein Model.PrimaryPart (das auf ein Meshzeigen kann) noch nicht gestreamt wurde, würden wir einfach das Update überspringen.Das aktuelle System ist eine zweite Iteration der Objektrotierung, und das vorherige System funktionierte anders: Die Werte waren 12-mal unterschiedlich! Um die gleichen Daten beizubehalten, konvertierten wir sie in unserem Skript, das. PL: die Skripts, wie "12 * obj.Speed.Value".

Entwerfen von Blitzschlägen

Da Studio keinen Lightning-Generator aus der Schachtel anbietet und das Partikel-System einige Einschränkungen hatte, die für die Helden-Blitzschläge nicht funktionieren würden, mussten wir kreativ werden mit einer Lösung für die Helden-Blitzschläge.Wir haben uns für zwei Hauptsysteme entschieden, um den Blitz zu bilden: strukturierte Strahlen für die Heldenblitzschläge, die vom Auge des Sturms kommen, sind strukturierte Strahlen, die sich mit Audio- und Postprozess-Effekten offenbaren und synchronisieren, und ein einfacher Partikeleffekt für den entfernten Wolken-zu-Wolken-Blitz.

Texturstrahlen

Wir würden normalerweise entweder einen Sequenzer oder ein Zeitplanwerkzeug verwenden, um die Timing eines Blitzschlageffekts wie diesen zu steuern, aber da Studio diese Funktionalität noch nicht anbietet, beschlossen wir, Skripte zu schreiben, die die Timing des Blitzschlageffekts steuern würden.Die Skriptierung dieses Effekts ist ziemlich einfach, aber sie erreicht die folgenden wichtigen Ziele:

  1. Elemente des Blitzschlags, wie ihre Texturen, Helligkeit und Verzögerungen, werden mit jedem Schlag zufällig verändert.
  2. Änderungen an Audio und Post-FX sind im Einklang mit Strike-FX.
  3. Spieler, die entweder drinnen sind oder sich im korrupten Bereich befinden, wären nicht in der Lage, sie zu sehen oder zu hören.

Wir haben eine serverseitige Script, die verschiedene Parameter und Zeiten berechnet, sendet sie an alle Clients und wartet auf eine zufällige Menge an Zeit:


local function LightningUpdate()
while true do
task.wait(rand:NextNumber(3.0, 10.0))
local info = CreateFXData()
lightningEvent:FireAllClients(info)
end
end

Innerhalb von CreateFXData füllen wir die Informationsstruktur aus, damit alle Clients die gleichen Parameter erhalten.

Auf der Clientseite ( LightningVFXClient ), prüfen wir, ob dieser Client die FX ausführen sollte:


local function LightningFunc(info)
-- keine FX im Innenraum
if inVolumesCheckerFunc:Invoke() then
return
end
-- keine FX, wenn nicht in der "normalen" Welt
if not gameStateInfoFunc:Invoke("IsInNormal") then
return
end

Darüber hinaus führen wir die Sequenz aus, um Texturen, Positionen und Helligkeit festzulegen, Tweens auszuführen und task.wait(number) zu verwenden.Zufallsparameter stammen aus der Informationsstruktur, die wir vom Server erhalten haben, und einige Zahlen sind fest.


beam.Texture = textures[info.textIdx]
beamPart.Position = Vector3.new(info.center.X + og_center.X, og_center.Y, info.center.Y + og_center.Z)
-- Löschen
beam.Brightness = 10
ppCC.Brightness = maxPPBrightness
ppBloom.Intensity = 1.1
bottom.Position = top.Position
tweenBrightness:Play()
tweenPPBrightness:Play()
tweenPPBrightness:Play()
tweenBottomPos:Play()
tweenBrightness.Completed:Wait()
-- audiodateien
if audioFolder and audioPart then
if audioFolder.Value and audioPart.Value then
audioUtils.PlayOneShot(audioObj, audioFolder.Value, audioPart.Value)
end
end
task.wait(info.waitTillFlashes)
-- and so on

Um zu überprüfen, ob ein Spieler im Innenraum ist, verwenden wir eine Hilfsfunktion inVolumesCheckerFunc, die vor platzierte Volumen überprüft, die Innenräume annähern, und prüft, ob die Spielerposition in einem von ihnen ist (PointInABox).Wir hätten berührungsbasierte Erkennung verwenden können, aber wir stellten fest, dass, wenn ein Spieler innerhalb der Lautstärke einen Sitz nimmt, er die Lautstärke nicht mehr "berührt".Das Testen eines Punkts in ein paar Boxen ist einfacher, und wir tun es nur, wenn ein Spieler weit genug von der zuvor getesteten Position wegzieht.

Um zu überprüfen, ob ein Spieler in beschädigten Bereichen ist, rufen wir eine Hilfsfunktion gameStateInfoFunc auf, die den aktuellen Spielstatus überprüft.Um einen zufälligen Ton aus einem Ordner wiederzugeben, verwendeten wir auch eine Hilfsfunktion PlayOneShot.Für die Blitzschläge selbst waren diese in Photoshop sehr einfach zu erstellen; wir zeichneten eine wackelige Linie und fügten dann einen "Outer Glow"-Layereffekt hinzu.

Nutze Partikel-Emitter-Systeme

Die Heldenblitzschläge werden von einem Partikelsystem unterstützt, das einen entfernten Blitz vorschlägt, indem es den Eindruck einer Wolkenschicht im Hintergrund erzeugt, die Licht von entfernten Schlägen oder Wolken-zu-Wolken-Beleuchtung einfängt.Wir haben diesen Effekt durch ein sehr einfaches Partikelsystem erreicht, das eine Wolkenwerbetafel an der Peripherie der Hauptsturmwolke blinkt.Das System sendet eine Wolkenpartikelperiode periodisch mit einer zufälligen Transparenz-Kurve aus:

Lassen Sie Bäume im Wind wehen

Nachdem wir die Wolken und den Blitz so eingerichtet hatten, wie wir es wollten, mussten wir dann zwei weitere wichtige Bestandteile eines Sturms hinzufügen: den Wind und den Regen! Diese Elemente stellten einige Herausforderungen dar, unter anderem die Notwendigkeit, innerhalb der aktuellen Einschränkungen unserer Physik- und Spezialeffektsysteme von Studio zu arbeiten.Zum Beispiel ist es mit der heutigen Engine nicht möglich, Bäume mit echtem Wind zu bewegen, also nutzten wir PartikelEmitter-Effekte und benutzerdefinierte Charakteranimationen für die Bäume.

Wir wussten, dass wir den Effekt von Wind und Regen wirklich verkaufen mussten, wir brauchten die Bäume selbst, um sich zu Verschiebungswerkzeug.Es gibt ein paar Möglichkeiten, dies innerhalb der Engine zu tun, einschließlich der Bewegung von Teilen mit Plugins, die öffentlich verfügbar sind, mit TweenService oder der Animation von Modellen direkt.Für unsere Zwecke gaben uns Animationen die Möglichkeit, die Bewegung zu steuern, die wir von unseren Bäumen wollten, und es ermöglichte uns, eine einzige Animation zu verwenden, die wir unter allen Bäumen innerhalb des Erlebnisses teilen konnten.

Wir begannen, mehrere Bäume vom Endorse Model Pack - Forest Assets zu entfernen.Da diese Bäume bereits existierten und unsere Erfahrung im pazifischen Nordwesten stattfand, sparte es uns einige Zeit am Anfang, jedes Modellerstellen zu müssen.

Das Waldpaket enthält mehrere Baumarten, die Ihnen Zeit in Ihren eigenen Erfahrungen sparen können.

Nachdem wir unsere Bäume ausgewählt hatten, wussten wir, dass wir sie schälen mussten.Skinning ein Mesh ist der Akt, Gelenke (oder Knochen) an ein Mesh in einer anderen 3D-Modellierungsanwendung hinzuzufügen, wie z. B. Blender oder Maya, und dann Einfluss auf diese Gelenke/Knochen auszuüben, um das Mesh zu bewegen.Dies wird am häufigsten in humanoiden Charaktern verwendet, aber mit benutzerdefinierten Charaktern kannst du so ziemlich alles skinen.

Wir wussten, dass wir Zeit sparen und die gleiche Animationenwiederverwenden wollten, also bauten wir unser erstes Baumgerüst und stellten sicher, dass die gemeinsamen Namen generisch waren, weil wir diese gleichen Namen in den Geräten für die anderen Bäume verwenden wollten.Wir wussten auch, dass wir primäre, sekundäre und tertiäre Gelenke/Knochen einbeziehen mussten, damit sich die Stämme mit dem Wind biegen, die Äste schwingen und die Blätter so aussehen, als ob sie im Antwort darauf wackeln würden.Für diesen Prozess mussten wir eine sekundäre Bewegung erstellen, die ein Animationskonzept ist, bei dem jede Aktion dazu führt, dass andere Teile des Objekts auf diese Aktion reagieren und so aussehen, als würden sie der ursprünglichen Bewegung hinterherkommen.

Die Bäume haben primäre, sekundäre und tertiäre Gelenke, damit wir eine glaubwürdige Bewegung haben können, von der wir vom Wind herumgeblasen werden.

Sobald wir unsere Gelenke/Knochen erstellt hatten, war es Zeit, eine Testanimation zu erstellen, um sich um alle Gelenke und Knochen in Studio zu bewegen, um zu sehen, ob es sich so bewegt, wie wir es wollten.Um dies zu tun, mussten wir den Baum in Studio importieren durch die benutzerdefinierte Rig-Einstellung im 3D-Importeur , dann die Mesh mit dem Animations-Editor bewegen/animieren.Wir konfigurieren die Materialien und Texturen nach diesen Tests, aber Sie können das Ergebnis unten sehen.

Die gleiche Hierarchie innerhalb von Studio.

Nachdem wir mit den Ergebnissen auf diesem Baum zufrieden waren, war es Zeit, die gleiche Animation auf einem anderen Baum zu testen! Wir wussten bereits, dass es die gleiche Animation zwischen den verschiedenen Ringen für jeden eingebensein würde, also stellten wir sicher, dass unsere Animation so aussah, als wäre sie allgemein genug, um zwischen einem hohen Redwood- und einem stämmigen Beechwood-Baum zu arbeiten!

Die Animation, die wir auf dem Redwood-Baum importiert haben.

Um dies zu tun, nahmen wir den Beechwood-Baum aus diesem Waldpaket und bauten ein ähnliches Rig, verwendeten die gleiche genaue Namensgebung für die Gelenke.Das war so, dass die Animation, die wir zuvor importiert hatten, auch auf diesen Baum angewendet werden konnte.Da alle Animationen auf drehenden Gelenken basierten, spielte es keine Rolle, wie groß, klein, hoch oder breit der Baum war!

Der Beechwood-Baum hat die gleiche genaue Namensgebung für seine Gelenke, nur nicht in der gleichen Menge.Das ist in Ordnung, da das Animationssystem nur Animationen auf diese bestimmten Gelenke anwenden wird, die dem Namen entsprechen! Aus diesem Grund könnten wir die gleichen Animationen auf alles anwenden, das den Gelenknamen entspricht!

Nachdem wir Rig und Skin den Beechwood-Baum gemacht haben, konnten wir ihn importieren und die gleiche Animation anwenden.Das bedeutete, dass nur eine Iteration und Bearbeitung auf einer Datei durchgeführt und gespeichert werden musste, und es wurde auch bei der Leistung mit weniger Animationen gespart, wenn das Erlebnis ausgeführt wurde.

Mit dem Animations-Editor konnten wir die gleiche Redwood-Baumanimation auf den Beechwood-Baum anwenden!

Sobald wir alle Baumarten hatten, die wir animieren wollten, machten wir jede zu Paketen, so dass wir weiterhin bearbeiten und aktualisieren konnten, während wir mehrere der Animationen rund um den Hauptbereich des Erlebnisses spielen.Da wir wussten, dass sie eine Leistungskosten hatten, verwendeten wir sie knapp um das Haus herum, wo der Effekt am wertvollsten war! In der Zukunft, wenn dies effizienter wird, werden Sie in der Lage sein, immer mehr verkleidete Meshing-Instanzen hinzuzufügen!

Wir verwendeten animierte Bäume sofort rund um das Haus, wo der Vortex am stärksten war und der visuelle Effekt für die Spieler am wirksamsten wäre.

Abfall (Service)machen

Wir wollten, dass der Regen schwer aussieht und der Nebel und die Trümmer durch die Bäume wehen.Um dies zu tun, haben wir einige unsichtbare Teile eingerichtet, die als Partikelmengen mit Kindern Partikelstrahler direkt unter den großen Sturmwolken agieren.Aufgrund der Partikelzählgrenze in Studio konnten wir keinen PartikelEmitter für den gesamten Platzverwenden.Stattdessen fügten wir mehrere hinzu, die die gleiche Größe wie einander in einem Rastermuster über dem spielbaren Platzhatten, weil die Anwesenheit der Bäume bedeutet, dass die Spieler nicht sehr weit sehen könnten.

Wir verwendeten mehrere Volumen, um sowohl die Menge des Regens als auch die spezifische Abdeckung des Regens zu erhalten, die wir wollten.

Die Regentropfen nutzten eine neue PartikelEmitter-Eigenschaft ParticleEmitter.Squash, mit der du einen Partikel länger oder härter machen kannst.Es ist besonders nützlich für Regen, weil es bedeutete, dass wir keine große Texturbrauchten, einfach diejenige strecken, die da war.Wissen Sie nur, dass, wenn Sie den Wert von ParticleEmitter.Squash erhöhen, Sie möglicherweise auch die Gesamteigenschaft ParticleEmitter.Size erhöhen müssen, damit sie nicht zu dünn ist! Insgesamt war es nur eine Frage der Spielerei mit den Werten, bis wir den Regen schwer genug bekamen, aber nicht so sehr, dass die Sichtbarkeit des Erlebnisses blockiert wurde!

Ein Squash-Wert von 3 beginnt, die Textur länger zu dehnen.
>

Ein Squash-Wert von 20 streckt die Partikel viel länger aus, aber wir mussten auch den Größenwert erhöhen.

Für den Nebel, den Nebel und die Blätter, die durchströmten, war es viel einfacher, eine einzige größere Teilmenge hinzuzufügen, die weniger Bereiche abdeckte, weil wir keine Tonne von Partikeln brauchten, die gleichzeitig laufen.Wir begannen, indem wir ein Volumen einrichteten und die Frequenz der Partikel erhielten, wo sie sie wollten.

Es gab ein paar Partikelteilvolumen, so dass wir keine Partikel im Haus hatten, und weil wir nicht fühlten, dass sie sich wie der Nebel durch die Bäume bewegen mussten.
>

Die Partikelteilmenge war viel größer, da die Partikel groß waren und wir nicht so genau mit der Lokalisierung sein mussten.
>

Danach haben wir unsere Blattblasen und Windtexturen erstellt und die Partikel so eingestellt, dass sie sich alle mit unterschiedlichen Geschwindigkeiten drehen/bewegen und mit unterschiedlichen Geschwindigkeiten starten.Das bedeutete, dass die größeren Nebelpartikel natürlicher interagieren würden und nicht so aussehen würden, als würde sich eine wiederholende Textur, vor allem wegen ihrer Größe.

Nebelpartikel
>

Blattpartikel
>

Das Ergebnis war einige großartige Aktionen zwischen den sich bewegenden Bäumen, dem blasenden Fenster und dem Blitz, um den Effekt des Sturms zu schaffen, der das zentrale Auge des Sturms umgibt.

Stelle das Auge des Sturms ein

Das zerbrochene steinige Auge mit leuchtendem Kern soll den Spielern den ersten Hinweis geben, dass es etwas Unheimliches und Mysteriöses am Haus passiert, das sie weiter erforschen sollen.Da unsere Szene dunkel ist und das Auge weit in den Himmel blickt, war es wichtig, eine glaubwürdige zerbrochene Steinsilhouette zu erstellen, aber es war nicht so wichtig, glaubwürdige Details der Steinoberfläche zu erstellen, weil Spieler das nicht sehen könnten.Zu wissen, was für deine Spieler realistisch ist, innerhalb der Beleuchtung deiner Szene zu sehen, bevor du viel Zeit in unnötige Details investierst, kann dir viele Ressourcen im Entwicklungsprozess sparen.

Die frühe Einrichtung der endgültigen Beleuchtung in deiner Szene kann dir viel unnötige Arbeit ersparen.Du würdest die Oberflächendetails auf den Ringen mit der letzten Beleuchtung unserer Szene nicht sehen können, also gab es keine Notwendigkeit, die Zeit damit zu verbringen, sie dort hinzuzubringen!

Die Entfernung vom Spieler bedeutete auch, dass wir uns vollständig auf eine normale Karte für die Details der Oberfläche des Auges verlassen konnten, so dass das Netz nur eine einfache Kugel ist! Wir haben die Details in ein hochpoliges Netz geschnitzt und seine normale Karte auf eine viel niedrigere Kugel gebacken, so dass wir all diese schönen Details ohne die enorme Leistungskosten erhalten konnten.

Hohe Poly-Skulptur
>

Niedriges Poly-Mesh
>

Das niedrigpolige Netz mit den normalen Informationen aus der hochpoligen Skulptur, die gebacken wurde

Um dem Auge ein übernatürliches Gefühl zu verleihen und seine Präsenz zu betonen, beschlossen wir, ein leuchtendes, neonfarbenes Magma zu schaffen, das durch seine Risse sickern würde.Während es keinen emissiven Kanal für das Aussehender Oberfläche gibt, überwinden wir diese Hürde, indem wir das Auge aus 2 Kugeln erstellen: eine für die felsige Außenseite und eine zweite, etwas kleinere, für das leuchtende Magma.In Substance Painter haben wir eine Grundfarbtextur für die äußere Kugel mit Transparenz in den Bereichen erstellt, in denen wir wollten, dass der innere Kern durchkommt.In Mixer haben wir die innere Kugel "vertexiert" für eine billige und einfache Art, einige Farbvariationen darauf zu bekommen.

Das Gipfelbild auf der inneren Kugel.Wir haben einen Gradienten erstellt, der am leichtesten rund um das Auge war, um ein größeres Gefühl der Tiefe und des visuellen Interesses zu geben.

Eine weitere Herausforderung, mit der wir uns konfrontiert sahen, als wir das Auge erstellten, war durch unsere Verwendung von Streaming in Verbindung mit der Entfernung des Auges vom Spieler:inauferlegt.Angesichts der Zentralität dieser Struktur wollten wir, dass sie trotz ihrer Entfernung immer sichtbar bleibt, aber ohne irgendwelche Hacks zu ihrem Mesh, konnten die Spieler das Auge nicht sehen, es sei denn, sie waren im Solarium.Wir konnten die ständige Präsenz des Auges in der Szene erzwingen, indem wir einige Geometrie zum Auge und seinen Ringen hinzufügten.Diese Geometrie sitzt direkt unter der Oberfläche des Geländeund das reicht aus, um die Engine dazu zu bringen, zu glauben, dass die Kugel näher am Spieler ist als sie ist und sie immer wieder einzustreamen.Dies sollte aber ziemlich sparsam erfolgen, da das Zwangszappen von zu vielen großen Objekten, die gestreamt werden sollen, die Vorteile von Streaming deaktivieren und die Erfüllungnegativ beeinflussen könnte.

Wir konnten der Augen und seinen Ringen Bewegung hinzufügen, dank des gleichen Skripts, das wir verwendet haben, um die Wolkenmeshes zu drehen.Für einen letzten Schliff entschieden wir uns, einen Hinweis auf die Präsenz einer anderen Welt jenseits der Wolken hinzuzufügen, aber wir mussten einen kreativen Ansatz wählen, um mehr Geometrie in die Szene einzufügen und zusätzlich mit den zuvor erwähnten Hindernissen, die durch Streaming aktiviert wurden, umgehen zu müssen.Wir haben eine Szene erstellt, die aufgrund der relativen Größe und Entfernung der Objekte eine Menge Tiefe hatte, ein Bild dieser Szene gerendert und dann dieses Bild als Aufkleber auf einem Teil verwendet, das direkt hinter dem Auge des Sturms platziert wurde.Wir verwendeten die gleiche Methode, um dieses Teil zu drehen, wie wir es für das Auge und seine Ringe verwendet hatten.

Das Bild, das wir verwendet haben, um eine Illusion einer Welt jenseits der Wolken zu erschaffen.Wenn Spieler weit von etwas entfernt sind, reicht ein einfaches Bild aus, um die Illusion einer größeren Tiefe und Komplexität in deiner Szene zu erzeugen!

Erweitere die Pantry machen

Eines der amüsantesten Dinge, die zu produzieren waren, waren die korrupten Räume, in denen wir die Erwartungen der Spieler an die Realität untergraben konnten, indem wir sie buchstäblich um sie herum veränderten.Zum Beispiel wollten wir im Rätsel des Vaters einen Moment simulieren, der einem Albtraum ähnelt, bei dem es egal ist, wie schnell du ausführen, der Raum sich wie immer länger anfühlt.Wir beschlossen, eine ausgedehnte Speisekammer zu erstellen, die den Spielern entkommen würde, wenn sie nach Zutaten suchten, um den Raum in seinen normalen Zustand zurückzubringen.

Wir haben das mit einer einfachen Bewegung der Wände und einer klugen Anordnung unserer Räume eingerichtet, die auf beiden Seiten der Küche erscheinen würde.Im normalen Zustand des Raums war die Pantry ein einfacher Flur, aber im korrupten Platzwar sie eigentlich viel länger mit mehreren Flügeln und einer falschen Wand!

Der korrupte Zustand der Küchenkammer.
>

Die falsche Wand weg von den Spielern.
>

Die falsche Wand war eine Modellgruppe, die wir zurückbewegen würden, wenn Spieler einen Auslöserlautstärke betreten würden, der zuvor ein durchsichtiger Teil der Küche war, durch den sie gehen würden.Dieser Trigger wurde auch in einem Skript verwendet, das ähnlich wie die auf all unseren Türen verwendet wurde, und rief die TweenService an, um sich von einem Ziel zum anderen zu bewegen.Wir verwendeten Teilvolumen, um der Tweening-Operation mitzuteilen, bei der die Start- und Endpositionen für die Wand waren.

Das Teilvolumen löst eine falsche Wand hinter sich aus, um sich zu seinem Endpunkt zu bewegen.Es wird in diesem Bild mit einem gelben Farbton sichtbar gemacht.
Target_Closed war ein generisches Zielteil, das wir auf all unsere Türen angewendet haben, wo sie sich drehen sollten.Hier wurde es umgebaut, um der Hallenwand mitzuteilen, wo es hin Los.

Da TweenService ein so allgemeines System ist, musste unser Wanddatenmodell alle dieselben Komponenten enthalten.Zum Beispiel spielt ein allgemeines "Door_Script"-Skript einen Ton ab, der von einem "Wert" unter dem Modell "Grow_Wall" definiert wird.Das gleiche Skript, das. PL: die Skripts, mit einigen Änderungen im folgenden Codebeispiel, hat auch Audio ausgelöst, wenn die Pantry sich bewegt.Dies hat der Bewegung viel hinzugefügt!


local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local model = script.Parent
local sound = model.Sound.Value
local trigger = model.Trigger
local left = model.TargetL_Closed
local right = model.TargetR_Closed
local tweenInfo = TweenInfo.new(
model.Speed.Value, --Zeit/Geschwindigkeit des Türwechsels
Enum.EasingStyle.Quart, --Entspannungsstil
Enum.EasingDirection.InOut, --Entlastungsrichtung
0, --Zählen wiederholen
false, --Wahrheit umkehren
0 --Verzögerung
)
local DoorState = {
["Closed"] = 1,
["Opening"] = 2,
["Open"] = 3,
["Closing"] = 4,
}
local doorState = DoorState.Closed
local playersNear = {}
local tweenL = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Open.CFrame})
local tweenR = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Open.CFrame})
local tweenLClose = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Closed.CFrame})
local tweenRClose = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Closed.CFrame})
local function StartOpening()
doorState = DoorState.Opening
sound:Play()
tweenL:Play()
tweenR:Play()
end
local function StartClosing()
doorState = DoorState.Closing
--Modell["Tür"]:Spielen()
tweenLClose:Play()
tweenRClose:Play()
end
local function tweenOpenCompleted(playbackState)
if next(playersNear) == nil then
StartClosing()
else
doorState = DoorState.Open
end
end
local function tweenCloseCompleted(playbackState)
if next(playersNear) ~= nil then
StartOpening()
else
doorState = DoorState.Closed
end
end
tweenL.Completed:Connect(tweenOpenCompleted)
tweenLClose.Completed:Connect(tweenCloseCompleted)
local function touched(otherPart)
if otherPart.Name == "HumanoidRootPart" then
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
--print("berühren")
playersNear[player] = 1
if doorState == DoorState.Closed then
StartOpening()
end
end
end
end

Sobald wir die falsche Wand an die Rückseite des Raums bewegt hatten, brauchten wir den Rest des Inhalts, um sich mit ihr zu bewegen.Um das zu tun, mussten alle lose Gegenstände in der Pantry an der Wand verschweißt werden, während sie sich bewegte.Mit der Verwendung von Schweiß约束 konnten wir schnell alle Objekte an die Schrankwand schweißen, um sich als ein einzelnes Objekt zu bewegen.Dies bedeutete, dass wir die Möglichkeit hatten, diese Gegenstände zu entfernen, damit Spieler darauf stoßen und sie herumwerfen konnten!

Erstelle das korrupte Baumhaus

Studio ist eine fantastische physikbasierte Engine, die du verwenden kannst, um alles von einem schwingenden Tor bis zu einer drehenden Plattform zu erstellen.Mit unserer Demo wollten wir Physik verwenden, um ein Gefühl von Realismus in einem sonst unrealistischen Set von Umgebungen zu schaffen.Mit nur wenigen Einschränkungen kannst du einige lustige und herausfordernde Hinderniskurse innerhalb deiner eigenen Erfahrungen erstellen!

Einschränkungen sind eine Gruppe von physisch basierten Motoren, die Objekte ausrichten und Verhaltensweisen einschränken.Zum Beispiel können Sie eine Stangen约束 verwenden, um sich mit Objekten zu verbinden, um sie auf eine feste Entfernung voneinander zu halten, oder die Seil约束, um eine Lampe am Ende der Linie hängen zu lassen.Für das Puzzle des Sohnes, in dem Spieler in den korrupten Zustand der Studie transportiert werden, wollten wir die Welt buchstäblich auf die Seite werfen.Das würde die Erwartungen der Spieler an die Realität und die Regeln dort untergraben, während das Physiksystem immer noch so verwendet wird, wie es gedacht war!

Das Puzzle des Sohnes begann mit den Spielern im selben Raum, aber alles war quer.

Sobald Spieler in den Hauptbereich des Puzzles vordrangen, wurden sie mit einer vertrauten Sicht auf Roblox begrüßt: einem Hindernisparcours.Dieser spezielle Hinderniskurs bestand aus mehreren drehenden Plattformen und drehenden Wänden, zusammen mit "sicheren Bereichen", die die Geschichte voran trieben.Wir werden uns auf die drehenden/drehenden Elemente konzentrieren.

Das verrückte Aussehen verbarg die Tatsache, dass das Spiel hier sehr einfach war.

Warum haben wir hier Einschränkungen verwendet? Weil TweenService oder andere Methoden den Spieler:innicht bewegen würden, während er auf ihnen steht.Ohne dass sich das Objekt bewegt, könnte jemand auf eine Plattform springen und sie würde sich von unter ihnen drehen.Stattdessen wollten wir, dass Spieler durch eine drehende Plattform navigieren, während sie versuchen, auf die nächste zu springen.Aufgrund dieses Ansatzes fühlten sich die Spieler dort verwurzelt, wo sie standen, während sie eine Entscheidung trafen, wie sie durch den Kurs fortfahren sollten, und wir mussten nichts Besonderes tun, um sicherzustellen, dass sie mit einer drehenden Oberfläche fortbewegten!

Du könntest deine Freunde drehen sehen, während du versuchst, auch den Hindernisparcours zu navigieren.

Um dies zu tun, mussten wir zuerst Assets aus unserem aktuellen Kit verwenden und jeden neuen Inhalt für einen visuellen Effekt hinzufügen.Wir haben einige unvollständige Wände und Plattformen mit Löchern erstellt, um die Geschichte der Großmutter zu erzählen, die das Baumhaus gebaut hat.Da wir keine Menge an einzigartigen Plattformen erstellen wollten, haben wir 4 verschiedene Basisteile und Geländerteile separat erstellt.Dies ermöglichte es uns, einzelne Basis- und Geländerteile zu mischen und zu kombinieren, um eine Menge Vielfalt zu haben.

Wir wussten, dass wir, da wir Einschränkungen verwendeten, diese Meshes nicht verankern könnten, weil sie sich nicht bewegen würden, selbst wenn eine Einschränkung/Motor sie antrieb.Die Einschränkung musste ein Kind von etwas sein, das verankert war, damit die Plattform nicht einfach aus der Welt herausfiel.Wir haben dies durch ein Teil gelöst, das wir Motor_Anker genannt haben, das eine Scharnierzwang hatte, um die gesamte Bewegung der Plattform zu treiben.Danach benötigten wir die beiden Meshes, um sich als eines zu bewegen, also erstellten wir ein Teil, das wir Motor_Turn nannten, und schweißten dann die beiden Meshes daran.Auf diese Weise wäre die Einschränkung in der Lage, an einem einzigen Teil zu arbeiten, im Gegensatz zu mehreren Scharnieren, die mit mehreren Teilen arbeiten.

Es war jetzt Zeit, das tatsächliche Verhalten der Scharnierzwang selbst einzurichten und die Anhänge hinzuzufügen, die als Orientierung des Teils und der Einschränkung zusammen fungieren würden.Wir haben das drehende Zubehör auf dem Motor_Turn platziert, an den sich die Gehwegteile geschweißt wurden, und ein weiteres Zubehör für das Ankerverhalten auf dem Motor_Anker selbst, neben der Beschränkung, angebracht.Da dies besitzenvon dem Spieler gedreht werden musste, anstatt von ihm beeinflusst zu werden (wie ein Türscharnier), legten wir das HingeConstraint.ActuatorType auf Motor fest, das die Einschränkung wie ein selbstbewegender Motor behandelt.

Um die Plattformen mit konstanter Geschwindigkeit zu drehen, stellen wir dann die Eigenschaften HingeConstraint.AngularVelocity, HingeConstraint.MotorMaxAcceleration und HingeConstraint.MotorMaxTorque auf Werte ein, die Bewegung ermöglichen und Unterbrechungen verhindern, wenn ein Spieler darauf springt.

Anhang 0 war im Wesentlichen der Anker für das Scharnier und Anhang 1 repräsentierte das Scharnier selbst.Wir hatten das Scharnier ständig drehend, aber du kannst auch ein Scharnierhindernis für Türen verwenden.

Jetzt mussten wir die drehenden Wände herstellen.Die Wände mussten sich an ihrem offensichtlichen Zentrum drehen, und wir wussten, dass wir wollten, dass sie in der Lage sind, jede Orientierung im Verhältnis zum Rest der Stufezu handhaben.Wie die Plattformen haben wir diese so konstruiert, dass alle Wände unverankert und mit dem Motor_Turn verschweißt wurden.

Wir wollten so viele der tatsächlichen Baumhaus-Modelle wiederverwenden, um bei der Erfüllungzu sparen, also folgten wir einem ähnlichen Weg wie die Plattformen.Mehrere Wandtypen wurden hergestellt, die in verschiedenen Kombinationen zusammenhalten konnten, um einige Variation zu haben.

Wir verwendeten Texture Objekte auf top von SurfaceAppearance Objekten, um unseren Grundmaterialien etwas Variation hinzuzufügen.Texturen, ähnlich wie Bilder, ermöglichen es Ihnen, ein Bild auf einer Fläche eines Meshes zu platzieren.Dies kann nützlich sein, wenn du Schmutz zu einer Ziegelwand hinzufügen oder Holz alt aussehen lassen möchtest, während du dasselbe Basis-Holzmaterial verwendest. Texture Objekte haben ein etwas anderes Verhalten als Decal Objekte, bei denen Sie das Bild wie gewünscht einteilen und verschieben können, was sehr nützlich ist, wenn Sie Ihre Overlay-Texture skalieren möchten und es nicht stört, wiederholt zu werden!

Du kannst sowohl das ähnliche Verhalten als auch die Einrichtung für die Beschränkungsehen und auch, wie wir Texture Objekte verwendet haben.

Sobald wir ein paar Plattformen und drehende Wände getestet hatten, machten wir mehrere Variationen und spielten mit ihrer Platzierung, um sicherzustellen, dass der Hinderniskurs herausfordernd, knifflig und auch klar war, wo der Spieler Los! Es dauerte einige Anpassungen an ihre Werte und Positionen, um sie gut laufen zu lassen.Wir hatten mehrere Punkte, in denen die Plattformen und Wände aufeinander oder die Umgebung trafen, aber mit einigen Bewegungen und häufigen Tests konnten wir auf die Einstellungen landen, die wir in der Demo haben!

Wenn du dir nicht sicher bist, welche physischen Objekte getroffen werden, kannst du auf Kollisionsgenauigkeit von der Visualisierungsoptionen-Widget in der oberen rechten Ecke des 3D-Ansichtsfensters umschalten.

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.
Wenn die Kollisionsvisualisierung deaktiviert ist, kannst du die normale Geometrie-Repräsentation sehen, die im Spiel angezeigt wird.
Wenn die Kollisionsvisualisierung aktiviert ist, können Sie sehen, dass die Baumblätter keine Kollisionen haben, so dass sie nicht mit den drehenden Plattformen oder Wänden interagieren.

Wie Sie unten sehen können, sind die Eingangstüren-/Fensterlöcher sichtbar, aber die kleineren Details wie die Unterverkleidung sind nicht.Das liegt daran, dass die CollisionFidelity Eigenschaft für die Wände auf Box gesetzt wurde.Wir brauchten die Präzision für diese Panels nicht, also um Kosten für die Leistung zu sparen, war dies detailliert genug, auf die Spieler springen zu können.Mit den Plattformen und drehenden Wänden erledigt, mussten wir nur noch detaillierte Assets wie Kisten und Lampen hinzufügen, dann war es bereit zum Spielen!