Sviluppa un Mondoin movimento

*Questo contenuto è tradotto usando AI (Beta) e potrebbe contenere errori. Per visualizzare questa pagina in inglese, clicca qui.

Creare movimento in qualsiasi ambiente all'interno di un'esperienza lo aiuta a sentirsi istantaneamente più immersivo e realistico nel nostro Mondo, che si tratti di movimento ambientale, porte reattive dall'interazione del giocatore o anche scatole che si muovono quando si scontrano con loro.Studio ha molti metodi unici per creare movimento al fine di aiutare i mondi a sentirsi più vivi, tra cui un sistema di fisica, TweenService , e animazioni, e analizzare le esigenze specifiche della tua esperienza può aiutarti a determinare quale utilizzare.In questa sezione, mostreremo come abbiamo determinato quale tipo di movimento volevamo creare in Studio e quali strumenti abbiamo usato per realizzare questi obiettivi distinti.

Crea la tempesta

La tempesta ha attraversato molte iterazioni prima che ci siamo accordati su ciò che è in diretta in The Mystery of Duvall Drive.Fin dall'inizio, abbiamo pensato alla tempesta come a un gigantesco pilastro di obsidiana, e in iterazioni successive l'abbiamo considerata un gigantesco portale verso lo Spazio.Dopo aver sperimentato con molte tempeste diverse con look e sensazioni unici per loro, ci siamo accordati su una tempesta con un "occhio" centrale più piccolo perché:

  • La tempesta dovrebbe dare ai giocatori una sensazione dell' impatto di questo evento sul mondo , inclusi alberi che soffiano e detriti che volano in giro.
  • Il vortice rotante del cloud stesso dovrebbe dare ai giocatori un'occhiata al portale centrale senza rivelare tutto .Ciò incoraggeresti i giocatori a indagare più da vicino per vedere cosa sta succedendo.
  • Il punto più stretto di luce ci consentirebbe di concentrarci sulla composizione della casa , che è sia il personaggio principale che dove è situata la maggior parte del gameplay.

Per rendere la tempesta dinamica, aggressiva e sempre in evoluzione all'interno del suo Ambiente, abbiamo utilizzato i seguenti sistemi e funzionalità:

  1. TweenService - Per il movimento del cloud.
  2. Modifiche di illuminazione - Per creare il fulminamento dal cloud al cloud.
  3. Fasci - Per la "luce volume" e i fulmini.
  4. Emittenti di particelle - Per detriti che volano fino al portale e volano in giro a causa del vento che soffia.
  5. Animazioni - Per gli alberi che stavano soffiando nel vento.

Aggiungi nuvole con texture

Mentre nubi dinamiche sono grandi per le nubi realistiche di alta altitudine normali, avevamo bisogno di qualcosa che fosse drammatico e che potessimo dirigere e personalizzare più pesantemente.Per fare ciò, abbiamo applicato apparenza della superficie oggetti con semi-trasparenza a una serie di mesh di nuvole pesantemente sovrapposte e stratificate al fine di contraffare la copertura delle nuvole.Perché li abbiamo sovrapposti e stratificati così pesantemente? Perché quando ogni mesh cloud si muove a velocità diverse, si intersecano e creano forme di cloud che vanno dentro e fuori l'uno dall'altro.Questo processo ha fatto sentire ai cloud un po' più dinamici e naturali, nonostante fossero solo dischi in rotazione.Era anche importante che le nuvole fossero semi-trasparente , perché volevamo che i giocatori potessero guardarle per vedere qualcosa di luminoso al centro prima di arrivare alla casa!

Una singola Mesh, magliadel cloud.
>

Reti di cloud stratificate senza le loro texture!
>

Poiché ogni mesh cloud doveva essere massiccia per circondare completamente la casa e trasmettere quanto fosse enorme la tempesta, sapevamo di dover piastrellare la texture che volevamo utilizzare sui singoli mesh cloud in modo che si ripetesse pesantemente su tutta la superficie del Mesh, maglia.Abbiamo testato i materiali che abbiamo realizzato per il cloud su queste parti semplici, quindi li abbiamo applicati al vortice!

A differenza di emittenti di particelle o raggi, le maglie ci hanno permesso di essere in grado di rimbalzare la luce da ogni Mesh, maglia, il che era importante quando volevamo implementare i fulmini cloud-to-cloud.Abbiamo anche modellato nella torsione in modo che la luce rimbalzante su di essa avrebbe sembrato avere profondità! Questo era importante soprattutto nelle situazioni in cui le esigenze di prestazioni dell'esperienza hanno abbassato i livelli di qualità dell'aspetto della nostra superficie.

Una volta iniziato ad aggiungere illuminazione ad esso, abbiamo dovuto aggiungere dettagli alle maglie per renderle reagire meglio all'illuminazione!

Ruota le maglie del cloud

Dopo che eravamo soddisfatti dell'aspetto visivo generale delle nuvole, avevamo bisogno di metterlo in moto! Avevamo le forme generali di ogni strato di nuvole in Posto, ma ci sono voluti alcuni tentativi e errori per assicurarsi che l'effetto di rotazione fosse bello in pratica.Abbiamo inizialmente provato ad utilizzare restrizioni per introdurre la velocità che avrebbe guidato fisicamente le nuvole a Sposta.Questo era più difficile di quanto volevamo che fosse per essere ripetuto in seguito e il giocatore non interagirebbe mai con esso, quindi non avevamo bisogno che fosse così preciso nel suo movimento.

Volevamo un metodo facile da usare per ruotare le istanze che fossero troppo lontane per essere interattive, come le nuvole, o troppo piccole o decorative per essere importanti per il gameplay/la fisica, come i mobili interni come piccole lampade.Abbiamo deciso di utilizzare un LocalScript per ridurre la larghezza di banda client-server, consentire un movimento più fluido e far sì che ogni mesh cloud sia in grado di avere un diverso tasso di rotazione e ritardo.Per renderlo più generico, abbiamo anche reso possibile specificare l'asse di rotazione.È possibile utilizzare 3 attributi, ma per il nostro caso abbiamo utilizzato 3 valori: Axis , Delay e Speed .

Come in molti casi nella demo, abbiamo utilizzato un tag LocalSpaceRotation per poter gestire le istanze interessate in Studio utilizzando un Collegaredi marcatura delle istanze.Abbiamo utilizzato solo un singolo LocalScript che ha gestito tutte le istanze contrassegnate utilizzando il CollectionService in modo che non avessimo una tonnellata di script da mantenere durante il processo di sviluppo.

Nella nostra demo, porzioni del mondo vengono clonate dall'ServerStorage spazio di lavoro come necessario, quindi abbiamo dovuto gestire casi in cui oggetti contrassegnati sono stati creati e distrutti.Con LocalScripts , dobbiamo anche essere consapevoli dello streaming, dove le maglie e i loro valori figli possono essere trasmessi in entrata e in uscita.Abbiamo processato inizialmente oggetti posizionati nella funzione Init() e connessi a CollectionService.GetInstanceAddedSignal e CollectionService.GetInstanceRemovedSignal per oggetti contrassegnati per gestire oggetti appena creati/distrutti.La stessa funzione SetupObj è stata utilizzata per inizializzare nuovi oggetti in Init() e in CollectionService.GetInstanceAddedSignal .


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 è una mappa che ha informazioni per tutti gli oggetti pertinenti, come la loro velocità di rotazione e l'asse.Nota che non chiamiamo SetupObj da CollectionService.GetInstanceAddedSignal immediatamente, ma abbiamo aggiunto un oggetto in objInfoQueue .Con oggetti di streaming e clonazione sul Server, quando viene chiamata CollectionService.GetInstanceAddedSignal , potremmo non aver ancora avuto i nostri Axis , Delay e Speed valori, quindi aggiungiamo l'oggetto in una coda e chiamiamo SetupObj sulla successiva cornice della funzione Update finché i valori non sono stati lì e abbiamo potuto leggerli nella struttura "info" per oggetto.

Abbiamo ruotato le istanze nella funzione Update connessa al battito cardiaco.Abbiamo ottenuto la trasformazione genitrice (parentTransform), accumulato un nuovo angolo di rotazione ( curObjInfo.curAngle ) in base alla velocità di rotazione di questo oggetto, calcolato la trasformazione locale ( rotatedLocalCFrame) , e infine lo abbiamo impostato al CFrame .Nota che sia il genitore che l'oggetto possono essere un Model o MeshPart , quindi abbiamo dovuto controllare IsA("Modello") e utilizzare o un PrimaryPart.CFrame o CFrame .


local parentTransform
if parentObj:IsA("Model") then
if not parentObj.PrimaryPart then
-- la parte principale potrebbe non essere ancora trasmessa
continue -- aspetta che la parte primaria si replica
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

Abbiamo controllato per un valido Model.PrimaryPart per essere impostato per gestire lo streaming.Se un aggiornamento è stato richiesto sul nostro oggetto mentre un Model.PrimaryPart (che può puntare a una Mesh, magliafiglia) non è stato ancora trasmesso, salteremmo l'Aggiornarmento.Il sistema attuale è una seconda iterazione della rotazione dell'oggetto e il sistema precedente funzionava in modo diverso: i valori sono stati 12 volte diversi! Per mantenere gli stessi dati, l'abbiamo convertita nel nostro script, come "12 * obj.Speed.Value".

Progetta colpi di fulmini

Poiché Studio non offre un generatore di fulmini fuori dalla scatola e il sistema delle particelle aveva alcune limitazioni che non funzionerebbero per gli strike di fulmini dell'eroe, abbiamo dovuto essere creativi con una soluzione per gli strike di fulmini dell'eroe.Abbiamo deciso su due sistemi principali per comporre il fulmine: i raggi texturizzati per gli strike fulmini dell'eroe che provengono dall'occhio della tempesta sono scriptati raggi texturizzati che rivelano e si sincronizzano con gli effetti audio e post-process, e un semplice effetto di particelle per il fulmine a distanza tra le nuvole.

Raggi di texture

Di solito utilizziamo uno sequencer o uno strumento di cronologia per guidare il timing di un effetto colpo di luce come questo, ma poiché Studio non offre ancora questa funzionalità, abbiamo deciso di scrivere script che controllino il timing del colpo di luce.Lo scripting di questo effetto è piuttosto semplice, ma raggiunge i seguenti importanti obiettivi:

  1. Gli elementi degli scarti del fulmine, come le loro texture, la luminosità e i ritardi, sono randomizzati con ogni colpo.
  2. I cambiamenti audio e post FX sono sincronizzati con gli attacchi FX.
  3. I giocatori che sono all'interno o nell'area corrotta non sarebbero in grado di vederli o sentirli.

Abbiamo un lato server Script che calcola vari parametri e tempistiche, li invia a tutti i client e attende una quantità casuale di tempo:


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

All'interno di CreateFXData , riempiamo la struttura di informazioni, in modo che tutti i client ottengano gli stessi parametri.

Sul lato client ( LightningVFXClient ), controlliamo se questo client dovrebbe eseguire il FX:


local function LightningFunc(info)
-- nessun FX quando all'interno
if inVolumesCheckerFunc:Invoke() then
return
end
-- nessun FX quando non nel Mondo"normale"
if not gameStateInfoFunc:Invoke("IsInNormal") then
return
end

Inoltre, eseguiamo la sequenza per impostare le texture, le posizioni e la luminosità, eseguire gli adolescenti e utilizzare task.wait(number) .I parametri randomizzati provengono dalla struttura delle informazioni che abbiamo ricevuto dal Servere alcuni numeri sono fissi.


beam.Texture = textures[info.textIdx]
beamPart.Position = Vector3.new(info.center.X + og_center.X, og_center.Y, info.center.Y + og_center.Z)
-- Cancella
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()
-- audio/suono
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

Per controllare se un giocatore è all'interno usiamo una funzione aiutante inVolumesCheckerFunc, che supera i volumi pre-posizionati che approssimano le aree interne e controlla se la posizione del giocatore è all'interno di uno di essi (PointInABox).Avremmo potuto usare la rilevazione basata sul tocco, ma abbiamo scoperto che quando un giocatore si siede all'interno del volume, non sta più "toccando" il volume.Testare un punto in poche scatole è più semplice, e lo facciamo solo quando un giocatore si muove abbastanza lontano dalla posizione precedentemente testata.

Per controllare se un giocatore è in aree corrotte, invochiamo una funzione ausiliaria gameStateInfoFunc che controlla lo stato del gioco attuale.Per riprodurre un suono casuale da una cartella, abbiamo anche utilizzato una funzione ausiliaria PlayOneShot .Per i fulmini stessi, questi sono stati super facili da creare in Photoshop; abbiamo disegnato una linea scricchiolante, quindi aggiunto un effetto layer "Outer Glow".

Utilizzare sistemi emittenti di particelle

Gli strike fulmini dell'eroe sono supportati da un sistema di particelle che suggerisce un fulmine distante creando l'impressione di uno strato di nuvole in background che cattura la luce da colpi distanti o illuminazione cloud-to-cloud.Abbiamo ottenuto questo effetto attraverso un sistema di particelle molto semplice che lampeggia un cartellone pubblicitario sul periferia del principale cloud tempesta.Il sistema emette un periodo di particelle di cloud periodicamente con una curva di trasparenza randomizzata:

Fai soffiare gli alberi nel vento

Dopo aver avuto le nuvole e i fulmini che hanno funzionato nel modo in cui volevamo, abbiamo poi avuto bisogno di aggiungere altre due componenti principali di una tempesta: il vento e la pioggia! Questi elementi hanno presentato alcune sfide, tra cui il dover lavorare all'interno delle limitazioni attuali del nostro sistema di fisica e effetti speciali di Studio.Ad esempio, rendere gli alberi muoversi con il vento reale non è possibile nell'attuale motore, quindi abbiamo utilizzato gli effetti di mittente di particelle e animazioni di personaggi personalizzati per gli alberi.

Sapevamo di vendere davvero l'effetto del vento e della pioggia, avevamo bisogno degli alberi stessi per Sposta.Ci sono alcuni modi in cui puoi farlo all'interno del motore, incluso spostare parti utilizzando plugin che sono pubblicamente disponibili, usando TweenService , o animare i modelli direttamente.Per i nostri scopi, le animazioni ci hanno dato la possibilità di controllare il movimento che volevamo fuori dai nostri alberi, e ci ha permesso di utilizzare un'unica animazione che potevamo condividere tra tutti gli alberi all'interno dell'esperienza.

Abbiamo iniziato sbucciando diversi alberi dal Modello di approvazione del pacchetto - Risorse forestali.Poiché questi alberi esistevano già, e la nostra esperienza si è svolta nel Pacifico nordoccidentale, ci ha risparmiato un po' di tempo all'inizio dal dover creare ogni modello di albero.

Il pacchetto Foresta contiene diversi tipi di alberi, che possono risparmiarti tempo nelle tue esperienze.

Dopo aver scelto i nostri alberi, sapevamo di doverli sbucciare.Raschiare una mesh è l'atto di aggiungere articolazioni (o ossa) a una mesh in un'altra applicazione di modellazione 3D, come Blender o Maya, quindi applicare l'influenza su quelle articolazioni/ossa per spostare la Mesh, maglia.Questo è più comunemente utilizzato in personaggi umanoidi , ma con personaggi personalizzati , puoi skinare praticamente qualsiasi cosa.

Sapevamo che volevamo risparmiare tempo e riutilizzare la stessa animazioni, quindi abbiamo costruito il nostro primo tree rig e ci siamo assicurati che i nomi congiunti fossero generici perché volevamo utilizzare questi stessi nomi nei rig per gli altri alberi.Sapevamo anche che dovevamo includere articolazioni/ossa primarie, secondarie e terziarie per i tronchi per piegarsi con il vento, le branche per oscillare e le foglie per sembrare che stessero tremando in risposta.Per questo processo, abbiamo dovuto creare un movimento secondario , che è un concetto di animazione in cui qualsiasi azione fa reagire altre parti dell'oggetto a quell'azione e sembra raggiungere il movimento iniziale.

Gli alberi hanno articolazioni primarie, secondarie e terziarie in modo che possiamo avere movimenti credibili dal essere soffiati in giro dal vento.

Una volta creati i nostri arti/ossa, era il momento di creare un'animazione di prova per muoversi intorno a tutte le articolazioni e le ossa in Studio per vedere se si muoveva come volevamo.Per farlo, abbiamo dovuto importare l'albero in Studio attraverso la Impostazione Rig personalizzata nel 3D Importer , quindi spostare/animare la mesh usando l'Editor di animazione.Configuriamo i materiali e le texture dopo questi test, ma puoi vedere il risultato qui sotto.

La stessa gerarchia all'interno di Studio.

Dopo che eravamo stati contenti dei risultati su quell'albero, era tempo di testare la stessa animazione su un albero diverso! Sapevamo già che sarebbe stata la stessa animazione tra le diverse righe per ogni inserisci / scrividi albero, quindi ci siamo assicurati che la nostra animazione fosse abbastanza generale da funzionare tra un grande Redwood e un Beechwood solido!

L'animazione che abbiamo importato sull'albero di Redwood.

Per farlo, abbiamo preso l'albero di Beechwood da quel pacchetto forestale e costruito una Piattaforma di testsimile, usando lo stesso nome esatto per le giunzioni.Questo era così che l'animazione che avevamo precedentemente importato poteva essere applicata anche a questo albero.Poiché tutte le animazioni si basavano su articolazioni rotanti, non importava quanto fosse grande, piccola, alta o ampia l'albero!

L'albero di Beechwood ha la stessa esatta denominazione per le sue articolazioni, solo non la stessa quantità.Questo è perfetto poiché il sistema di animazione applicherà l'animazione solo a quelle giunture specifiche che corrispondono al nome in esso! Per questo motivo, potremmo applicare le stesse animazioni a qualsiasi cosa corrisponda ai nomi delle giunte!

Dopo aver rigato e rivestito l'albero di Beechwood, potremmo quindi importarlo e applicare esattamente la stessa animazione.Questo significava che l'iterazione e la modifica doveva essere eseguita solo su un file e veniva anche salvata sulle prestazioni con meno animazioni durante l'esecuzione dell'esperienza.

Utilizzando l'editor di animazione, potremmo applicare la stessa animazione dell'albero di Redwood al albero di Beechwood!

Una volta che avevamo tutti i tipi di albero che volevamo animare, li abbiamo resi pacchetti così potevamo continuare a modificare e aggiornare mentre giocavamo diverse delle animazioni intorno alla zona principale dell'esperienza.Poiché sapevamo che avevano un costo di performance, li abbiamo usati con parsimonia intorno alla casa dove l'effetto era più prezioso! In futuro, man mano che diventerà più performante, sarai in grado di aggiungere sempre più istanze di mesh con pelle!

Abbiamo usato alberi animati immediatamente intorno alla casa dove il vortice era più forte e l'effetto visivo sarebbe stato il più impattante per i giocatori.

Crea detriti della tempesta

Volevamo che la pioggia apparisse pesante, e che la nebbia e i detriti soffiassero attraverso gli alberi.Per farlo, configuriamo alcune parti invisibili per agire come volumi di particelle con emittenti di particelle figli immediatamente sotto le grandi nuvole tempesta.A causa del limite del conteggio delle particelle in Studio, non potevamo utilizzare un emittente di particelle per l'intero Spazio.Invece abbiamo aggiunto diversi che avevano le stesse dimensioni l'uno dell'altro in un modello di griglia sullo Spaziodella zona giocabile, perché la presenza degli alberi rende i giocatori non in grado di vedere molto lontano.

Abbiamo usato diversi volumi per ottenere sia la quantità di pioggia, che la copertura specifica di pioggia che volevamo.

Le particelle di pioggia hanno sfruttato una nuova proprietà emittente di particelle ParticleEmitter.Squash che ti consente di rendere una particella più lunga o più sparpagliata.È particolarmente utile per la pioggia perché significava che non avevamo bisogno di una grande Strutturadi pioggia, basta allungare quella che era lì.Sappi solo che se aumenti il valore di ParticleEmitter.Squash , potresti dover aumentare anche la proprietà generale ParticleEmitter.Size in modo che non sia troppo magra! Nel complesso, era solo una questione di giocare con i valori fino a quando non abbiamo ottenuto la pioggia abbastanza pesante, ma non così tanto da bloccare la visibilità dell'esperienza!

Un valore Squash di 3 inizia a distendere la texture più a lungo.
>

Un valore Squash di 20 allunga le particelle per molto più tempo, ma abbiamo anche dovuto aumentare anche il valore Dimensione .
>

Per la nebbia, la nebbia e le foglie che soffiavano attraverso, era molto più semplice aggiungere un singolo volume di parti più grande che copriva meno aree perché non avevamo bisogno di una tonnellata di particelle che corrono contemporaneamente.Abbiamo iniziato impostando un volume e ottenendo la frequenza dei particolari dove li volevamo.

Si è concluso con alcuni volumi di particelle quindi non abbiamo avuto particelle che entravano in casa, e perché non sentivamo che avessero bisogno di muoversi attraverso gli alberi come la nebbia.
>

Il volume delle particelle della nebbia era molto più grande poiché le particelle eran grandi, e non avevamo bisogno di essere così precisi con la posizione.
>

Dopo ciò, abbiamo creato le nostre texture di soffiamento delle foglie e di vento e abbiamo impostato i particolari a ruotare/spostarsi a velocità diverse e a iniziare a velocità diverse.Questo ha significato che le particelle di nebbia più grandi interagirebbero in modo più naturale e non sembrerebbero così tanto una Strutturaripetitiva, soprattutto dato le loro dimensioni.

Particella di nebbia
>

Particola foglia
>

Il risultato è stato qualche grande azione tra gli alberi in movimento, la finestra che soffia e il fulmine per creare l'effetto della tempesta che circonda l'occhio centrale della tempesta.

Configura l'occhio della tempesta

L'occhio di pietra fratturato con un nucleo incandescente è destinato a dare ai giocatori il primo indizio che c'è qualcosa di sinistro e arcano che accade alla casa che dovrebbero esplorare ulteriormente.Poiché la nostra scena è buia e l'occhio è molto in alto nel cielo, era importante creare una silhouette di pietra fratturata credibile, ma non era così importante creare dettagli della superficie di pietra credibili perché i giocatori non sarebbero stati in grado di vederli.Sapere cosa è realistico per i tuoi giocatori vedere all'interno dell'illuminazione della tua scena prima di spendere un sacco di tempo in dettagli non necessari può risparmiarti molte risorse nel processo di sviluppo.

Impostare la luce finale nella tua scena in anticipo può risparmiarti un sacco di lavoro inutile.Non saresti in grado di vedere i dettagli della superficie sugli anelli con la luce finale della scena quindi non c'era bisogno di spendere il tempo a metterli lì!

La distanza dal giocatore ha anche significato che potevamo fare affidamento interamente su una mappa normale per i dettagli della superficie dell'occhio in modo che la mesh sia solo una sfera piatta! Abbiamo scolpito i dettagli in una mesh ad alta poligonalità e cotto la sua mappa normale su una sfera poligonale molto più bassa in modo che potessimo ottenere tutti quei bei dettagli senza il costo di performance massiccio.

Alto scolpimento poli
>

Retina a bassa polizia
>

La mesh a bassa poligonalità con le informazioni normali della scultura ad alta poligonalità cucinata in

Per aggiungere una sensazione soprannaturale all'occhio e sottolineare la sua presenza, abbiamo deciso di creare un magma incandescente e neon che si infiltrerebbe attraverso le sue crepe.Mentre non esiste alcun canale emissivo per l'aspetto della superficie, superiamo questo ostacolo creando l'occhio da 2 sfere: una per la superficie rocciosa e una seconda, leggermente più piccola, per la magma incandescente.In Pittore di sostanza, abbiamo creato una texture di colore di base per la sfera esterna con trasparenza nelle aree in cui volevamo che il nucleo interno passasse.In Blender , abbiamo "vertexato" la sfera interna per un modo economico e facile per ottenere qualche variazione di colore su di essa.

Il dipinto del vertice sulla sfera interna.Abbiamo creato un gradiente che era più leggero intorno all'occhio per dare un maggiore senso di profondità e interesse visivo.

Un'altra sfida che abbiamo incontrato durante la creazione dell'occhio è stata imposta dal nostro uso di streaming combinato con la distanza dell'occhio dal Giocatore.Dato il centralismo di questa struttura, volevamo che fosse sempre visibile nonostante la sua distanza ma, senza alcun hack alla sua Mesh, maglia, i giocatori non sono stati in grado di vedere l'occhio a meno che non fossero nel solarium.Siamo stati in grado di forzare la presenza costante dell'occhio nella scena aggiungendo un po' di geometria all'occhio e ai suoi anelli.Questa geometria si trova proprio sotto la superficie del terreno, e questo è sufficiente per ingannare il motore a pensare che la sfera sia più vicina al giocatore di quanto non sia e sempre in streaming.Questo dovrebbe essere fatto abbastanza risparmiando però poiché forzare troppi oggetti grandi a essere trasmessi potrebbe negare i vantaggi dello streaming abilitato e influenzare negativamente le Prestazionedi gioco.

Siamo stati in grado di aggiungere movimento all'occhio e ai suoi anelli grazie allo stesso script che usavamo per ruotare le maglie del cloud.Per un tocco finale, abbiamo deciso di aggiungere un suggerimento alla presenza di un altro mondo oltre le nuvole, ma abbiamo dovuto adottare un approccio creativo per evitare di aggiungere più geometria alla scena e inoltre dover affrontare le barriere menzionate in precedenza abilitate tramite lo streaming.Abbiamo creato una scena che aveva molta profondità a causa della dimensione e della distanza relativi degli oggetti, reso un'immagine di questa scena, quindi usato l'immagine detta come adesivo su una parte posizionata proprio dietro l'occhio della tempesta.Abbiamo usato lo stesso metodo per ruotare questa parte come abbiamo fatto per l'occhio e i suoi anelli.

L'immagine che usavamo per creare un'illusione di un mondo al di là delle nuvole.Quando i giocatori sono molto lontani da qualcosa, un'immagine semplice potrebbe essere sufficiente per creare l'illusione di maggiore profondità e complessità nella tua scena!

Fai espandere il magazzino

Una delle cose più divertenti da produrre sono stati gli spazi corrotti, in cui potevamo sovvertire le aspettative dei giocatori sulla realtà letteralmente cambiandola intorno a loro.Ad esempio, nel puzzle del padre volevamo emulare un momento simile a un incubo in cui non importa quanto velocemente Eseguire, la stanza sembra continuare ad allungarsi.Abbiamo deciso di creare un magazzino espandibile che scappasse dai giocatori mentre cercavano gli ingredienti per trasformare la stanza nel suo stato normale.

Abbiamo configurato questo con un semplice movimento delle pareti e un layout intelligente delle nostre stanze che apparirebbero su entrambi i lati del magazzino.Nello stato normale della stanza, il magazzino era un semplice corridoio, ma nello Spaziocorrotto era in realtà molto più lungo con diverse ali e un muro falso!

Lo stato corrotto del magazzino di cucina.
>

Il muro falso che si allontana dai giocatori.
>

Il muro falso era un gruppo di modelli che avremmo riportato al momento in cui i giocatori entrassero in un volume di trigger, che era una parte trasparente in precedenza nel magazzino in cui passeranno.Quel trigger è stato utilizzato anche in uno script simile a quelli utilizzati su tutte le nostre porte, che ha chiamato il TweenService per passare da un obiettivo all'altro.Abbiamo usato i volumi parziali per dire all'operazione di tweening dove le posizioni di inizio e fine fossero per il muro.

Il volume delle parti attiva una falsa parete dietro di essa per spostarsi al suo punto finale.Viene reso visibile in questa immagine con una tinta gialla.
Target_Closed era una parte generica dell'obiettivo che abbiamo usato su tutte le nostre porte per dove dovrebbero Rotare.Qui è stato riutilizzato per dire alla parete del corridoio dove Vai.

Poiché TweenService è un sistema così generale, tutti i nostri modelli di dati del muro hanno dovuto contenere gli stessi componenti.Ad esempio, uno script generale "Door_Script" riproduce un suono definito da un "valore" sotto il modello "Grow_Wall".Quello stesso script, con alcune modifiche nel seguente esempio di codice, ha anche attivato l'audio per la movimentazione del magazzino.Questo ha aggiunto molto al movimento!


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, --Tempo/Velocità di Door Tween
Enum.EasingStyle.Quart, --Stile di facilitazione
Enum.EasingDirection.InOut, --Direzione di facilitazione
0, --Ripeti il conteggio
false, --Inverti vero
0 --Ritardo
)
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
--modello ["Porta"]:Play()
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("tocco")
playersNear[player] = 1
if doorState == DoorState.Closed then
StartOpening()
end
end
end
end

Una volta che avevamo il muro falso che si muoveva verso il retro della stanza, avevamo bisogno del resto del contenuto a muoversi con esso.Per farlo, avevamo bisogno che tutti gli oggetti smessi sul magazzino fossero saldati al muro mentre si muoveva.Usando Contrazioni di saldatura, siamo stati in grado di saldare rapidamente tutti gli oggetti al muro del magazzino per muoversi come un singolo oggetto.Fare ciò significava che avevamo l'opzione di rimuovere questi oggetti in modo che i giocatori potessero scontrarsi con essi e farli cadere!

Crea la casa sull'albero corrotta

Studio è un motore fisicamente basato fantastico che puoi usare per creare tutto, da una porta oscillante a una Piattaformarotante.Con la nostra demo, volevamo usare la fisica per creare un senso di realismo in un insieme di ambienti altrimenti irrealistici.Usando solo alcune restrizioni , puoi creare alcuni percorsi di ostacoli divertenti e impegnativi all'interno delle tue esperienze!

Restrizioni sono un gruppo di motori fisicamente basati che allineano gli oggetti e vincolano i comportamenti.Ad esempio, puoi usare una restrizione del rodillo per connetterti agli oggetti per mantenerli a una distanza fissa l'uno dall'altro, o la restrizione della corda per avere una lampada appesa alla fine della linea.Per il puzzle del figlio in cui i giocatori vengono trasportati nello stato corrotto dello studio, volevamo letteralmente ribaltare il mondo sul suo lato.Farlo sarebbe sottomettere le aspettative dei giocatori sulla realtà e sulle regole lì, mentre si continua ad usare il sistema fisico come era previsto!

Il puzzle del figlio è iniziato con i giocatori nella stessa stanza, ma tutto era laterale.

Una volta che i giocatori sono scesi nell'area principale del puzzle, sono stati accolti con una vista familiare su Roblox: un percorso ostico.Questo particolare percorso di ostacoli consisteva in diverse piattaforme rotanti e pareti rotanti, oltre a "aree sicure" che hanno progredito la storia.Ci concentreremo sugli elementi rotanti/spinenti.

L'apparenza che distrugge la mente nascondeva il fatto che il gameplay qui era molto semplice.

Perché abbiamo usato qui le restrizioni? Perché TweenService o altri metodi non avrebbero spostato il giocatore mentre stava su di essi.Senza che l'oggetto si muova il Giocatore, qualcuno potrebbe saltare su una piattaforma e si svilupperà da sotto di loro.Invece, volevamo che i giocatori navigassero attraverso una piattaforma rotante mentre cercavano di fare il loro salto sulla successiva.A causa di questo approccio, i giocatori si sono sentiti radicati dove stavano mentre prendevano una decisione su come procedere attraverso il corso, e non avevamo bisogno di fare nulla di speciale per garantire che si muovessero con una superficie rotante!

Potresti guardare i tuoi amici girare mentre tenti di navigare anche sul percorso dell'ostacolo.

Per farlo, abbiamo dovuto prima utilizzare le risorse del nostro kit attuale e aggiungere qualsiasi nuovo contenuto per un effetto visivo.Abbiamo fatto alcune pareti e piattaforme incomplete con buchi al loro interno per raccontare la storia della nonna che costruiva la casetta sull'albero.Poiché non volevamo creare un mucchio di piattaforme uniche, abbiamo creato 4 pezzi di base e pezzi di balaustra separatamente.Ciò ci ha permesso di mescolare e abbinare singoli pezzi di base e ringhiere per avere molta varietà.

Sapevamo che poiché stavamo usando delle restrizioni, non saremmo stati in grado di ancorare queste maglie perché non si sarebbero mosse nemmeno con la presenza di una restrizione/motore che le guidava.La restrizione necessaria per essere un figlio di qualcosa che era ancorato in modo che la piattaforma non cadesse semplicemente dal Mondo.Abbiamo risolto questo attraverso una parte che abbiamo chiamato Motor_Anchor che aveva una restrizione a serratura per guidare il movimento generale della Piattaforma.Dopo di ciò, avevamo bisogno delle due maglie per muoversi come una sola, quindi abbiamo creato una parte che abbiamo chiamato Motor_Turn , quindi abbiamo saldato le due maglie ad essa.In questo modo la restrizione sarebbe in grado di lavorare su una singola parte, a differenza di più serrature che lavorano con più parti.

Era ora di impostare il comportamento effettivo della restrizione a serratura stessa e aggiungere gli allegati che agirebbero come orientamento della parte e della restrizione insieme.Abbiamo posizionato l'accessorio rotante sul Motor_Turn, a cui le parti del percorso sono state saldate, e un altro accessorio per il comportamento dell'ancoraggio sul Motor_Anchor stesso, accanto alla restrizione a serratura.Poiché questo doveva ruotare da Proprio, a differenza di essere influenzato dal giocatore (come una Cerniera), abbiamo impostato il HingeConstraint.ActuatorType su Motore , trattando la restrizione come un motore a movimento automatico.

Per mantenere le piattaforme in rotazione a una velocità costante, configuriamo quindi le proprietà HingeConstraint.AngularVelocity, HingeConstraint.MotorMaxAcceleration e HingeConstraint.MotorMaxTorque a valori che consentirebbero il movimento e impedirebbero l'interruzione se un giocatore saltasse su di essa.

L'allegato 0 era essenzialmente l'ancoraggio per la cerniera e l'allegato 1 rappresentava la cerniera stessa.Avevamo l'articolazione in rotazione costante, ma puoi anche usare una restrizione di articolazione per le porte.

Ora avevamo bisogno di fare le pareti rotanti.I muri hanno bisogno di ruotare sul loro centro apparente e sapevamo che volevamo che fossero in grado di gestire qualsiasi orientamento rispetto al resto del Livello.Come le piattaforme, abbiamo costruito queste in modo che tutti i muri fossero non ancorati e saldati al Motor_Turn.

Volevamo riutilizzare quanto più delle mesh della casa sull'albero effettive per risparmiare sulle Prestazione, quindi abbiamo seguito un percorso simile alle piattaforme.Sono stati creati diversi tipi di pareti che potrebbero aderire insieme in diverse combinazioni per qualche variazione.

Abbiamo utilizzato Texture oggetti sui SurfaceAppearance oggetti per aggiungere qualche variazione ai nostri materiali di base.Texture, simili alle Decal, ti consentono di posizionare un'immagine su un piano di una Mesh, maglia.Questo può essere utile se vuoi aggiungere sporcizia a un muro di mattoni o rendere il legno vecchio mentre usi lo stesso materiale di legno di base. Texture gli oggetti hanno un comportamento leggermente diverso da quello di Decal oggetti in cui puoi riempire e spostare l'immagine come vuoi, il che è molto utile se vuoi essere in grado di ridimensionare la tua texture di sovrapposizione e non ti dispiace che si ripeta!

Puoi vedere sia il comportamento simile che il set up per la Vincoloa serratura, e anche come abbiamo usato gli oggetti Texture .

Una volta testate alcune piattaforme e pareti rotanti, abbiamo fatto diverse varianti e giocato con il loro posizionamento per assicurarci che il percorso ostico fosse impegnativo, sorprendente e anche chiaro dove il giocatore avrebbe dovuto Vai! Ci è voluto un po' di tuning sia ai loro valori che alle loro posizioni per farli funzionare bene.Abbiamo avuto diversi punti in cui le piattaforme e i muri si stavano colpendo l'un l'altro o l'ambiente circostante, ma con qualche movimento in giro e test frequenti, siamo stati in grado di atterrare sulle impostazioni che abbiamo nella demo!

Se non sei sicuro di ciò che i tuoi oggetti fisici stanno colpendo, puoi attivare fedeltà della collisione dal widget Opzioni di visualizzazione nell'angolo in alto a destra della finestra3D.

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.

Quando la visualizzazione della collisione è disabilitata, puoi vedere la rappresentazione normale della geometria che viene visualizzata in gioco.
>

Quando la visualizzazione della collisione è abilitata, puoi vedere che le foglie dell'albero non hanno collisioni, quindi non interferiranno con le piattaforme o le pareti in rotazione.
>

Come puoi vedere qui sotto, le fessure dell'ingresso/finestra sono visibili, ma i dettagli più piccoli come il sottopannello non lo sono.Questo perché la proprietà CollisionFidelity per i muri è stata impostata su Scatola .Non avevamo bisogno della precisione per questi pannelli, quindi per risparmiare sul costo delle prestazioni, questo era abbastanza dettagliato per i giocatori da saltare su.Con le piattaforme e i muri rotanti completati, avevamo solo bisogno di aggiungere risorse di dettaglio come scatole e lampade, quindi era pronto per essere giocato!