Documentatie Jason - j5x/PvB2025 GitHub Wiki
Allow the Match-3 grid to be manually positioned in the Unity Inspector using a gridOffset field, without it being overwritten at runtime.
โ
No pre-existing matches at the start.
โ
Swappable tiles with valid match detection.
โ
Tile gravity ensures tiles fall into empty spaces.
โ
Grid automatically refills after matches.
[SerializeField] private Vector3 gridOffset;This lets you position the grid wherever you want in the scene from the Unity Inspector.
private void SpawnTile(int x, int y)
{
GameObject tilePrefab;
do
{
tilePrefab = GetRandomTilePrefab();
} while (WouldCreateMatch(x, y, tilePrefab));
Vector3 spawnPosition = new Vector3(x * tileSize, y * tileSize, 0) + gridOffset;
GameObject tile = Instantiate(tilePrefab, spawnPosition, Quaternion.identity, transform);
Tile tileComponent = tile.GetComponent<Tile>();
tileComponent.SetGridPosition(new Vector2Int(x, y));
_grid[x, y] = tile;
}private IEnumerator MoveTile(Tile tile, Vector3 targetPos)
{
if (tile == null || tile.gameObject == null) yield break;
float duration = 0.2f;
float elapsedTime = 0f;
Vector3 startPos = tile.transform.position;
while (elapsedTime < duration)
{
if (tile == null || tile.gameObject == null) yield break;
tile.transform.position = Vector3.Lerp(startPos, targetPos + gridOffset, elapsedTime / duration);
elapsedTime += Time.deltaTime;
yield return null;
}
if (tile != null && tile.gameObject != null)
{
tile.transform.position = targetPos + gridOffset;
}
}
Loads the next scene when pressed: This is the start button
using UnityEngine;
using UnityEngine.SceneManagement;
public class StartButton : MonoBehaviour
{
public void StartGame()
{
SceneManager.LoadScene("LevelSelector"); // Replace with your level name
}
}-
Background Scaling: Uses a
CanvaswithCanvasScalerset toScale With Screen Sizeto support phone resolutions. - Button Scaling: Buttons are inside the Canvas with anchoring and responsive layout (e.g., Vertical Layout Group, Content Size Fitter).
This is the credits button
- UI Text/Panel toggled by button:
using UnityEngine;
public class CreditsPopup : MonoBehaviour
{
[SerializeField] private GameObject creditsPanel;
public void ToggleCredits()
{
creditsPanel.SetActive(!creditsPanel.activeSelf);
}
}- Button assigned to different scenes via a simple script:
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelButton : MonoBehaviour
{
public void LoadLevel(string levelName)
{
SceneManager.LoadScene(levelName);
}
}- Character is selected via UI and remembered using a persistent GameManager:
using UnityEngine;
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
public GameObject selectedPlayerPrefab;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}- In the scene:
void Start()
{
Instantiate(GameManager.Instance.selectedPlayerPrefab, spawnPosition, Quaternion.identity);
}- Triggers
OnDeathevent when HP reaches 0.
- Subscribes to
OnDeathand notifies spawner:
private void HandleDeath()
{
if (spawner != null)
{
spawner.SpawnEnemy();
}
Destroy(gameObject);
}- Delay before spawn
- Max number of enemies that can spawn
using UnityEngine;
using System.Collections;
public class EnemySpawner : MonoBehaviour
{
[SerializeField] private GameObject enemyPrefab;
[SerializeField] private Transform spawnPoint;
[SerializeField] private float respawnDelay = 2f;
[SerializeField] private int maxSpawns = 5;
private int spawnCount = 0;
public void SpawnEnemy()
{
if (spawnCount >= maxSpawns) return;
StartCoroutine(SpawnEnemyWithDelay(respawnDelay));
}
private IEnumerator SpawnEnemyWithDelay(float delay)
{
yield return new WaitForSeconds(delay);
GameObject newEnemy = Instantiate(enemyPrefab, spawnPoint.position, Quaternion.identity);
Enemy enemyScript = newEnemy.GetComponent<Enemy>();
if (enemyScript != null)
{
enemyScript.spawner = this;
}
spawnCount++;
}
}- Make sure all prefabs are assigned in the inspector.
- Use
DontDestroyOnLoadonly on necessary singletons like GameManager. - Consider object pooling for performance if many enemies are involved.
Purpose:
Manages global game state across scenes, specifically tracking the selected character prefab.
Key Features:
- Singleton pattern with
DontDestroyOnLoad. - Holds reference to
SelectedCharacterPrefab. - Event
OnCharacterSelectednotifies UI when a character is picked.
Usage:
GameManager.Instance.SelectCharacter(prefab);
GameManager.Instance.SelectedCharacterPrefab;Purpose:
Automatically tracks the next enemy when the current one is defeated.
Key Features:
- Searches for GameObject with tag
"Enemy". - Subscribes to new enemy's
HealthComponentdynamically.
Usage:
GameObject enemy = GameObject.FindWithTag("Enemy");
targetHealthComponent = enemy.GetComponent<HealthComponent>();This system handles a talking animated character ("Donut Cop") that delivers tutorial lines via a speech bubble on screen.
| Object | Description |
|---|---|
DonutCopTutorial |
Main script controlling the tutorial sequence. |
Animator |
Animates the cop (Idle, Talk, etc.). |
SpeechBubble |
A UI GameObject (enabled/disabled to show dialogue). |
TextMeshProUGUI |
Displays typed-out tutorial text inside the bubble. |
SceneManager |
Used to transition to the next scene after tutorial ends. |
-
Tutorial Starts Automatically on
Start(). - Each line of dialogue is typed out character by character.
-
Cop animation is triggered (
"Talk"trigger). - Player can tap to skip typing and instantly show full text.
- After all lines, the speech bubble disappears.
- Scene is changed automatically to the next level or scene.
In DonutCopTutorial.cs:
[SerializeField] private string[] tutorialLines; // Lines of dialogue
[SerializeField] private float delayBetweenLines = 1.5f; // Delay after each line
[SerializeField] private float textTypingSpeed = 0.03f; // Speed of character-by-character typing
[SerializeField] private string nextSceneName = "Level1"; // Scene to load after tutorial- Place a Donut Cop GameObject in Canvas.
- Attach
DonutCopTutorial.cs. - Assign:
- Animator with
"Talk"trigger. -
speechBubbleGameObject. - TextMeshPro component inside the bubble.
- Animator with
- Populate
tutorialLines[]in Inspector. - Make sure
nextSceneNamematches your level name.
| Action | Result |
|---|---|
| Tap during typing | Skips to full sentence instantly. |
| Wait for auto progression | Moves to next sentence. |
| Last line completes | Loads new scene. |