// ----------- PlayerController.
cs -----------
using UnityEngine;
public class PlayerController : MonoBehaviour
public float moveSpeed = 5f;
public float jumpForce = 5f;
public Transform weaponHolder;
private CharacterController controller;
private float gravity = -9.81f;
private float verticalVelocity;
private Weapon currentWeapon;
void Start()
controller = GetComponent<CharacterController>();
void Update()
Move();
if (Input.GetMouseButtonDown(0) && currentWeapon != null)
{
currentWeapon.Shoot();
void Move()
float moveX = Input.GetAxis("Horizontal");
float moveZ = Input.GetAxis("Vertical");
Vector3 move = transform.right * moveX + transform.forward * moveZ;
controller.Move(move * moveSpeed * Time.deltaTime);
if (controller.isGrounded)
verticalVelocity = -1f;
if (Input.GetButtonDown("Jump"))
verticalVelocity = jumpForce;
else
verticalVelocity += gravity * Time.deltaTime;
}
controller.Move(new Vector3(0, verticalVelocity, 0) * Time.deltaTime);
public void EquipWeapon(Weapon weapon)
if (currentWeapon != null)
Destroy(currentWeapon.gameObject);
currentWeapon = Instantiate(weapon, weaponHolder.position, weaponHolder.rotation,
weaponHolder);
public Weapon GetCurrentWeapon()
return currentWeapon;
// ----------- WeaponPickup.cs -----------
using UnityEngine;
public class WeaponPickup : MonoBehaviour
public Weapon weaponPrefab;
void OnTriggerEnter(Collider other)
if (other.CompareTag("Player"))
PlayerController player = other.GetComponent<PlayerController>();
if (player != null)
player.EquipWeapon(weaponPrefab);
Destroy(gameObject);
// ----------- WeaponData.cs (ScriptableObject) -----------
using UnityEngine;
[CreateAssetMenu(fileName = "NewWeaponData", menuName = "Weapons/WeaponData")]
public class WeaponData : ScriptableObject
public string weaponName;
public GameObject weaponModel;
public int maxAmmo;
public float damage;
public float fireRate;
public float range;
public AudioClip shootSound;
public AudioClip reloadSound;
public ParticleSystem muzzleFlash;
// ----------- Weapon.cs -----------
using UnityEngine;
public class Weapon : MonoBehaviour
public WeaponData weaponData;
protected int currentAmmo;
protected float nextTimeToFire = 0f;
protected Camera fpsCam;
protected AudioSource audioSource;
protected virtual void Start()
currentAmmo = weaponData.maxAmmo;
fpsCam = Camera.main;
audioSource = GetComponent<AudioSource>();
if (weaponData.muzzleFlash != null)
weaponData.muzzleFlash.Stop();
}
public virtual void Shoot()
if (Time.time < nextTimeToFire) return;
if (currentAmmo <= 0)
Debug.Log("Out of ammo!");
return;
nextTimeToFire = Time.time + weaponData.fireRate;
currentAmmo--;
if (weaponData.muzzleFlash != null)
weaponData.muzzleFlash.Play();
if (weaponData.shootSound != null)
audioSource.PlayOneShot(weaponData.shootSound);
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit,
weaponData.range))
HealthSystem target = hit.transform.GetComponent<HealthSystem>();
if (target != null)
{
target.TakeDamage(weaponData.damage);
public void Reload()
currentAmmo = weaponData.maxAmmo;
if (weaponData.reloadSound != null)
audioSource.PlayOneShot(weaponData.reloadSound);
public int GetCurrentAmmo()
return currentAmmo;
// ----------- Shotgun.cs -----------
using UnityEngine;
public class Shotgun : Weapon
public int pellets = 6;
public float spreadAngle = 10f;
public override void Shoot()
if (Time.time < nextTimeToFire) return;
if (currentAmmo <= 0)
Debug.Log("Out of ammo!");
return;
nextTimeToFire = Time.time + weaponData.fireRate;
currentAmmo--;
if (weaponData.muzzleFlash != null)
weaponData.muzzleFlash.Play();
if (weaponData.shootSound != null)
audioSource.PlayOneShot(weaponData.shootSound);
for (int i = 0; i < pellets; i++)
Vector3 spread = fpsCam.transform.forward;
spread.x += Random.Range(-spreadAngle, spreadAngle) * 0.01f;
spread.y += Random.Range(-spreadAngle, spreadAngle) * 0.01f;
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, spread, out hit, weaponData.range))
HealthSystem target = hit.transform.GetComponent<HealthSystem>();
if (target != null)
target.TakeDamage(weaponData.damage);
// ----------- HealthSystem.cs -----------
using UnityEngine;
using UnityEngine.SceneManagement;
public class HealthSystem : MonoBehaviour
public float maxHealth = 100f;
[HideInInspector] public float currentHealth;
void Start()
{
currentHealth = maxHealth;
public void TakeDamage(float amount)
currentHealth -= amount;
if (currentHealth <= 0)
Die();
void Die()
if (gameObject.CompareTag("Player"))
Debug.Log("Player Died! Game Over!");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
else
Destroy(gameObject);
}
// ----------- EnemyAI.cs -----------
using UnityEngine;
using UnityEngine.AI;
public class EnemyAI : MonoBehaviour
public NavMeshAgent agent;
public Transform player;
public Weapon enemyWeapon;
public float shootRange = 15f;
private HealthSystem health;
void Start()
agent = GetComponent<NavMeshAgent>();
health = GetComponent<HealthSystem>();
if (player == null)
player = GameObject.FindGameObjectWithTag("Player").transform;
void Update()
if (health == null || player == null) return;
float distance = Vector3.Distance(transform.position, player.position);
if (distance > shootRange)
agent.isStopped = false;
agent.SetDestination(player.position);
else
agent.isStopped = true;
transform.LookAt(player);
if (enemyWeapon != null)
enemyWeapon.Shoot();
// ----------- SafeZone.cs -----------
using UnityEngine;
public class SafeZone : MonoBehaviour
{
public float shrinkSpeed = 0.1f;
public float minRadius = 5f;
private SphereCollider zoneCollider;
void Start()
zoneCollider = GetComponent<SphereCollider>();
void Update()
if (zoneCollider.radius > minRadius)
zoneCollider.radius -= shrinkSpeed * Time.deltaTime;
void OnTriggerStay(Collider other)
if (other.CompareTag("Player") || other.CompareTag("Enemy"))
// Inside safe zone - no damage
}
}
void OnTriggerExit(Collider other)
if (other.CompareTag("Player") || other.CompareTag("Enemy"))
HealthSystem health = other.GetComponent<HealthSystem>();
if (health != null)
health.TakeDamage(Time.deltaTime * 5); // Damage outside safe zone
// ----------- PlayerUI.cs -----------
using UnityEngine;
using UnityEngine.UI;
public class PlayerUI : MonoBehaviour
public Slider healthBar;
public Text ammoText;
public Text weaponNameText;
private HealthSystem playerHealth;
private Weapon currentWeapon;
void Start()
playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<HealthSystem>();
healthBar.maxValue = playerHealth.maxHealth;
healthBar.value = playerHealth.maxHealth;
void Update()
healthBar.value = playerHealth.currentHealth;
PlayerController playerController =
GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
currentWeapon = playerController.GetCurrentWeapon();
if (currentWeapon != null)
ammoText.text = $"{currentWeapon.GetCurrentAmmo()} /
{currentWeapon.weaponData.maxAmmo}";
weaponNameText.text = currentWeapon.weaponData.weaponName;
else
{
ammoText.text = "No Weapon";
weaponNameText.text = "";