8. Shooting

Raycast

        // Check for left mouse button click
        if (Input.GetButtonDown("Fire1"))
        {
            // Call the Shoot() function from the Shooting script
            shooting.Shoot();
        }
using UnityEngine;
using System.Collections.Generic;

public class Shooting : MonoBehaviour
{
    public Transform crosshair;
    public float shootRange = 100f;

    public void Shoot()
    {
        // Calculate the direction from the player to the crosshair
        Vector3 shootDirection = crosshair.position - transform.position;

        // Cast a ray in the shoot direction
        RaycastHit hit;
        if (Physics.Raycast(transform.position, shootDirection, out hit, shootRange))
        {
            // Handle hit event
            Debug.Log("Hit " + hit.collider.gameObject.name);
        }
    }
}

Decals (bullet holes in walls)

    void InstantiateDecal(Vector3 position, Vector3 normal, Transform hitTransform)
    {
        // Determine the rotation to align with the surface
        Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normal);

        // Instantiate the decal prefab
        GameObject decal = Instantiate(decalPrefab, position, rotation);

        // Adjust the decal's position slightly to prevent z-fighting
        decal.transform.position += normal * 0.01f;

        // Parent the decal to the hit object to keep it in the correct position
        decal.transform.parent = hitTransform;
    }
using UnityEngine;

public class DecalDestroyer : MonoBehaviour
{
    public float lifespan = 5f; // Lifespan of the decal in seconds

    private float creationTime; // Time when the decal was instantiated

    void Start()
    {
        // Record the time when the decal was instantiated
        creationTime = Time.time;
    }

    void Update()
    {
        // Check if the decal has exceeded its lifespan
        if (Time.time - creationTime >= lifespan)
        {
            // Destroy the decal
            Destroy(gameObject);
        }
    }
}
using UnityEngine;
using System.Collections.Generic;

public class Shooting : MonoBehaviour
{
    public Transform crosshair;
    public float shootRange = 100f;
    public GameObject decalPrefab; // Prefab for the bullet hole decal
    public int maxDecals = 10; // Maximum number of decals allowed

    private List<GameObject> instantiatedDecals = new List<GameObject>();

    public void Shoot()
    {
        // Calculate the direction from the player to the crosshair
        Vector3 shootDirection = crosshair.position - transform.position;

        // Cast a ray in the shoot direction
        RaycastHit hit;
        if (Physics.Raycast(transform.position, shootDirection, out hit, shootRange))
        {
            // Handle hit event
            Debug.Log("Hit " + hit.collider.gameObject.name);
            InstantiateDecal(hit.point, hit.normal, hit.transform);
        }
    }

    void InstantiateDecal(Vector3 position, Vector3 normal, Transform hitTransform)
    {
        // Determine the rotation to align with the surface
        Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normal);

        // Instantiate the decal prefab
        GameObject decal = Instantiate(decalPrefab, position, rotation);

        // Adjust the decal's position slightly to prevent z-fighting
        decal.transform.position += normal * 0.01f;

        // Parent the decal to the hit object to keep it in the correct position
        decal.transform.parent = hitTransform;

        // Add the decal to the list of instantiated decals
        instantiatedDecals.Add(decal);

        // Ensure that only the newest decals are kept
        RemoveOldDecals();
    }

    void RemoveOldDecals()
    {
        // If the number of decals exceeds the maximum limit
        if (instantiatedDecals.Count > maxDecals)
        {
            // Calculate the number of excess decals
            int excessDecals = instantiatedDecals.Count - maxDecals;

            // Remove the oldest excess decals from the list and destroy them
            for (int i = 0; i < excessDecals; i++)
            {
                GameObject decal = instantiatedDecals[0]; // Get the oldest decal
                instantiatedDecals.RemoveAt(0); // Remove it from the list
                Destroy(decal); // Destroy the GameObject
            }
        }
    }

    // Draw the raycast for visualization
    private void OnDrawGizmos()
    {
        Debug.DrawRay(transform.position, (crosshair.position - transform.position) * shootRange, Color.red);
    }
}

Check if shot

using UnityEngine;

public class ShotController : MonoBehaviour
{
    public void Shot()
    {
        Debug.Log("I have been shot!");
    }
}
            // Check if the hit object has a ShotController component
            ShotController shotController = hit.collider.gameObject.GetComponent<ShotController>();
            if (shotController != null)
            {
                // Call the Shot method of the ShotController
                shotController.Shot();
            }

Barrel explosion

using UnityEngine;

public class ShotController : MonoBehaviour
{
    public void Shot()
    {
        if (gameObject.CompareTag("ExplosiveBarrel"))
        {
            Explode();
        }
        else if (gameObject.CompareTag("Character"))
        {
            TakeDamage();
        }
        else
        {
            Debug.LogWarning("Object does not have a recognized tag for shot behavior.");
        }
    }

    void Explode()
    {
        Debug.Log("Barrel exploded!");
    }

    void TakeDamage()
    {
        Debug.Log("Took damage!");
    }
}
using UnityEngine;

public class WallExplosionTriggerController : MonoBehaviour
{
    public float explosionForce = 180f;

    public void WallExplosion(GameObject barrel)
    {
        // Get all Rigidbody components in children (pieces of the wall)
        Rigidbody[] rigidbodies = GetComponentsInChildren<Rigidbody>();

        foreach (Rigidbody rb in rigidbodies)
        {
            // Enable physics simulation
            rb.isKinematic = false;

            // Calculate the direction away from the explosion point
            Vector3 explosionDirection = rb.transform.position - barrel.transform.position;

            // Apply force to each Rigidbody piece
            rb.AddForce(explosionDirection.normalized * explosionForce / (explosionDirection.magnitude*explosionDirection.magnitude), ForceMode.Impulse);
        }
    }
}
using UnityEngine;

public class BarrelState : MonoBehaviour
{
    public GameObject explosiveAreaTrigger;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("ExplosionArea"))
        {
            explosiveAreaTrigger = other.gameObject; // Store reference to the trigger GameObject
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("ExplosionArea"))
        {
            explosiveAreaTrigger = null; // Clear reference to the trigger GameObject
        }
    }
}
    void Explode()
    {
        Debug.Log("Barrel exploded!");
        // Check if the barrel is in the explosive area and trigger GameObject reference is not null
        BarrelState barrelState = GetComponent<BarrelState>();
        if (barrelState != null && barrelState.explosiveAreaTrigger != null)
        {
            // Call explosion method from the trigger GameObject
            barrelState.explosiveAreaTrigger.GetComponent<WallExplosionTriggerController>().WallExplosion(gameObject);
        }
        Destroy(gameObject);
    }

Enemy, HP

using UnityEngine;

public class HealthSystem : MonoBehaviour
{
    public float HP = 100f;

    public void TakeDamage(float dmgValue)
    {
        HP = HP - dmgValue;
        if (HP <= 0)
        {
            Death();
        }
    }

    private void Death()
    {
        Debug.Log("Died");
        Destroy(gameObject);
    }
}
    void TakeDamage()
    {
        HealthSystem healthSystem = GetComponent<HealthSystem>();
        if (healthSystem != null)
        {
            healthSystem.TakeDamage(25);
        }
    }
< ^ >