165 lines
5.9 KiB
C#
165 lines
5.9 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Code.Gameplay.Level
|
|
{
|
|
public class LevelBuilder : MonoBehaviour
|
|
{
|
|
[Header("Tile Settings")] [SerializeField]
|
|
private GameObject[] tilePrefabs;
|
|
|
|
[SerializeField] private float tileLength = 6f;
|
|
[SerializeField] private int numberOfTiles = 20;
|
|
[SerializeField] private Transform playerTransform;
|
|
|
|
[Header("Environment Settings")] [SerializeField]
|
|
private GameObject[] treePrefabs;
|
|
|
|
[SerializeField] private float sideOffset = 10f;
|
|
[SerializeField] private float treeRandomSpread = 2f;
|
|
|
|
[Header("Obstacles Settings")] [SerializeField]
|
|
private GameObject[] lowObstacles;
|
|
[SerializeField] private GameObject[] highObstacles;
|
|
[SerializeField] private GameObject[] movingLowObstacles;
|
|
[SerializeField] private GameObject[] movingHighObstacles;
|
|
[SerializeField] private GameObject[] sideObstacles;
|
|
[Range(0, 100)] [SerializeField] private int obstacleChance = 40;
|
|
[SerializeField] private float laneDistance = 5f;
|
|
|
|
[Header("Coins Settings")]
|
|
[SerializeField] private GameObject coinPrefab;
|
|
[Range(0, 100)] [SerializeField] private int coinChance = 50;
|
|
|
|
[Header("Bonus Settings")]
|
|
[SerializeField] private GameObject bonusX2Prefab;
|
|
[Range(0, 100)] [SerializeField] private int bonusChance = 10;
|
|
|
|
private readonly List<GameObject> _activeTiles = new();
|
|
private readonly List<GameObject> _activeEnvironment = new();
|
|
private float _spawnZ;
|
|
|
|
private void Start()
|
|
{
|
|
for (var i = 0; i < numberOfTiles; i++)
|
|
{
|
|
SpawnTile(i < 10 ? 0 : Random.Range(0, tilePrefabs.Length), i >= 10);
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (playerTransform.position.z - 35 > _spawnZ - numberOfTiles * tileLength)
|
|
{
|
|
SpawnTile(Random.Range(0, tilePrefabs.Length), true);
|
|
DeleteTile();
|
|
}
|
|
}
|
|
|
|
private void SpawnTile(int tileIndex, bool spawnItems)
|
|
{
|
|
var tile = Instantiate(tilePrefabs[tileIndex], transform.forward * _spawnZ, transform.rotation);
|
|
_activeTiles.Add(tile);
|
|
|
|
SpawnEnvironment(_spawnZ);
|
|
|
|
if (spawnItems)
|
|
{
|
|
var occupiedLane = SpawnObstacle(_spawnZ);
|
|
SpawnCoins(_spawnZ, occupiedLane);
|
|
}
|
|
|
|
_spawnZ += tileLength;
|
|
}
|
|
|
|
private int SpawnObstacle(float zPos)
|
|
{
|
|
if (Random.Range(0, 100) > obstacleChance) return -2;
|
|
|
|
var lane = Random.Range(-1, 2);
|
|
var spawnPos = new Vector3(lane * laneDistance, 0, zPos);
|
|
|
|
var type = Random.Range(0, 5);
|
|
|
|
var prefab = type switch
|
|
{
|
|
0 => GetRandom(lowObstacles),
|
|
1 => GetRandom(highObstacles),
|
|
2 => GetRandom(movingLowObstacles),
|
|
3 => GetRandom(movingHighObstacles),
|
|
4 => GetRandom(sideObstacles),
|
|
_ => null
|
|
};
|
|
|
|
if (prefab)
|
|
{
|
|
var obs = Instantiate(prefab, spawnPos, Quaternion.Euler(0, 180, 0));
|
|
obs.transform.SetParent(_activeTiles[^1].transform);
|
|
}
|
|
|
|
return lane;
|
|
}
|
|
|
|
private void SpawnCoins(float zPos, int occupiedLane)
|
|
{
|
|
if (Random.Range(0, 100) > coinChance) return;
|
|
|
|
var coinLane = Random.Range(-1, 2);
|
|
if (coinLane == occupiedLane)
|
|
{
|
|
coinLane = (coinLane + 1 > 1) ? -1 : coinLane + 1;
|
|
if (coinLane == occupiedLane) coinLane = (coinLane + 1 > 1) ? -1 : coinLane + 1;
|
|
}
|
|
|
|
var shouldSpawnBonus = Random.Range(0, 100) < bonusChance;
|
|
|
|
if (shouldSpawnBonus && bonusX2Prefab)
|
|
{
|
|
var spawnPos = new Vector3(coinLane * laneDistance, 1f, zPos + tileLength / 2f);
|
|
var bonus = Instantiate(bonusX2Prefab, spawnPos, Quaternion.identity);
|
|
bonus.transform.SetParent(_activeTiles[^1].transform);
|
|
}
|
|
else if (coinPrefab)
|
|
{
|
|
for (var i = 0; i < 2; i++)
|
|
{
|
|
var spawnPos = new Vector3(coinLane * laneDistance, 1f, zPos + (i * 2f));
|
|
var coin = Instantiate(coinPrefab, spawnPos, Quaternion.identity);
|
|
coin.transform.SetParent(_activeTiles[^1].transform);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static GameObject GetRandom(GameObject[] array)
|
|
{
|
|
return array.Length > 0 ? array[Random.Range(0, array.Length)] : null;
|
|
}
|
|
|
|
private void SpawnEnvironment(float zPos)
|
|
{
|
|
var envContainer = new GameObject("EnvGroup_" + zPos);
|
|
envContainer.transform.SetParent(transform);
|
|
CreateTree(-sideOffset, zPos, envContainer.transform);
|
|
CreateTree(sideOffset, zPos, envContainer.transform);
|
|
_activeEnvironment.Add(envContainer);
|
|
}
|
|
|
|
private void CreateTree(float xOffset, float zPos, Transform parent)
|
|
{
|
|
if (treePrefabs.Length == 0) return;
|
|
var spawnPos = new Vector3(xOffset + Random.Range(-treeRandomSpread, treeRandomSpread), 0,
|
|
zPos + Random.Range(-treeRandomSpread, treeRandomSpread));
|
|
var tree = Instantiate(treePrefabs[Random.Range(0, treePrefabs.Length)], spawnPos,
|
|
Quaternion.Euler(0, Random.Range(0, 360), 0));
|
|
tree.transform.SetParent(parent);
|
|
}
|
|
|
|
private void DeleteTile()
|
|
{
|
|
Destroy(_activeTiles[0]);
|
|
_activeTiles.RemoveAt(0);
|
|
Destroy(_activeEnvironment[0]);
|
|
_activeEnvironment.RemoveAt(0);
|
|
}
|
|
}
|
|
} |