Over het Project
OverzichtIk werd uitgedaagd door mijn vrienden om zo snel mogelijk een volledig functionele Pacman-kloon te ontwikkelen. Hoewel er nog een paar uitbreidingen ontbreken, is de core loop van de gameplay – inclusief spelerinvoer, ghost AI en collectibles – volledig operationeel!
Player Movement
Input SystemDe KeyInput ondersteunt WASD, pijltoetsen en joysticks. Ik gebruik Unity's nieuwe Input System in combinatie met een Rigidbody voor responsieve, soepele bewegingen.
using UnityEngine;
using UnityEngine.InputSystem;
[SelectionBase]
public class PlayerMovement : MonoBehaviour
{
private Rigidbody _Rigidbody;
private InputAction _MoveAction;
private PlayerInput _PlayerInput;
[SerializeField] private float _PlayerSpeed;
private void Start()
{
_PlayerInput = GetComponent();
_MoveAction = _PlayerInput.actions.FindAction("Move");
_Rigidbody = GetComponent();
}
private void Update()
{
CalculateMovement();
}
private void CalculateMovement()
{
Vector2 direction = _MoveAction.ReadValue().normalized;
Vector3 movement = new Vector3(direction.x, 0f, direction.y);
_Rigidbody.velocity = movement * _PlayerSpeed;
}
}
Collectibles
Triggers & ScoreOm ervoor te zorgen dat de speler de pellets kan verzamelen en punten scoort, is er een lichtgewicht trigger-handler geschreven.
using UnityEngine;
public class CollectibleHandler : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Coin"))
{
GameManager.Instance.GetPointValue(other.GetComponent().GetPoints());
Destroy(other.gameObject);
}
}
}
Player Health
Game StateDit script verwerkt de levens van de speler en communiceert direct met de centrale GameManager bij opgelopen schade.
using UnityEngine;
public class PlayerHealth : MonoBehaviour
{
public void ChangeHealth(int Damage)
{
GameManager.Instance.PlayerHasDied = true;
GameManager.Instance.Lives -= Damage;
GameManager.Instance.HandleChangeHealth(this.gameObject);
}
}
Enemy Manager
Singleton & CoroutineDe EnemyManager beheert de spoken bij het begin van het spel, inclusief een gecontroleerde start-vertraging via een Coroutine.
using MyBox;
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
public class EnemyManager : Singleton
{
public float EnemyWaitTime;
public GameObject[] Enemies;
private void Awake()
{
InitializeSingleton(false);
StartSendingEnemies();
}
private void StartSendingEnemies()
{
StartCoroutine(SendEnemiesWithDelay());
}
private IEnumerator SendEnemiesWithDelay()
{
foreach (GameObject enemy in Enemies)
{
yield return new WaitForSeconds(EnemyWaitTime);
enemy.GetComponent().enabled = true;
enemy.GetComponent().CanMove = true;
}
}
}
Enemy Movement
NavMesh PathfindingDe beweging van de spoken wordt dynamisch aangestuurd via Unity's NavMeshAgent om de speler over het speelveld te achtervolgen.
using MyBox;
using UnityEngine;
using UnityEngine.AI;
[SelectionBase] [RequireTag("Enemy")]
public class EnemyMovement : MonoBehaviour
{
private NavMeshAgent _EnemyNavmeshAgent;
public bool CanMove = false;
[SerializeField] private GameObject _Player;
[SerializeField] private string _PlayerString;
private void Start()
{
_EnemyNavmeshAgent = GetComponent();
FindPlayerByTag(_PlayerString);
}
private void Update()
{
if (CanMove) GoToPlayer();
}
public void GoToPlayer() => GoToDestination(_Player.transform);
private void FindPlayerByTag(string tag)
{
_Player = GameObject.FindGameObjectWithTag(tag);
}
private void GoToDestination(Transform destination)
{
_EnemyNavmeshAgent.SetDestination(destination.position);
}
}
Enemy Attack
Cooldown SystemWanneer een spook in aanraking komt met de speler, voert het schade uit en activeert het een cooldown-timer om meervoudige hits te voorkomen.
using UnityEngine;
using System.Collections;
public class EnemyAttack : MonoBehaviour
{
private bool _Attacked = false;
[SerializeField] private float _AttackCooldown = 0.5f;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player") && _Attacked == false)
{
_Attacked = true;
other.GetComponent().ChangeHealth(1);
StartCoroutine(ResetAttackCoroutine());
}
}
private IEnumerator ResetAttackCoroutine()
{
yield return new WaitForSeconds(_AttackCooldown);
_Attacked = false;
}
}
Animatie Keyframes
Timeline & ClipsVoor de introductie-sequentie zijn specifieke animatie-keyframes gebruikt die de startposities van de speler en de spoken afstemmen.