Salut tuturor, AL aici. Bine ati venit la prima privire in culisele lui Mortumus.
In timp ce Fin e ingropat in minele serverului, luptandu-se cu baze de date, subscriptions si toata magia infricosatoare de distributed systems care tine lumea in viata, eu sunt la celalalt capat, asigurandu-ma ca fiecare lovitura de sabie, pas, palparire de torta si piesa de armura arata si se simte bine pe ecranul vostru.
Construirea unui MMO dark fantasy nu e genul de lucru pe care il poti asambla cu drag-and-drop dintr-un asset store. Senzatia aspra, oldschool pe care o urmarim (greutatea luptei, scrasnitul armurii, spaima cand vezi alt jucator la orizont) apare doar cand uneltele de dedesubt sunt construite special pentru asta. Asa ca azi dau la o parte cortina si va arat cateva dintre sistemele Unity personalizate pe care le-am construit pe partea de client: cele pe care nimeni nu le va vedea vreodata, dar pe care toata lumea le va simti.
Hai sa incepem.
Vizuale, Loot si Confidentialitate in PvP
Daca exista un adevar despre jucatorii de MMO, e acesta: iubim gear-ul. Si intr-un joc full-loot PvP ca Mortumus, gear-ul nu e doar o doza de dopamina, e informatie. Ce poarta cineva iti spune ce iti poate face.
Tine-l secret, tine-l in siguranta: Equipment Visualizer
Devreme am realizat ca avem o problema pe care multe MMO-uri o ignora in liniste: daca clientul stie ID-ul exact al fiecarui item echipat pe fiecare jucator vizibil, un cheater hotarat poate extrage asta din memorie si sa-ti stie stat-urile exacte inainte sa decida sa te omoare.
Asa ca Equipment Visualizer-ul nostru face ceva usor paranoid. Pentru propriul tau personaj, citeste din serviciul complet de echipament, vezi tot despre gear-ul tau. Dar pentru orice alt jucator, citeste doar un blob simplificat de "visuals" pe care serverul il publica. Vezi sabia, nu fisa de stat-uri. ID-urile item-elor altor jucatori pur si simplu nu parasesc niciodata serverul lui Fin.
E un lucru mic. De asemenea, face cheats-urile de memory-scraping mult mai putin utile. Schimb bun.
Stiva de Animatii
Lupta bazata pe skill traieste sau moare prin animatie. Daca windup-ul nu e lizibil, nu poti reactiona. Daca lovitura nu aterizeaza, lupta se simte fara greutate. Daca moartea arata ca si cum modelul pur si simplu... s-a oprit, pierzi jumatate din atmosfera.
Player Animation Coordinator
Am inceput asa cum incepe toata lumea: o clasa giganta de animation controller care incerca sa gestioneze totul. Miscare, vraji, moarte, lovituri, idles, totul intr-un singur fisier. Dupa vreo doua saptamani era un haos.
Asa ca am spart-o in bucati. Acum Player Animation Coordinator e un punct de intrare minuscul care porneste o stiva de module mici si specializate: miscare, rotatie, atac, vraji, reactii la lovituri, moarte, idles. Fiecare modul face un singur lucru. Fiecare e lizibil de unul singur. Bug-urile se gasesc in minute, nu in ore.
Cod mai curat pentru mine. Lupta mai stransa pentru voi.
Receptivitatea luptei: Attack Animator & Spell Animator
Iata problema clasica de MMO: lupta server-authoritative e singura cale sa opresti cheating-ul, dar sa astepti ca serverul sa confirme fiecare cast se simte ca melasa.
Spell Animator-ul nostru triseaza putin, dar sincer. Cand apesi tasta de vraja, animatia de cast porneste imediat, prezisa local, ca sa se simta instant. Apoi serverul lui Fin valideaza daca cast-ul a fost legal (cooldown expirat, destula mana, tinta valida etc.). Daca confirma, nimic nu se schimba. Daca respinge, iesim curat din animatie.
Attack Animator face acelasi dans pentru melee si chiar scaleaza viteza swing-ului sa se potriveasca cu cadenta pe care serverul o spune pentru arma ta. Ochii tai vad lupta responsiva. Serverul vede o lume careia nu i se poate minti.
Acel punct dulce intre "se simte bine" si "joaca corect" e locul in care traieste intregul joc.
Sunetele Regatului
Audio-ul e 50% din atmosfera si lumea subestimeaza mereu cat de multa munca necesita.
Crearea atmosferei: Audio Manager & Music Region System
Jocurile traditionale tind sa schimbe muzica printr-o taietura brusca cand treci o linie invizibila. E socant. Noi o facem cu zone poligonale 3D. Music Region System ne permite sa pictam zone de forma arbitrara in lume (un creng fermecat, o capela blestemata, apropierea de un boss), iar cand intri si iesi, Audio Manager face crossfade la coloana sonora lin. Fara taieturi. Fara restartarea aceluiasi track daca calci pe granita.
Si pentru ca totul ruleaza prin surse audio din pool cu rutare pe mixer-group, nu costa practic nimic din bugetul de cadre.
Character Audio Manager
Fiecare pas in Mortumus e legat de animatia personajului tau si de suprafata de sub tine: piatra suna ca piatra, noroiul suna ca noroiul. Sunetele vrajilor sunt legate de abilitate, cele ale armelor de arma. Character Audio Manager sta intre animation events si Audio Manager, asa ca putem schimba pachete SFX noi pe rasa/clasa fara sa atingem cod de gameplay.
Lucruri mici. Multe. Se aduna.
Marginea Apei
Fiecare lume dark fantasy are apa. Mlastini, rauri, ruine inundate, marea la marginea unui cap blestemat. Si apa e unul din acele lucruri care arata fals foarte usor, mai ales acolo unde intalneste uscatul. Acea linie poligonala urata a apei unde mesh-ul intersecteaza terenul e semnatura unui joc care arata ieftin.
Baza noastra de apa
Nu am construit apa de la zero. Unity vine de fapt cu un proiect demo fantastic numit Boat Attack care include unul din cele mai bune sisteme de apa URP de pe piata: reflexii reale, refractii, flotabilitate, tot tacamul. Asa ca am pornit cu apa din Boat Attack ca fundatie, pentru ca reinventarea rotii ne-ar fi costat luni intregi fara un castig real.
Dar Boat Attack a fost construit pentru, pai... barci. Linii de coasta oceanice frumoase si curate. Comportamentul de coasta care arata grozav pe o plaja cu nisip arata oribil in jurul apelor noroioase, stufoase si neregulate pe care le vrem de fapt in Mortumus. Asa ca a trebuit sa fim chirurgicali.
Shader-ul personalizat: WaterShoreline
In loc sa editam pachetul Unity direct (ceea ce s-ar fi stricat la fiecare update), am scris un shader personalizat subtire "WaterShoreline" care inlocuieste doar bucata din pipeline responsabila de coasta. Tot restul (reflexii, flow maps, caustics) vine direct din Boat Attack. Suprascriem doar ce avem nevoie.
Cele doua schimbari mari:
Cutoff-ul dur de spuma de 2 metri a disparut. Banda de spuma implicita a Boat Attack are un cutoff fix de adancime, care iti da acel "inel alb" uniform in jurul fiecarei coaste. L-am inlocuit cu un falloff mai moale plus un camp de noise derulant, asa ca spuma acum se estompeaza treptat si se sparge in limbi si degete organice in loc de o panglica perfecta.
Alpha moale la linia de coasta. Problema cu linia poligonala a apei pe teren? Facem fade la apa insasi spre transparent pe ultimul jumatate de metru de adancime. Linia apei dispare complet. Terenul pur si simplu devine mai inchis pe masura ce merge sub apa, asa cum face o coasta reala umeda.
Sistemul nostru de rauri
Iata chestia cu apa din Boat Attack: direct din cutie gestioneaza oceanele frumos, dar nu stie cu adevarat ce e un rau. Apa poate sa se onduleze pe loc, dar nu poate curge in aval si in jurul unui cot asa cum face un rau real. E o problema cand jumatate din lumea ta dark fantasy trebuie sa fie mlastinoasa, plina de rauri si inmuiata.
Asa ca am construit un sistem de rauri deasupra.
Un rau in Mortumus e creat ca un traseu de curgere, o polilinie simpla de puncte care traseaza coloana vertebrala a raului de la sursa la varsare. Designerii pun punctele unde vor sa curga apa, iar shader-ul face restul: pentru fiecare pixel de suprafata de apa, determina care segment al traseului de curgere e cel mai apropiat si foloseste directia acelui segment ca curent local. Rezultat: apa langa o sectiune dreapta curge drept, apa pe interiorul unui cot curbeaza cu cotul, si totul face tranzitie lin intre ele.
Texturile, normalele si spuma se deruleaza toate in directia de curgere in loc sa pluteasca fara tinta. Poti vedea cu adevarat in ce directie curge raul.
Totul e reglabil live din ShoreFoamTuner, o componenta mica de inspector pe care o punem pe orice scena cu apa. Slidere pentru moliciunea spumei, scara noise-ului, intensitatea noise-ului, viteza de drift, falloff-ul alpha. Schimba atmosfera unui lac intreg fara sa atingi un material.
Comunitate si Trash Talk: Chat & Social
Un MMO oldschool e la fel de mult despre oameni cat si despre joc. Daca uneltele sociale se simt prost, lumea se simte goala.
Overhead Chat System
Text ancorat fix deasupra capului unui personaj, urmarindu-l cand se misca, estompandu-se la distanta: un element absolut de baza al genului si ceva pentru care vom lupta pana la capat.
Transforma grupurile in conversatii reale. Te lasa sa faci trash talk cuiva in mijlocul luptei. Permite ca ultimele cuvinte ale unui jucator care moare sa fie ceva prost si amuzant in loc de o linie de log de sistem. Overhead Chat System gestioneaza pooling, distance culling si anchor tracking ca sa scaleze chiar si cand douazeci de oameni se striga unii la altii intr-un dungeon inghesuit.
Sa arati bine
Fii sincer: o sa petreci o cantitate jenanta de timp in ecranul de personaj. Toti o facem. E cea mai frumoasa oglinda din joc.
Sistemul de previzualizare a personajului
Paper doll-ul nostru nu e un render 2D prebaked, e o scena 3D live randata intr-o render texture de UI. Iluminare completa, geometrie reala, fiecare piesa de echipament pe tine in timp real. Roteste-l, da zoom, holbeaza-te la el. E genul de feature care nu schimba gameplay-ul deloc si schimba absolut tot modul in care se simte jocul.
Umplerea sacilor: Icon Studio
Iata un mic secret murdar al dezvoltarii de MMO-uri: iconitele. Ai nevoie de sute. Fiecare sabie, fiecare potiune, fiecare bucata de loot gunoi pe care o gasesti intr-un cufar are nevoie de propriul sau patrat mic de 64x64 care se citeste curat intr-un inventar aglomerat. Si toate trebuie sa arate ca apartin aceluiasi joc.
Nu poti pur si simplu sa faci screenshot la un model 3D si gata. Iluminarea trebuie sa fie consistenta. Unghiul camerei trebuie sa fie consistent. Si (asta e partea pe care toata lumea o subestimeaza) incadrarea trebuie sa se potriveasca cu dimensiunea de grid pe care item-ul o va ocupa in inventar. Un pumnal 1x1 si o sabie mare 2x3 au nevoie de compozitii complet diferite, altfel amandoua arata gresit.
Solutia noastra: Icon Studio
Icon Studio e o fereastra de editor Unity personalizata pe care am construit-o ca o singura persoana (de obicei eu, mormaiind) sa poata produce o suta de iconite consistente fara sa-si piarda mintile.
Workflow-ul: pune o lista de prefab-uri de item-uri. Spune-i tool-ului ce dimensiune de grid ocupa fiecare in inventar: 1x1, 2x2, 2x3, 1x4, orice. Incadreaza camera o data. Salveaza incadrarea ca preset. Apasa Genereaza.
Magia e ca dimensiunea de grid nu e cosmetica, ea conduce render-ul real. Un item 2x3 se randeaza la 2x latime si 3x inaltime (dintr-o baza de 512px), asa ca proportiile sunt corecte cand sta in inventar, nu intinse. O sabie lunga chiar umple un slot 1x4 pe diagonala. O sticluta de potiune chiar incape in 1x1. Inventarul se simte ca si cum ai organiza obiecte reale.
Pe langa asta, tool-ul gestioneaza: fundal transparent sau personalizat per item, bone pose capture ca item-urile bazate pe schelet sa-si poata salva poza de afisare fara sa deranjeze rig-ul de gameplay, si preset-uri pentru categorii intregi de item-uri, toate topoarele se randeaza cu aceeasi camera, toate potiunile cu alta. Consistenta gratis.
Rezultatul final e ca fiecare iconita din joc (cele care se citesc bine la 32 de pixeli intr-un grid dens de inventar) a fost randata din modelul real din joc, la forma reala pe care item-ul o ocupa in geanta ta. Fara arta 2D externalizata. Fara iluminare nepotrivita. Fara pumnal care cumva arata mai mare decat o sabie mare in UI.
E genul de tool pe care nimeni nu-l vede. E de asemenea motivul pentru care inventarul nu arata ca o geanta de stock art asortat la intamplare.
Pana data viitoare
Niciunul dintre aceste sisteme nu e un feature principal al lui Mortumus. Nimeni nu va cumpara jocul pentru ca pasii suna bine sau pentru ca scheletele explodeaza in bucati de fizica. Dar acestea sunt oasele de sub tot: munca invizibila care face ca lucrurile mari sa se simta corect cand aterizeaza deasupra lor.
Cu aceasta fundatie pusa, Fin si cu mine putem construi lumea sumbra, brutala, cu full-loot pe care am schitat-o in caiete de doi ani, intr-un ritm care nu ne face sa vrem sa ne aruncam calculatoarele intr-un rau.
-- AL