komprimera Tilemap bounds bra gjort, spelbrädet är klart att användas! Vi återkommer till detta i del 3.
del 2. Nivådata
eftersom vi vill återanvända samma scen och samma spelbräda bör nivådata hållas någonstans. En enkel lösning för det är en enkel json-fil som beskriver hur varje nivå ska byggas.
det är viktigt att förstå vad vi försöker uppnå, det är därför jag måste säga några ord om mekaniken. I spelet finns föremål som rör sig längs vägen från början till slutet (ungefär som i Zuma) och spelarens mål är att förstöra dem alla. I denna handledning skapar vi den här vägen som kommer att vara unik för varje nivå.
okej, tillbaka till projektet.
det finns flera sätt att komma åt en extern data i en runtime från ett skript. Här kommer vi att använda resurser mappar
låt oss skapa en ny mapp-filer-och en undermapp resurser. Det är den plats vi vill behålla data, så skapa en ny fil-nivåer.json och placera den där.
för handledningsändamål har vi bara två fält för att beskriva varje nivå:
nummer — en int för att identifiera en nivå
sökväg — den kakelbaserade sökvägen som vi vill skapa programmatiskt. Array av värden där första värdet är startpunkten och det sista värdet är slutpunkten.
det här är filen Jag ska använda. Oroa dig inte för dessa värden i path, vi kommer till det senare.
{ "levels": }, { "number": 2, "path": }, { "number": 3, "path": } ] }
låt oss skapa en annan mapp — skript — och nu börjar kodningen äntligen.
Vi vill komma åt data från filen i koden, så vi behöver en modellklass för den. Det är dags att skapa vårt allra första skript – LevelsData
. Det är inte tänkt att instansieras av Unity, såMonoBehaviour
ochStart
Update
metoder bör tas bort. Från filen ovan kan vi se att rotelementet är ett array
av nivåer där varje nivå ska ha en int
fältnummer och en int array
fältväg. Glöm inte att sätta
annotation.
public class LevelsData { public LevelData levels; public class LevelData { public int number; public int path; } }
trevligt, nu har vi filen och modellen. Nästa steg är att förvandla en till en annan. Låt oss skapa ett annat skript – GameZone
— och bifoga det till objektet GameZone
på scenen. Detta skript kommer att användas senare för att ställa in hela spelplanen.
följ principen om enskilt ansvar låt oss skapa ännu ett skript — LevelsDataLoader
— som kommer att göra all omvandling. Bifoga det till objektet GameZone
också.
public class LevelsDataLoader : MonoBehaviour { private const string LevelsPath = "Levels"; public Dictionary<int, LevelsData.LevelData> ReadLevelsData() { var jsonFile = Resources.Load(LevelsPath, typeof(TextAsset)) as TextAsset; if (jsonFile == null) { throw new ApplicationException("Levels file is not accessible"); } var loadedData = JsonUtility.FromJson<LevelsData>(jsonFile.text); return loadedData.levels.ToDictionary(level => level.number, level => level); } }
den här klassen laddar data och returnerar den som en ordbok där nyckeln är nivånumret och data är själva nivådata.
Nu ska vi kunna komma åt data iGameZone
script.
public class GameZone : MonoBehaviour { private Dictionary<int, LevelsData.LevelData> _levelsData; private LevelsDataLoader _dataLoader;private void Awake() { _dataLoader = GetComponent<LevelsDataLoader>(); }private void Start() { _levelsData = _dataLoader.ReadLevelsData();Debug.Log(_levelsData.Count + " levels have been stored in the dictionary!"); } }
byt tillbaka till Unity, tryck på play — knappen och kontrollera konsolen-du bör se meddelandet ” 3 nivåer har lagrats i ordboken!”
del 3. Ansluta styrelsen och Data
Grattis, du har nått den sista och mest intressanta delen av denna handledning. Hur kommer vi faktiskt att ansluta styrelsen och uppgifterna? Fortsätt läsa för att ta reda på det!
Låt oss först och främst placera horizontal
och start_stop
plattor skapade i den första delen av handledningen i mappen resurser under mappen plattor. Lägg sedan till ett nytt skript — TilesResourcesLoader
— en statisk hjälparklass för att ladda brickor från den mappen under en körning.
public static class TilesResourcesLoader { private const string PathHorizontal = "horizontal"; private const string StartStop = "start_stop"; public static Tile GetPathHorizontalTile() { return GetTileByName(PathHorizontal); } public static Tile GetStartStopTile() { return GetTileByName(StartStop); } private static Tile GetTileByName(string name) { return (Tile) Resources.Load(name, typeof(Tile)); } }
som det sista steget bör vi placera dessa plattor på brädet vid scenstart. Låt oss gå tillbaka till skriptet GameZone
. Först och främst måste vi simulera nivåvalet, i det riktiga spelet händer det vanligtvis när en användare trycker på en nivåknapp. För enkelhetens skull låt oss lägga till en offentlig fältnivå till GameZone
och ändra det värde till 1 för start. Jag kommer att visa dig det slutliga skriptet först:
public class GameZone : MonoBehaviour { public int Level; private const int FieldLineSize = 11; private const int FieldTotalTiles = FieldLineSize * FieldLineSize; private Dictionary<int, LevelsData.LevelData> _levelsData; private void Start() { _levelsData = GetComponent<LevelsDataLoader>().ReadLevelsData(); SetupTiles(); } private void SetupTiles() { var baseLevel = GetComponentsInChildren<Tilemap>(); var localTilesPositions = new List<Vector3Int>(FieldTotalTiles); foreach (var pos in baseLevel.cellBounds.allPositionsWithin) { Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z); localTilesPositions.Add(localPlace); } SetupPath(localTilesPositions, baseLevel); } private void SetupPath(List<Vector3Int> localTilesPositions, Tilemap baseLevel) { var path = _levelsData.path; var pathHorizontalTile = TilesResourcesLoader.GetPathHorizontalTile(); var first = path.First(); var last = path.Last(); foreach (var localPosition in localTilesPositions.GetRange(first, Math.Abs(first - last))) { baseLevel.SetTile(localPosition, pathHorizontalTile); } var startStopTile = TilesResourcesLoader.GetStartStopTile(); baseLevel.SetTile(localTilesPositions, startStopTile); baseLevel.SetTile(localTilesPositions, startStopTile); } }
Wow, det är mycket action! Låt mig gå igenom det.
iSetupTiles
– metoden bör vi först få tilemap själv eftersom vi behöver veta positionerna för plattor för att ändra den. För att uppnå detta använder vi tilemap.cellBounds.allPositionsWithin
— metoden som returnerar alla positioner för plattor från och med den allra första-i den givna konfigurationen är det en nere kakel.
se följande bild där varje nummer representerar indexet i listan localTilesPositions
.