Working on lession 29

This commit is contained in:
2026-04-02 16:20:38 +01:00
parent 72ae178fd1
commit 76dc783914
16735 changed files with 6083173 additions and 183 deletions

View File

@@ -1,6 +1,10 @@
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
public enum TargetType { Gate, Wall, Tower, Any }
public class EnemyController : MonoBehaviour
{
public float moveSpeed;
@@ -8,8 +12,7 @@ public class EnemyController : MonoBehaviour
public float attackRange;
public float attackSpeed;
public float attackDamage;
public float health;
public Transform defaultTarget;
public TargetType targetType;
public Transform target;
private NavMeshAgent navMeshAgent;
private Animator animator;
@@ -27,18 +30,18 @@ public class EnemyController : MonoBehaviour
void Start()
{
MoveToDefault();
GetTarget(targetType);
}
void Update()
{
if(target != null && !target.gameObject.activeInHierarchy)
if (target != null && !target.gameObject.activeInHierarchy)
{
target = null;
MoveToDefault();
GetTarget(targetType);
}
if(target != null)
if (target != null)
Attack();
animator.SetFloat("Speed", navMeshAgent.velocity.magnitude);
@@ -46,11 +49,11 @@ public class EnemyController : MonoBehaviour
private void OnTriggerEnter(Collider other)
{
if(target != null) return;
if(!other.CompareTag("Gate")) return;
if (target != null) return;
if (!other.CompareTag("Gate")) return;
AttackPoint attackPoint = other.GetComponentInChildren<AttackPoint>();
if(attackPoint != null)
if (attackPoint != null && targetType == TargetType.Any)
{
target = attackPoint.transform;
navMeshAgent.stoppingDistance = attackRange;
@@ -58,17 +61,65 @@ public class EnemyController : MonoBehaviour
}
}
private void MoveToDefault()
private void GetTarget(TargetType targetType)
{
navMeshAgent.stoppingDistance = 0f;
if(defaultTarget != null)
navMeshAgent.destination = defaultTarget.position;
GameObject[] potentialTargets;
GameObject closest = null;
float minDistance = Mathf.Infinity;
switch (targetType)
{
case TargetType.Gate:
potentialTargets = GameObject.FindGameObjectsWithTag("Gate");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Wall:
potentialTargets = GameObject.FindGameObjectsWithTag("Wall");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Tower:
potentialTargets = GameObject.FindGameObjectsWithTag("Tower");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Any:
potentialTargets = GameObject.FindGameObjectsWithTag("Gate")
.Concat(GameObject.FindGameObjectsWithTag("Wall"))
.Concat(GameObject.FindGameObjectsWithTag("Tower")).ToArray();
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
}
if (closest != null)
{
AttackPoint attackPoint = closest.GetComponentInChildren<AttackPoint>();
if (attackPoint != null)
{
target = attackPoint.transform;
navMeshAgent.stoppingDistance = attackRange;
navMeshAgent.destination = target.position;
}
}
}
private void Attack()
{
attackCooldown -= Time.deltaTime;
if(Vector3.Distance(target.position, transform.position) < attackRange && attackCooldown <= 0f)
if (Vector3.Distance(target.position, transform.position) < attackRange && attackCooldown <= 0f)
{
transform.LookAt(target.position);
animator.SetTrigger("Attack");
@@ -78,7 +129,7 @@ public class EnemyController : MonoBehaviour
}
}
private void OnDrawGizmosSelected()
/*private void OnDrawGizmosSelected()
{
// Target range — green if priority target is assigned, red if not
Gizmos.color = target != null ? Color.green : Color.red;
@@ -88,5 +139,5 @@ public class EnemyController : MonoBehaviour
bool inAttackRange = target != null && Vector3.Distance(target.position, transform.position) < attackRange;
Gizmos.color = inAttackRange ? Color.green : Color.red;
Gizmos.DrawWireSphere(transform.position, attackRange);
}
}*/
}

View File

@@ -1,16 +0,0 @@
using UnityEngine;
public class EnemyDetector : MonoBehaviour
{
private EnemyController enemyController;
void Awake()
{
enemyController = GetComponentInParent<EnemyController>();
}
private void OnTriggerEnter(Collider other)
{
enemyController.OnDetectorTriggerEnter(other);
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 137b6d86a1dcfa94b84dee4c8c248fab

View File

@@ -0,0 +1,23 @@
using UnityEngine;
public class EnemyHealthController : MonoBehaviour
{
[SerializeField] float totalHealth;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void TakeDamage(float damageToTake)
{
totalHealth -= damageToTake;
if(totalHealth <= 0)
Destroy(gameObject);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 005e302fe21ff164985e65ea087d083c

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 357db81f8fc0d2a40a68189df6a4d203
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using System;
using UnityEngine;
public class Projectile : MonoBehaviour
{
private Rigidbody theRB;
[SerializeField] private float moveSpeed;
[SerializeField] private float damageAmount;
[SerializeField] private GameObject impactEffect;
void Awake()
{
theRB = GetComponent<Rigidbody>();
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
theRB.linearVelocity = transform.forward * moveSpeed;
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter(Collider other)
{
if(other.tag == "Enemy")
{
other.GetComponent<EnemyHealthController>().TakeDamage(damageAmount);
Instantiate(impactEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
void OnBecameVisible()
{
Destroy(gameObject);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 84b12942bc65a07418ae0012c4b99995

View File

@@ -0,0 +1,70 @@
using Unity.Mathematics;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering;
public class ProjectileTower : MonoBehaviour
{
private Tower theTower;
[SerializeField] GameObject projectile;
[SerializeField] Transform firePoint;
[SerializeField] float minTimeBetweenShot = 2f;
[SerializeField] float maxTimeBetweenShot = 6f;
private Transform target;
[SerializeField] private Transform launcherModel;
[SerializeField] private GameObject shotEffect;
private float shotCounter;
void Awake()
{
theTower = GetComponentInParent<Tower>();
}
void Start()
{
shotCounter = UnityEngine.Random.Range(minTimeBetweenShot, maxTimeBetweenShot);
}
void Update()
{
shotCounter -= Time.deltaTime;
if (shotCounter <= 0f && target != null)
{
Vector3 directionToTarget = (target.position - firePoint.position).normalized;
Quaternion aimRotation = Quaternion.LookRotation(directionToTarget);
Instantiate(projectile, firePoint.position, aimRotation);
shotCounter = UnityEngine.Random.Range(minTimeBetweenShot, maxTimeBetweenShot);
}
if (theTower.enemiesUpdated)
{
if (theTower.enemiesInRange.Count > 0)
{
float minDistance = theTower.range * 1f;
foreach (EnemyController enemy in theTower.enemiesInRange)
{
if (enemy != null)
{
float distance = Vector3.Distance(enemy.transform.position, transform.position);
if (distance < minDistance)
{
minDistance = distance;
target = enemy.transform;
}
}
}
}
else
{
target = null;
}
}
}
void LateUpdate()
{
if (target != null)
{
launcherModel.rotation = Quaternion.Slerp(launcherModel.rotation, Quaternion.LookRotation(target.position - transform.position), 5f * Time.deltaTime);
launcherModel.rotation = Quaternion.Euler(0f, launcherModel.rotation.eulerAngles.y, 0f);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4e4085db6b1775b4b8304ef40f7d802d

View File

@@ -0,0 +1,43 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public class Tower : MonoBehaviour
{
public float range;
[SerializeField] private float attackSpeed;
[SerializeField] private float attackDamage;
[SerializeField] private LayerMask whatIsEnemy;
private Collider[] collidersInRange;
public List<EnemyController> enemiesInRange = new List<EnemyController>();
private float checkCounter;
[SerializeField] private float checkTime = .2f;
[HideInInspector] public bool enemiesUpdated;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
checkCounter = checkTime;
}
// Update is called once per frame
void Update()
{
enemiesUpdated = false;
checkCounter -= Time.deltaTime;
if (checkCounter <= 0f)
{
checkCounter = checkTime;
collidersInRange = Physics.OverlapSphere(transform.position, range, whatIsEnemy);
enemiesInRange.Clear();
foreach (Collider collider in collidersInRange)
{
if (collider.gameObject.GetComponent<EnemyController>() != null)
{
enemiesInRange.Add(collider.GetComponent<EnemyController>());
}
}
enemiesUpdated = true;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c877527d90d3a5b4d879a153b810fcfe