Kembangkan dunia bergerak

*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.

Membuat gerakan di setiap lingkungan dalam pengalaman membantu menjadikannya langsung terasa lebih imersif dan realistis ke dunia kita, apakah itu berasal dari gerakan pohon ambient, pintu reaktif dari interaksi pemain, atau bahkan kotak yang bergerak saat mereka bertabrakan dengan mereka.Studio memiliki banyak metode unik untuk membuat gerakan untuk membantu dunia merasa lebih hidup, termasuk sistem fisika, TweenService , dan animasi, dan menganalisis kebutuhan khusus pengalaman Anda dapat membantu Anda menentukan yang mana untuk digunakan.Di bagian ini, kami akan menunjukkan bagaimana kami menentukan jenis gerakan yang ingin kami buat di Studio, dan alat apa yang kami gunakan untuk mencapai tujuan yang berbeda ini.

Buat badai itu

Badai melalui banyak iterasi sebelum kami menetap pada apa yang hidup di The Mystery of Duvall Drive.Pada awalnya, kami berpikir tentang badai sebagai pilar obsidian raksasa, dan dalam iterasi selanjutnya kami menganggapnya sebagai portal raksasa ke ruang korup.Setelah bereksperimen dengan banyak badai yang berbeda dengan penampilan dan perasaan unik bagi mereka, kami menetap pada badai dengan "mata" pusat yang lebih kecil karena:

  • Badai harus memberi pemain rasa pengaruh dari peristiwa ini terhadap dunia , termasuk pohon yang terbang dan sampah terbang di sekitar.
  • Vorteks berputar dari awan itu sendiri seharusnya memberi pemain pandangan ke portal tengah tanpa mengungkapkan semuanya .Ini akan mendorong pemain untuk menyelidiki lebih dekat untuk melihat apa yang terjadi.
  • Titik cahaya yang lebih ketat akan memungkinkan kita untuk fokus pada komposisi rumah , yang merupakan karakter utama dan di mana sebagian besar permainan berlokasi.

Untuk membuat badai terasa dinamis, agresif, dan selalu berubah dalam lingkungannya, kami menggunakan sistem dan fitur berikut:

  1. TweenService - Untuk pergerakan awan.
  2. Perubahan pencahayaan - Untuk membuat awan menjadi petir awan.
  3. Balok - Untuk "pencahayaan volumetrik" dan kilat petir.
  4. Pemancar Partikel - Untuk sampah yang terbang ke portal dan terbang di sekitar karena angin yang bertiup.
  5. Animasi - Untuk pohon yang terbang di angin.

Tambahkan awan dengan tekstur

Sementara awan dinamis bagus untuk awan realistik normal dan bertingkat tinggi, kami membutuhkan sesuatu yang terasa dramatis dan yang bisa kami arahkan dan kustomisasi lebih berat.Untuk melakukan ini, kami menerapkan penampilan permukaan objek dengan transparansi semi ke serangkaian meshes awan yang berat dan bertumpuk untuk memalsukan penutupan awan.Mengapa kami menumpuk dan melapisi mereka begitu berat? Karena ketika setiap mesh awan bergerak dengan kecepatan berbeda, mereka bertabrakan dan membuat bentuk awan yang masuk dan keluar satu sama lain.Proses ini membuat awan terasa sedikit lebih dinamis dan alami, meskipun hanya berputar disk.Penting juga bahwa awan menjadi semi-transparan , karena kami ingin pemain dapat melihat melalui mereka untuk melihat sesuatu yang terang di tengah sebelum tiba di rumah!

Satu mesh awan tunggal.
>

Jaringan awan berlapis tanpa teksturnya!
>

Karena setiap jaringan awan perlu menjadi besar untuk sepenuhnya mengelilingi rumah dan mengkomunikasikan seberapa besar badai itu, kami tahu kami perlu mengujungkan tekstur yang ingin kami gunakan pada jaringan awan individu sehingga akan diulang berat di seluruh permukaan jaringan.Kami menguji bahan yang kami buat untuk cloud pada bagian sederhana ini, lalu menerapkannya ke vortex!

Tidak seperti pemancar partikel atau balok, meshes memungkinkan kami untuk dapat memantulkan cahaya dari setiap meshes, yang penting ketika kami ingin menerapkan petir antara awan.Kami juga memodelkan di putaran sehingga pencahayaan melenting dari itu akan terlihat seperti memiliki kedalaman! Ini penting terutama dalam situasi di mana permintaan kinerja pengalaman menurunkan tingkat kualitas penampilan permukaan kami.

Setelah kami mulai menambahkan pencahayaan ke dalamnya, kami perlu menambahkan rincian ke meshes untuk membuatnya lebih bereaksi terhadap pencahayaan!

Putar meshes awan

Setelah kami puas dengan penampilan visual keseluruhan awan, kami perlu membuatnya bergerak! Kami memiliki bentuk umum setiap lapisan awan di tempat, tetapi diperlukan beberapa percobaan dan kesalahan untuk memastikan efek berputar terlihat bagus dalam praktik.Kami awalnya mencoba menggunakan kondisi untuk memperkenalkan kecepatan yang akan menggerakkan awan secara fisik.Ini lebih sulit daripada yang kami inginkan untuk diulang nanti, dan pemain tidak akan pernah berinteraksi dengannya, jadi kami tidak membutuhkannya untuk menjadi seakurat mungkin dalam gerakannya.

Kami menginginkan metode yang mudah digunakan untuk memutar instansi yang terlalu jauh untuk berinteraksi, seperti awan, atau terlalu kecil atau dekoratif untuk menjadi penting untuk gameplay/fisika, seperti perabotan dalam ruangan seperti lampu kecil.Kami memutuskan untuk menggunakan LocalScript untuk mengurangi bandwidth klien-server, memungkinkan gerakan yang lebih halus, dan setiap mesh awan dapat memiliki tingkat rotasi dan penundaan yang berbeda.Untuk membuatnya lebih umum, kami juga membuatnya mungkin untuk menentukan sumbu rotasi.Dimungkinkan untuk menggunakan 3 atribut, tetapi untuk kasus kami kami menggunakan 3 nilai: Axis , Delay , dan Speed .

Seperti dalam banyak kasus di demo, kami menggunakan tag LocalSpaceRotation sehingga kami dapat mengelola instans yang terpengaruh di Studio menggunakan plugin tagging instansi.Kami hanya menggunakan satu LocalScript yang menangani semua instansi yang ditagih menggunakan CollectionService sehingga kami tidak memiliki banyak skrip untuk dipertahankan selama proses pengembangan.

Dalam demo kami, bagian-bagian dunia diklon dari ServerStorage ke ruang kerja sesuai kebutuhan, jadi kami perlu menangani kasus di mana objek yang ditagih dibuat dan dihancurkan.Dengan LocalScripts , kami juga harus sadar akan streaming, di mana meshes dan nilai anak mereka dapat diputar masuk dan keluar.Kami memproses awalnya menempatkan objek di fungsi Init() dan terhubung ke CollectionService.GetInstanceAddedSignal dan CollectionService.GetInstanceRemovedSignal untuk objek ber标签 untuk menangani objek baru yang dibuat atau dihapus.Fungsi yang sama SetupObj digunakan untuk menginisialisasi objek baru di Init() dan di 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 adalah peta yang memiliki informasi untuk semua objek yang relevan, seperti kecepatan rotasi dan sumbu mereka.Perhatikan bahwa kami tidak memanggil SetupObj dari CollectionService.GetInstanceAddedSignal segera, tetapi kami menambahkan objek ke objInfoQueue .Dengan objek streaming dan kloning di server, ketika CollectionService.GetInstanceAddedSignal dipanggil, kami mungkin belum memiliki Axis , Delay , dan Speed nilai, jadi kami menambahkan objek ke dalam antrian, dan memanggil SetupObj pada frame berikutnya dari fungsi Update sampai nilai-nilai tersebut ada dan kami dapat membacanya ke dalam struktur "info" per objek.

Kami memutar instansi di fungsi Update yang terhubung ke detak jantung.Kami mendapatkan transformasi orang tua (parentTransform), mengumpulkan sudut rotasi baru ( curObjInfo.curAngle ) berdasarkan kecepatan rotasi objek ini, menghitung transformasi lokal ( rotatedLocalCFrame) , dan akhirnya menetapkannya ke CFrame .Perhatikan bahwa baik orang tua dan objek bisa menjadi Model atau MeshPart , jadi kami harus memeriksa IsA("Model") dan menggunakan entah PrimaryPart.CFrame atau CFrame .


local parentTransform
if parentObj:IsA("Model") then
if not parentObj.PrimaryPart then
-- bagian utama mungkin belum dapat diputar
continue -- tunggu bagian utama untuk direplikasi
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

Kami memeriksa untuk valid Model.PrimaryPart untuk ditetapkan untuk menangani streaming.Jika Pembaruan dipanggil pada objek kami saat Model.PrimaryPart (yang dapat menunjuk ke mesh anak) belum diputar, kami hanya akan melewati update.Sistem saat ini adalah iterasi kedua dari rotasi objek, dan sistem sebelumnya bekerja berbeda: nilainya berbeda 12 kali! Untuk menyimpan data yang sama, kami mengkonversinya di skrip kami, seperti "12 * obj.Speed.Value".

Desain serangan petir

Karena Studio tidak menawarkan generator petir keluar dari kotak, dan sistem partikel memiliki beberapa batasan yang tidak akan berfungsi untuk serangan petir pahlawan, kami harus kreatif dengan solusi untuk serangan petir pahlawan.Kami memutuskan pada dua sistem utama untuk membuat petir: balok bertekstur untuk serangan petir pahlawan yang berasal dari mata badai adalah balok bertekstur yang mengungkapkan dan sinkron dengan efek audio dan proses pengeditan, dan efek partikel sederhana untuk kilat awan ke awan jarak jauh.

Balok tekstur

Kami biasanya menggunakan sequencer atau alat jadwal untuk menggerakkan waktu serangan kilat pencahayaan seperti ini, tetapi karena Studio belum menawarkan fungsi ini, kami memutuskan untuk menulis skrip yang akan mengontrol waktu kilat pencahayaan.Pemrograman efek ini cukup sederhana, tetapi mencapai tujuan penting berikut:

  1. Elemen dari serangan kilat, seperti tekstur, kecerahan, dan penundaan, diacak dengan setiap serangan.
  2. Perubahan audio dan pos FX sinkron dengan serangan FX.
  3. Pemain yang berada di dalam atau di area korup tidak akan dapat melihat atau mendengarnya.

Kami memiliki sisi server Script yang menghitung berbagai parameter dan waktu, mengirimkannya ke semua klien, dan menunggu jumlah waktu acak:


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

Di dalam CreateFXData , kami mengisi struktur informasi, sehingga semua klien mendapatkan parameter yang sama.

Di sisi klien ( LightningVFXClient ), kami memeriksa apakah klien ini harus menjalankan FX:


local function LightningFunc(info)
-- tidak ada FX saat berada di dalam
if inVolumesCheckerFunc:Invoke() then
return
end
-- tidak ada FX saat tidak berada di dunia "normal"
if not gameStateInfoFunc:Invoke("IsInNormal") then
return
end

Selain itu, kami menjalankan urutan untuk mengatur teksur, posisi, dan kecerahan, menjalankan remaja, dan menggunakan task.wait(number).Para meteran acak berasal dari struktur informasi yang kami terima dari server, dan beberapa angka tetap.


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

Untuk memeriksa apakah pemain berada di dalam, kami menggunakan fungsi bantuan inVolumesCheckerFunc , yang melampaui volume yang ditempatkan sebelumnya yang mendekati area dalam, dan memeriksa apakah posisi pemain berada di dalam salah satunya (PointInABox).Kami bisa menggunakan deteksi berbasis sentuhan, tetapi kami menemukan bahwa ketika seorang pemain mengambil tempat duduk di dalam volume, mereka tidak lagi "menyentuh" volume.Menguji titik di beberapa kotak lebih sederhana, dan kami melakukannya hanya ketika pemain bergerak cukup jauh dari posisi yang sebelumnya diuji.

Untuk memeriksa apakah pemain berada di area korup, kami memanggil fungsi pembantu gameStateInfoFunc, yang memeriksa status permainan saat ini.Untuk memutar suara acak dari folder, kami juga menggunakan fungsi helper PlayOneShot.Untuk kilat itu sendiri, ini sangat mudah dibuat di Photoshop; kami menarik garis bergerigi, lalu menambahkan efek lapisan "Cahaya Luar".

Manfaatkan sistem pemancar partikel

Serangan petir pahlawan didukung oleh sistem partikel yang menyarankan petir jauh dengan menciptakan kesan lapisan awan di latar belakang menangkap cahaya dari serangan jarak jauh, atau pencahayaan awan ke awan.Kami mencapai efek ini melalui sistem partikel yang sangat sederhana yang menyinari billboard awan di periferan awan badai utama.Sistem memancarkan partikel awan secara berkala dengan kurva transparansi acak:

Membuat pohon terbang di angin

Setelah kami memiliki awan dan petir yang bekerja dengan cara yang kami inginkan, kami kemudian perlu menambahkan dua komponen utama lain dari badai: angin dan hujan! Elemen ini menghadirkan beberapa tantangan, termasuk perlu bekerja dalam batasan saat ini dari sistem fisika dan efek khusus Studio kami.Sebagai contoh, membuat pohon bergerak dengan angin aktual tidak mungkin dalam mesin saat ini, jadi kami menggunakan efek pemancar partikel dan animasi karakter khusus untuk pohon.

Kami tahu untuk benar-benar menjual efek angin dan hujan, kami membutuhkan pohon sendiri untuk bergerak.Ada beberapa cara Anda dapat melakukan ini di dalam mesin, termasuk memindahkan bagian menggunakan plugin yang tersedia secara publik, menggunakan TweenService , atau memanimasi model langsung.Untuk tujuan kami, animasi memberi kami kemampuan untuk mengontrol gerakan yang kami inginkan dari pohon kami, dan memungkinkan kami untuk menggunakan animasi tunggal yang bisa kami bagikan di antara semua pohon dalam pengalaman.

Kami mulai dengan mengulit beberapa pohon dari Endorse Model Pack - Forest Assets.Karena pohon-pohon ini sudah ada, dan pengalaman kami terjadi di Pasifik Utara, itu menyelamatkan kami beberapa waktu lebih awal dari harus membuat setiap model pohon.

Paket Hutan berisi beberapa jenis pohon, yang dapat menghemat waktu dalam pengalaman Anda sendiri.

Setelah kami memilih pohon kami, kami tahu kami perlu mengulitnya. Memotong mesh adalah tindakan menambahkan persambungan (atau tulang) ke mesh di aplikasi pemodelan 3D lain, seperti Blender atau Maya, kemudian menerapkan pengaruh ke persambungan/tulang itu untuk memindahkan mesh.Ini paling umum digunakan di karakter humanoid , tetapi dengan karakter khusus , Anda dapat melepaskan hampir semua hal.

Kami tahu kami ingin menghemat waktu dan menggunakan kembali animasi yang sama, jadi kami membangun rig pohon pertama kami dan memastikan nama-nama bersama adalah umum karena kami ingin menggunakan nama-nama yang sama di rig untuk pohon lainnya.Kami juga tahu kami perlu menyertakan joint/tulang utama, sekunder, dan tertiary untuk batang untuk melengkung dengan angin, cabang untuk ayunan, dan daun untuk tampak seperti mereka bergetar dalam respons.Untuk proses ini, kami perlu membuat gerakan sekunder , yang merupakan konsep animasi di mana setiap tindakan menyebabkan bagian lain dari objek bereaksi terhadap tindakan itu dan tampaknya mengejar gerakan awal.

Pohon memiliki persambungan primer, sekunder, dan tersier sehingga kita bisa memiliki gerakan yang dapat dipercaya dari terhembus oleh angin.

Setelah kami membuat persambungan/tulang kami, saatnya untuk membuat animasi tes untuk bergerak di sekitar semua persambungan dan tulang di Studio untuk melihat apakah itu bergerak seperti yang kami inginkan.Untuk melakukan ini, kami harus menge导入 pohon ke Studio melalui pengaturan Rig Kustom di Importer 3D , lalu pindahkan/animasikan mesh menggunakan Editor Animasi.Kami mengatur bahan dan tekstur setelah tes ini, tetapi Anda dapat melihat hasilnya di bawah ini.

Hierarki yang sama di dalam Studio.

Setelah kami puas dengan hasil di pohon itu, saatnya untuk menguji animasi yang sama di pohon yang berbeda! Kami sudah tahu itu akan menjadi animasi yang sama antara berbagai rig untuk setiap ketikpohon, jadi kami hanya memastikan animasi kami terlihat seperti cukup umum untuk bekerja di antara Redwood tinggi dan Beechwood kuat!

Animasi yang kami impor pada pohon Redwood.

Untuk melakukan ini, kami mengambil pohon Beechwood dari Forest Pack itu dan membangun rig serupa, menggunakan nama yang sama persis untuk sambungan.Ini agar animasi yang telah kami impor sebelumnya dapat diterapkan ke pohon ini juga.Karena animasi semuanya didasarkan pada sendi berputar, tidak masalah seberapa besar, kecil, tinggi atau lebar pohon itu!

Pohon Beechwood memiliki nama yang sama persis untuk persambungannya, hanya tidak sama jumlahnya.Ini baik-baik saja karena sistem animasi hanya akan menerapkan animasi kepada joint khusus yang sesuai dengan nama di dalamnya! Untuk alasan ini, kami bisa menerapkan animasi yang sama ke apa pun yang sesuai dengan nama joint!

Setelah kami merig dan kulit pohon Beechwood, kami kemudian bisa mengimpor dan menerapkan animasi yang persis sama.Ini berarti mengulang dan mengedit hanya perlu dilakukan pada satu file, dan juga disimpan pada kinerja dengan lebih sedikit animasi saat menjalankan pengalaman.

Menggunakan Editor Animasi, kita bisa menerapkan animasi pohon Redwood yang sama ke pohon Beechwood!

Setelah kami memiliki semua jenis pohon yang ingin kami animasikan, kami membuat masing-masing menjadi paket sehingga kami dapat terus mengedit dan memperbarui saat memainkan beberapa animasi di sekitar area utama pengalaman.Karena kami tahu mereka memiliki biaya kinerja, kami menggunakannya secara hemat di sekitar rumah di mana efeknya paling berharga! Di masa depan saat ini menjadi lebih produktif, Anda akan dapat menambahkan lebih banyak dan lebih banyak instansi mesh dilapisi!

Kami menggunakan pohon beranimasi segera di sekitar rumah di mana vorteks paling kuat dan efek visual akan paling berdampak bagi pemain.

Buat sampah badai

Kami ingin hujan tampak berat, dan untuk kabut dan sampah untuk meledak melalui pohon.Untuk melakukan ini, kami menyiapkan beberapa bagian tak terlihat untuk bertindak sebagai volume partikel dengan emitor anak partikel segera di bawah awan badai besar.Karena batas jumlah partikel di Studio, kami tidak bisa menggunakan satu emitor partikel untuk seluruh ruang.Sebagai gantinya, kami menambahkan beberapa yang memiliki ukuran yang sama dengan satu sama lain dalam pola grid di atas ruang permainan, karena kehadiran pohon berarti pemain tidak akan dapat melihat sangat jauh.

Kami menggunakan beberapa volume untuk mendapatkan jumlah hujan, dan penutupan hujan khusus yang kami inginkan.

Partikel hujan memanfaatkan properti emitor partikel baru ParticleEmitter.Squash yang memungkinkan Anda untuk membuat partikel lebih lama, atau menyebar.Sangat berguna untuk hujan karena berarti kita tidak membutuhkan teksur hujan besar, hanya meregangkan yang ada di sana.Hanya tahu bahwa jika Anda meningkatkan nilai ParticleEmitter.Squash , Anda mungkin perlu meningkatkan properti keseluruhan ParticleEmitter.Size juga agar tidak terlalu kurus! Secara keseluruhan, itu hanya masalah bermain-main dengan nilai sampai kami mendapatkan hujan yang cukup berat, tetapi tidak terlalu banyak yang memblokir visibilitas pengalaman!

Nilai Squash 3 mulai memperpanjang tekstur lebih lama.
>

Nilai Squash 20 memperpanjang partikel lebih lama, tetapi kami juga perlu meningkatkan nilai Ukuran juga.

Untuk kabut, debu, dan daun yang terbang melalui, jauh lebih mudah untuk menambahkan satu volume bagian yang lebih besar yang mencakup lebih sedikit area karena kami tidak membutuhkan banyak partikel yang berjalan pada satu waktu.Kami mulai dengan mengatur volume dan mendapat frekuensi partikel di mana mereka diinginkan.

Akhirnya ada beberapa volume bagian partikel sehingga kami tidak memiliki partikel yang masuk ke rumah, dan karena kami tidak merasa perlu bergerak melalui pohon seperti kabut.
>

Volume bagian partikel kabut jauh lebih besar karena partikelnya besar, dan kami tidak perlu menjadi begitu akurat dengan lokasi.
>

Setelah itu, kami membuat teks daun dan tekstur angin kami, dan mengatur partikel untuk semua berputar/bergerak dengan kecepatan berbeda dan mulai dengan kecepatan berbeda.Ini berarti bahwa partikel kabut yang lebih besar akan berinteraksi lebih alami dan tidak terlihat begitu banyak seperti tekstur yang diulang, terutama mengingat ukurannya.

Partikel kabut
>

Partikel daun
>

Hasilnya adalah beberapa tindakan hebat antara pohon bergerak, jendela meniup, dan petir untuk menciptakan efek badai yang mengelilingi mata pusat badai.

Siapkan mata badai

Mata batu retak dengan inti bercahaya dimaksudkan untuk memberi pemain petunjuk pertama bahwa ada sesuatu yang jahat dan misterius terjadi di rumah yang harus mereka jelajahi lebih lanjut.Karena adegan kami gelap dan mata berada jauh di langit, penting untuk membuat siluet batu retak yang dapat dipercaya, tetapi tidak penting untuk membuat detail permukaan batu yang dapat dipercaya karena pemain tidak akan dapat melihatnya.Mengetahui apa yang realistis bagi pemain Anda untuk melihat pencahayaan adegan Anda sebelum menghabiskan banyak waktu untuk rincian yang tidak perlu dapat menghemat banyak sumber daya dalam proses pengembangan.

Mengatur pencahayaan akhir di adegan Anda lebih awal dapat menghemat banyak pekerjaan yang tidak perlu.Anda tidak akan dapat melihat rincian permukaan pada cincin dengan pencahayaan terakhir adegan kami sehingga tidak perlu menghabiskan waktu untuk menempatkannya di sana!

Jarak dari pemain juga berarti bahwa kami dapat sepenuhnya bergantung pada peta normal untuk rincian permukaan mata sehingga mesh hanya merupakan bola polos! Kami memahat rincian ke dalam poli mesh tinggi dan memanggang peta normalnya ke poli sphere yang jauh lebih rendah sehingga kami dapat mendapatkan semua rincian cantik itu tanpa biaya kinerja besar.

Patung poli tinggi
>

Jaring pol rendah
>

Jaring poly rendah dengan informasi normal dari high poly sculpt yang dibakar di

Untuk menambahkan perasaan supernatural ke mata dan untuk menekankan kehadirannya, kami memutuskan untuk membuat magma bercahaya dan neon yang akan menembus celahnya.Meskipun tidak ada saluran emisif untuk penampilan permukaan, kami mengatasi hambatan ini dengan membuat mata keluar dari 2 bola: satu untuk permukaan batu di luar dan yang kedua, sedikit lebih kecil untuk magma bercahaya.Di Pelukis Substansi, kami membuat tekstur warna dasar untuk bidang luar dengan transparansi di area di mana kami ingin inti internal masuk.Di Blender , kami "vertex dilukis" bola dalam untuk cara yang murah dan mudah untuk mendapatkan beberapa variasi warna di atasnya.

Lukisan vertex pada bola dalam.Kami membuat gradien yang paling ringan di sekitar mata untuk memberikan rasa kedalaman dan minat visual yang lebih besar.

Tantangan lain yang kami hadapi saat membuat mata adalah diberlakukan oleh penggunaan streaming bersama dengan jarak mata dari pemain.Mengingat sentralitas struktur ini, kami ingin agar selalu terlihat meskipun jaraknya tetapi, tanpa peretasan apa pun ke mesh-nya, pemain tidak dapat melihat mata kecuali mereka berada di solarium.Kami dapat memaksa kehadiran konstan mata di adegan dengan menambahkan beberapa geometri ke mata dan cincinnya.Geometri ini berada tepat di bawah permukaan medan, dan ini cukup untuk menipu mesin agar berpikir bahwa bola lebih dekat ke pemain daripada sebelumnya dan selalu menyimpannya.Ini seharusnya dilakukan dengan cukup hemat meskipun karena memaksa terlalu banyak objek besar untuk disiarkan bisa menghilangkan manfaat streaming yang diaktifkan dan secara negatif mempengaruhi pelaksanaanpermainan.

Kami dapat menambahkan gerakan ke mata dan cincinnya berkat skrip yang sama yang kami gunakan untuk memutar meshes awan.Untuk sentuhan terakhir, kami memutuskan untuk menambahkan petunjuk kehadiran dunia lain di luar awan, tetapi kami harus mengambil pendekatan kreatif untuk menghindari menambahkan lebih banyak geometri ke adegan dan juga harus berurusan dengan hambatan yang disebutkan sebelumnya yang dihadapi oleh streaming diaktifkan.Kami membuat adegan yang memiliki banyak kedalaman karena ukuran dan jarak objek relatif, menampilkan gambar adegan ini, lalu menggunakan gambar itu sebagai decal dekal di bagian yang ditempatkan tepat di belakang mata badai.Kami menggunakan metode yang sama untuk memutar bagian ini seperti yang kami gunakan untuk mata dan cincinya.

Gambar yang kami gunakan untuk membuat ilusi tentang dunia di luar awan.Ketika pemain jauh dari sesuatu, gambar sederhana mungkin cukup untuk membuat ilusi lebih banyak kedalaman dan kompleksitas dalam adegan Anda!

Buat lemari ekspansi

Salah satu hal paling menyenangkan untuk diproduksi adalah ruang-ruang korup, di mana kami bisa menggoyahkan harapan pemain tentang kenyataan dengan secara harfiah mengubahnya di sekitar mereka.Sebagai contoh, dalam teka-teki ayah kami ingin meniru momen yang mirip dengan mimpi buruk di mana tidak peduli seberapa cepat Anda berlari, ruangan terasa seperti terus memanjang.Kami memutuskan untuk membuat pantry yang berkembang yang akan melarikan diri dari pemain saat mereka mencari bahan untuk mengubah kamar kembali ke keadaan normalnya.

Kami mengatur ini dengan gerakan sederhana dari dinding, dan desain pintar dari kamar kami yang akan muncul di kedua sisi lemari.Dalam keadaan normal ruangan, pantry adalah koridor sederhana, tetapi di ruang korup, sebenarnya lebih lama dengan beberapa sayap dan dinding palsu!

Keadaan korup dari lemari dapur.
>

Dinding palsu bergerak menjauh dari pemain.
>

Dinding palsu adalah kelompok model yang akan kami kembalikan saat pemain memasuki volume pemicu, yang merupakan bagian transparan sebelumnya di lemari yang akan mereka lewati.Pemicu itu juga digunakan dalam skrip yang mirip dengan yang digunakan di semua pintu kami, yang disebut TweenService untuk bergerak dari satu tujuan ke tujuan lain.Kami menggunakan volume bagian untuk memberi tahu operasi tweening di mana posisi awal dan akhir untuk dinding.

Volume bagian memicu dinding palsu di belakangnya untuk bergerak ke titik akhirnya.Ini dibuat terlihat dalam gambar ini dengan warna kuning.

Target_Closed adalah bagian target umum yang kami gunakan di semua pintu kami untuk tempat mereka berputar.Di sini diubah untuk memberi tahu dinding koridor ke mana harus mulai.

Karena TweenService adalah sistem umum seperti itu, semua model data dinding kami harus berisi komponen yang sama.Sebagai contoh, skrip umum "Door_Script" memainkan suara yang didefinisikan oleh "nilai" di bawah model "Grow_Wall".Skrip yang sama, dengan beberapa modifikasi dalam contoh kode berikut, juga memicu audio untuk gerakan pantry.Ini menambah banyak ke gerakan!


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, --Waktu/Kecepatan Tween Pintu
Enum.EasingStyle.Quart, --Gaya Meringankan
Enum.EasingDirection.InOut, --Arah Mudahkan
0, --Ulangi Hitungan
false, --Balikkan benar
0 --Penundaan
)
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
--model["Door"]:Mainkan()
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("sentuh")
playersNear[player] = 1
if doorState == DoorState.Closed then
StartOpening()
end
end
end
end

Setelah kami memiliki dinding palsu yang bergerak ke belakang ruangan, kami membutuhkan sisa konten untuk bergerak bersama dengannya.Untuk melakukan itu, kami membutuhkan semua item longgar di lemari untuk disambung ke dinding saat bergerak.Menggunakan Kontraksi Las, kami dapat dengan cepat menyambungkan semua objek ke dinding pantry untuk bergerak sebagai objek tunggal.Melakukan ini berarti kami memiliki pilihan untuk tidak menyambungkan item ini sehingga pemain bisa bertabrakan dengan mereka dan mengetuknya!

Buat rumah pohon yang rusak

Studio adalah mesin berbasis fisik yang fantastis yang dapat Anda gunakan untuk membuat segalanya dari gerbang berayun ke platform berputar.Dengan demo kami, kami ingin menggunakan fisika untuk menciptakan rasa realisme dalam satu set lingkungan yang tidak realistis.Menggunakan beberapa batasan saja , Anda dapat membuat beberapa rintangan menyenangkan dan menantang dalam pengalaman Anda sendiri!

Batasan adalah kelompok motor berbasis fisik yang mengatur objek dan membatasi perilaku.Sebagai contoh, Anda dapat menggunakan batas batang untuk menghubungkan ke objek agar tetap berjarak tetap dari satu sama lain, atau batas tali untuk memiliki lampu yang menggantung di ujung garis.Untuk teka-teki putra di mana pemain dibawa ke negara korup penelitian, kami ingin secara harfiah membalikkan dunia di sisinya.Melakukan hal itu akan menghalangi harapan pemain tentang kenyataan dan aturan di sana, sementara masih menggunakan sistem fisika seperti yang dimaksudkan!

Puzzle putra dimulai dengan pemain di ruangan yang sama, tetapi semuanya berada di samping.

Setelah pemain bekerja ke area utama teka-teki, mereka disambut dengan pemandangan yang familiar di Roblox: rintangan.Rintangan khusus ini terdiri dari beberapa platform berputar dan dinding berputar, serta "area aman" yang memajukan cerita.Kami akan fokus pada elemen berputar/berputar.

Penampilan yang membingungkan pikiran menyembunyikan kenyataan bahwa gameplay di sini sangat sederhana.

Mengapa kami menggunakan batasan di sini? Karena TweenService atau metode lain tidak akan memindahkan pemain saat mereka berdiri di atasnya.Tanpa objek yang memindahkan pemain, seseorang bisa melompat di atas platform dan akan berputar dari bawah mereka.Sebagai gantinya, kami ingin pemain menavigasi melalui platform berputar saat mencoba melompat ke yang berikutnya.Karena pendekatan ini, pemain merasa terikat di mana mereka berdiri saat membuat keputusan dengan cara melanjutkan melalui trek, dan kami tidak perlu melakukan sesuatu yang istimewa untuk memastikan mereka bergerak dengan permukaan berputar!

Anda bisa menonton teman-teman Anda berputar sambil mencoba menavigasi jalur penghalang juga.

Untuk melakukan ini, kami perlu terlebih dahulu menggunakan aset dari kit saat ini dan menambahkan konten baru untuk efek visual.Kami membuat beberapa dinding dan platform tidak lengkap dengan lubang di dalamnya untuk menceritakan kisah nenek yang membangun rumah pohon.Karena kami tidak ingin membuat banyak platform unik, kami membuat 4 bagian dasar dan bagian Railing secara terpisah.Ini memungkinkan kami untuk mencampur dan mencocokkan bagian basis dan Railing individu untuk memiliki banyak variasi.

Kami tahu bahwa karena kami menggunakan batasan, kami tidak akan dapat mengaitkan meshes ini karena mereka tidak akan bergerak bahkan dengan kehadiran batasan/motor yang menggerakkan mereka.Kontraksi yang diperlukan untuk menjadi anak dari sesuatu yang diikat agar platform tidak hanya jatuh dari dunia.Kami memecahkan ini melalui bagian yang kami beri nama Motor_Anchor yang memiliki batas geser untuk menggerakkan seluruh gerakan platform.Setelah itu, kami membutuhkan dua meshes untuk bergerak sebagai satu, jadi kami membuat bagian yang kami beri nama Motor_Turn , lalu kami menyambungkan dua meshes ke bagian itu.Dengan cara ini batasan akan dapat bekerja pada satu bagian, dibandingkan dengan engsel multi yang bekerja dengan beberapa bagian.

Sekarang saatnya untuk mengatur perilaku aktual dari batas geser itu sendiri, dan menambahkan lampir yang akan bertindak sebagai orientasi bagian dan batas bersama-sama.Kami menempatkan lampir balik di Motor_Turn, ke mana bagian jalan di las, dan lampir lain untuk perilaku anchor pada Motor_Anchor sendiri, di samping kendala engsel.Karena ini perlu berputar memiliki, berlawanan dengan dipengaruhi oleh pemain (seperti engsel pintu), kami mengatur HingeConstraint.ActuatorType ke Motor , memperlakukan keterbatasan seperti motor bergerak sendiri.

Untuk menjaga platform berputar dengan kecepatan konstan, kami kemudian mengatur properti HingeConstraint.AngularVelocity, HingeConstraint.MotorMaxAcceleration, dan HingeConstraint.MotorMaxTorque untuk nilai yang akan memungkinkan gerakan dan mencegah gangguan jika pemain melompat di atasnya.

Attachment0 pada dasarnya adalah pengait untuk engsel dan Attachment1 mewakili engsel itu sendiri.Kami memiliki engsel yang terus berputar, tetapi Anda juga dapat menggunakan batasan engsel untuk pintu.

Sekarang kami perlu membuat dinding berputar.Dinding perlu berputar di pusat yang tampaknya, dan kami tahu kami ingin mereka dapat menangani orientasi apa pun terhadap sisa level.Seperti platform, kami membangun ini sehingga semua dinding tidak terpasang dan disambungkan ke Motor_Turn.

Kami ingin menggunakan kembali sebanyak mungkin meshes rumah pohon aktual untuk menghemat kinerja, jadi kami mengikuti jalur serupa seperti platform.Beberapa jenis dinding dibuat yang bisa menempel bersama dalam kombinasi berbeda untuk beberapa variasi.

Kami menggunakan objek Texture di atas objek SurfaceAppearance untuk menambahkan beberapa variasi pada bahan dasar kami.Tekstur , mirip dengan Decal, memungkinkan Anda untuk menempatkan gambar di pesawat meshes.Ini bisa berguna jika Anda ingin menambahkan kotoran ke dinding batu bata, atau membuat kayu terlihat tua saat menggunakan bahan kayu dasar yang sama. Texture objek memiliki perilaku yang sedikit berbeda dari Decal objek di mana Anda dapat mengatur ubin dan mengimbangkan gambar sesuai keinginan Anda, yang sangat berguna jika Anda ingin dapat menyesuaikan teksur overlay Anda dan tidak keberatan itu diulang!

Anda dapat melihat perilaku serupa dan mengatur untuk batas geser, serta bagaimana kami menggunakan objek Texture.

Setelah kami menguji beberapa platform dan dinding berputar, kami membuat beberapa variasi dan bermain dengan penempatan mereka untuk memastikan trek penghalang menantang, membingungkan pikiran, dan juga jelas di mana pemain perlu mulai! Butuh beberapa penyesuaian untuk kedua nilai dan posisi mereka untuk membuat mereka berjalan dengan baik.Kami memiliki beberapa titik di mana platform dan dinding saling memukul atau lingkungan, tetapi dengan beberapa bergerak di sekitar dan pengujian sering, kami dapat mendarat di pengaturan yang kami miliki di demo!

Jika Anda tidak yakin apa objek fisik yang Anda pukul, Anda dapat beralih pada Keandalan kolisi dari widget Opsi visualisasi di sudut kanan atas tampilan 3D.

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.
Saat visualisasi kolisi dinonaktifkan, Anda dapat melihat representasi geometri normal yang ditampilkan dalam game.
Saat visualisasi kolisi diaktifkan, Anda dapat melihat daun pohon tidak memiliki kolisi, sehingga tidak akan mengganggu platform berputar atau dinding.

Seperti yang Anda lihat di bawah lubang pintu/jendela terlihat, tetapi rincian yang lebih kecil seperti sub-paneling tidak.Ini karena properti CollisionFidelity untuk dinding diatur ke Kotak .Kami tidak membutuhkan ketepatan untuk panel ini, jadi untuk menghemat biaya kinerja, ini cukup terperinci bagi pemain untuk melompat ke atasnya.Dengan platform dan dinding berputar selesai, kami hanya perlu menambahkan aset detail seperti kotak dan lampu, lalu sudah siap dimainkan!