dissertation / mainCode / Enemy / EnemyManager.cs
EnemyManager.cs
Raw
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Security.Cryptography;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;

public class EnemyManager : MonoBehaviour
{
    // Interfaces
    public GameObject player;
    public GameObject leftView, rightView, playerLeft, playerRight, playerTop, playerCenter;
    public CameraMovement cameraMovement;
    public Vector3 playerPosition;
    public Vector3 headHeight;
    public Transform head;
    public GameManager gameManager;
    public AudioSource gunshot;
    public LineRenderer lineRenderer;
    private TargetDamageable targetDamageable;
    private LearningEngine learningEngine;
    private GunHandler gunHandler;
    public GameObject feet;
    private GameObject playerFeet;
    public GameObject gunBarrel;
    public Image healthBar;
    
    // constants set by gamemanager
    private float minFireRate;
    private float maxFireRate;
    public float damage;
    private float aimModifier;
    public float health;
    private float noticeRate;
    private float speed;
    
    // flags
    private bool firstView;
    private bool firstDamage;
    public bool moving;
    private Vector3 startPoint;
    private Vector3 moveTo;
    private Rigidbody rigidbody;
    private float startTime;
    private bool readyToMove = false;
    
    // trackers
    private float timeOfEngagementStart;
    private float timeOfFirstDamage;
    private float damageDealt;
    private float timeOfNextShot;
    private Vector3 playerDirectionAtStart;
    private Vector3 playerDirectionAtKill;

    public int id;
    
    void Start()
    {
        // configure constants
        gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
        gunshot = GetComponent<AudioSource>();
        targetDamageable = GetComponent<TargetDamageable>();
        lineRenderer = GetComponent<LineRenderer>();
        lineRenderer.startColor = Color.white;
        lineRenderer.endColor = Color.white;
        lineRenderer.enabled = false;
        learningEngine = GameObject.Find("GameManager").GetComponent<LearningEngine>();
        rigidbody = GetComponent<Rigidbody>();
        
        
        firstView = true;
        firstDamage = true;
        startTime = Time.time;

        id = Random.Range(0, int.MaxValue);
        moving = Random.Range(0, 4) == 0; // 25% chance to be moving
        
        
    }

    // Update is called once per frame
    void Update()
    {
        if (!readyToMove && Time.time - startTime > 0.5f)
        {
            readyToMove = true;
            if (moving)
            {
            
                var pointFound = false;
                startPoint = transform.position;
                while (!pointFound)
                {
                    var relativeChange = new Vector3(Random.Range(-5, 5), 0, Random.Range(-5, 5));
                    moveTo = startPoint + relativeChange;
                    if (!Physics.Linecast(startPoint, moveTo))
                    {
                        pointFound = true;
                    }
                }
            
            
            }
        }
        head = transform.Find("headhitbox").transform;
        headHeight = head.position;
        if (moving && PlayerPrefs.GetInt("playerTrackingEnabled") == 1 && readyToMove)
        {
            rigidbody.position = Vector3.Lerp(startPoint, moveTo, Mathf.PingPong(Time.time, speed));
            transform.position = rigidbody.position;
        }
        
        healthBar.fillAmount = (targetDamageable.health / targetDamageable.maxHealth);
        
        if (player == null)
        {
            player = GameObject.FindGameObjectWithTag("Player");
            cameraMovement = player.GetComponentInChildren<CameraMovement>();
            gunHandler = player.GetComponentInChildren<GunHandler>();
            playerFeet = GameObject.Find("playerFeet");
            playerCenter = GameObject.Find("playerCenterView");
            playerLeft = GameObject.Find("playerLeftView");
            playerRight = GameObject.Find("playerRightView");
            playerTop = GameObject.Find("playerTopView");
        }

        playerPosition = player.transform.position;
        if (CanSeePlayer())
        {
            if (firstView)
            {
                timeOfNextShot = Time.time + noticeRate;
                timeOfEngagementStart = Time.time;
                firstView = false;
                learningEngine.StartEngagement(this);
                learningEngine.ReportAmmo(gunHandler.ammoInClip);
                learningEngine.ReportHeightDifference(this, playerFeet.transform.position.y - feet.transform.position.y);
                playerDirectionAtStart = cameraMovement.transform.forward;
                
            }
            if (Time.time > timeOfNextShot)
            {
                ShootPlayer();
            }

        }

        if (!firstView)
        {
            // run every time once engagement has started
            if (targetDamageable.health < 100 && firstDamage)
            {
                firstDamage = false;
                timeOfFirstDamage = Time.time;
                gameManager.ReportTimeToDamage(timeOfFirstDamage - timeOfEngagementStart, this);
            }
        }
        
    }

    public void AddHit()
    {
        
    }

    public void ReportDeath()
    {
        gameManager.ReportHealthLoss(damageDealt, this);
        gameManager.ReportTimeToKill(Time.time - timeOfEngagementStart, this);
        
        // learning engine report crosshair movement
        playerDirectionAtKill = cameraMovement.transform.forward;
        var xMovement = Vector3.Angle(new Vector3(playerDirectionAtStart.x, 0, playerDirectionAtStart.z),
            new Vector3(playerDirectionAtKill.x, 0, playerDirectionAtKill.z));
        var yMovement = Vector3.Angle(new Vector3(0, playerDirectionAtStart.y, playerDirectionAtStart.z),
            new Vector3(0, playerDirectionAtKill.y, playerDirectionAtKill.z));
        learningEngine.ReportCrosshairMovement(this, xMovement, yMovement);
        learningEngine.EndEngagement(this);
    }

    bool CanSeePlayer()
    {
        var mePositions = new[] {leftView.transform.position, rightView.transform.position};
        var playerPositions = new[] {playerCenter.transform.position, playerLeft.transform.position,
            playerRight.transform.position, playerTop.transform.position};

        bool hitPlayer = false;
        foreach (var mePos in mePositions)
        {
            foreach (var playerPos in playerPositions)
            {
                if (!Physics.Linecast(mePos, playerPos))
                {
                    hitPlayer = true;
                }
            }
        }

        return hitPlayer;
    }

    IEnumerator DrawLine(Vector3 start, Vector3 end)
    {
        Color c = lineRenderer.material.color;
        lineRenderer.SetPosition(0, start);
        lineRenderer.SetPosition(1, end);
        lineRenderer.enabled = true;
        for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
        {
            c.a = alpha;
            lineRenderer.material.color = c;
            yield return null;
        }

        lineRenderer.enabled = false;
    }

    void ShootPlayer()
    {
        AudioSource.PlayClipAtPoint(gunshot.clip, transform.position);
        float spread = aimModifier;
        Vector3 randomDir = new Vector3(Random.Range(-spread, spread), Random.Range(-spread, spread), Random.Range(-spread, spread));
        Vector3 sprayDir = head.TransformVector(randomDir);
        Vector3 dir = (playerPosition - headHeight).normalized;
        RaycastHit hit;
        if (Physics.Raycast(headHeight, dir + sprayDir, out hit))
        {
            StartCoroutine(DrawLine(gunBarrel.transform.position, hit.transform.position));
            if (hit.collider.gameObject.CompareTag("Player"))
            {
                damageDealt += damage;
                gameManager.DealDamage((int) damage);
                learningEngine.ReportDamageSource(this);
            }
        }
        
        timeOfNextShot = Time.time + minFireRate + Random.Range(0f, maxFireRate);

    }

    public void SetConstants()
    {
        if (gameManager == null)
        {
            gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
        }

        if (targetDamageable == null)
        {
            targetDamageable = GetComponent<TargetDamageable>();
        }
        noticeRate = gameManager.enemyNoticeRate;
        damage = gameManager.enemyDamage;
        minFireRate = gameManager.enemyFireRate;
        aimModifier = gameManager.enemyAimModifier;
        health = gameManager.enemyHealth;
        maxFireRate = gameManager.enemyMaxFireRate;
        targetDamageable.maxHealth = gameManager.enemyHealth;
        targetDamageable.health = gameManager.enemyHealth;
        speed = gameManager.enemySpeed;
    }
    
}