Hallo, i need help with my horror game and i am having problams with having the enamy ai react to my flash and running the other way. If someone can help i would be happy.
This is my flashlight scirpt
using UnityEngine.UI; // For managing UI elements
public class Flashlight : MonoBehaviour
{
public GameObject flashlight; // Assign your flashlight GameObject in the inspector
public AudioClip flashlightSound; // Assign the sound clip in the inspector
public Slider batteryBar; // UI Slider to display battery level
private AudioSource audioSource;
private Light myLight;
public float fadeDuration = 0.5f; // Time for fading out the light
public float cooldownDuration = 2f; // Cooldown time for the flashlight
private bool isOnCooldown = false; // Tracks if the flashlight is on cooldown
private int maxBatteryCharge = 20; // Maximum flashes the battery can support
private int currentBatteryCharge; // Current battery level
public LayerMask enemyLayer; // Set this to "Enemy" or the appropriate layer in the Inspector
public float flashRadius = 10f; // Radius within which the flash affects enemies
private void FlashNearbyEnemies()
{
// Detect all enemies within the flash radius
Collider[] enemies = Physics.OverlapSphere(transform.position, flashRadius, enemyLayer);
foreach (Collider enemy in enemies)
{
// Ensure the enemy has an EnemyAI component and call the flash reaction method
EnemyAI enemyAI = enemy.GetComponent<EnemyAI>();
if (enemyAI != null)
{
enemyAI.ReactToFlash(transform.position); // Pass the flashlight's position
}
}
}
void Start()
{
currentBatteryCharge = maxBatteryCharge; // Initialize the battery level
// Get the Light component from the flashlight GameObject
myLight = flashlight.GetComponent<Light>();
if (myLight != null)
{
myLight.enabled = false; // Start with the light turned off
myLight.range = 20f; // Set the light range to 20f
}
else
{
Debug.LogError("Light component not found on the flashlight object.");
}
// Add or get the AudioSource component
audioSource = gameObject.GetComponent<AudioSource>();
if (audioSource == null)
{
audioSource = gameObject.AddComponent<AudioSource>();
}
audioSource.playOnAwake = false; // Do not play the sound on start
UpdateBatteryBar(); // Initialize the battery bar UI
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0) && !isOnCooldown && currentBatteryCharge > 0)
{
Debug.Log("Click");
if (myLight != null)
{
currentBatteryCharge--; // Decrease battery charge
UpdateBatteryBar(); // Update the battery bar
PlayFlashlightSound(); // Play sound when toggling the flashlight
StartCoroutine(ToggleLight());
}
}
}
private void PlayFlashlightSound()
{
if (flashlightSound != null && audioSource != null)
{
audioSource.clip = flashlightSound;
audioSource.Play();
}
else
{
Debug.LogWarning("AudioClip or AudioSource is missing.");
}
}
private System.Collections.IEnumerator ToggleLight()
{
isOnCooldown = true; // Set cooldown state to true
myLight.enabled = true; // Turn the light on
myLight.intensity = 40f; // Ensure full intensity
myLight.range = 20f; // Set the light range to 20f
FlashNearbyEnemies(); // Notify nearby enemies
yield return new WaitForSeconds(0.1f); // Keep the light fully on for 0.1 seconds
// Start the fade-out process
float startIntensity = myLight.intensity;
float timeElapsed = 0f;
while (timeElapsed < fadeDuration)
{
myLight.intensity = Mathf.Lerp(startIntensity, 0, timeElapsed / fadeDuration); // Fade out
timeElapsed += Time.deltaTime;
yield return null;
}
myLight.intensity = 0; // Ensure the light is fully off after fading
myLight.enabled = false; // Turn the light off
// Wait for cooldown duration before allowing reactivation
yield return new WaitForSeconds(cooldownDuration);
isOnCooldown = false; // Reset cooldown state
}
public void RechargeBattery(int chargeAmount)
{
currentBatteryCharge = Mathf.Clamp(currentBatteryCharge + chargeAmount, 0, maxBatteryCharge); // Clamp the value between 0 and maxBatteryCharge
UpdateBatteryBar(); // Update the battery UI
Debug.Log($"Battery recharged by {chargeAmount}. Current battery level: {currentBatteryCharge}/{maxBatteryCharge}");
}
private void UpdateBatteryBar()
{
if (batteryBar != null)
{
if (currentBatteryCharge > 0)
{
batteryBar.gameObject.SetActive(true); // Ensure the slider is active when there's battery
batteryBar.value = (float)currentBatteryCharge / maxBatteryCharge; // Normalize battery level
}
else
{
batteryBar.gameObject.SetActive(false); // Hide the slider when the battery is depleted
}
}
else
{
Debug.LogWarning("Battery bar UI Slider is not assigned.");
}
}
}
This is my enamy ai script
using System.Collections;
using UnityEngine;
using Unity.Burst.CompilerServices;
public class EnemyAI : MonoBehaviour
{
public Transform player; // Player reference
public float detectionRadius = 15f; // Radius to detect player
public float fieldOfViewAngle = 90f; // Field of view angle
public float chaseSpeed = 6f; // Speed when chasing
public float patrolSpeed = 3f; // Speed when patrolling
public float wanderRadius = 20f; // Maximum radius for random wandering
public float minWanderRadius = 5f; // Minimum radius for wanderin
public float searchDuration = 5f; // How long the enemy searches after losing sight of the player
private NavMeshAgent agent; // NavMeshAgent component
private bool isChasing = false; // Whether the enemy is chasing
private bool isSearching = false; // Whether the enemy is searching
private float distanceToPlayer; // Distance to the player
private float wanderTimer = 0f; // Timer to track when to pick a new random position
private Vector3 lastKnownPosition; // Last known position of the player
private float searchTimer = 0f; // Timer for the search state
void Start()
{
agent = GetComponent<NavMeshAgent>();
agent.speed = patrolSpeed;
agent.stoppingDistance = 1.0f; // Stop close to the target
}
void Update()
{
distanceToPlayer = Vector3.Distance(player.position, transform.position);
if (isChasing)
{
ChasePlayer();
}
else if (isSearching)
{
SearchForPlayer();
}
else if (CanSeePlayer())
{
StartChasing();
}
else
{
WanderRandomly();
}
}
bool CanSeePlayer()
{
// Check if the player is within detection radius
if (distanceToPlayer > detectionRadius) return false;
// Check if the player is within the field of view
Vector3 directionToPlayer = (player.position - transform.position).normalized;
float angleBetweenEnemyAndPlayer = Vector3.Angle(transform.forward, directionToPlayer);
if (angleBetweenEnemyAndPlayer < fieldOfViewAngle / 2)
{
// Check for obstacles blocking the view
if (Physics.Linecast(transform.position, player.position, out RaycastHit hit))
{
if (hit.transform == player) return true;
}
}
return false;
}
void StartChasing()
{
isChasing = true;
isSearching = false;
agent.speed = chaseSpeed;
agent.isStopped = false; // Resume movement
}
void ChasePlayer()
{
agent.SetDestination(player.position);
CheckIfArrived();
// Stop chasing if the player moves out of range
if (distanceToPlayer > detectionRadius * 1.5f)
{
isChasing = false;
isSearching = true;
lastKnownPosition = player.position;
agent.speed = patrolSpeed;
searchTimer = 0f;
}
}
void SearchForPlayer()
{
// Move to the last known position
agent.SetDestination(lastKnownPosition);
CheckIfArrived();
if (Vector3.Distance(transform.position, lastKnownPosition) < 1f)
{
searchTimer += Time.deltaTime;
// Stop searching after a set duration
if (searchTimer >= searchDuration)
{
isSearching = false;
}
}
}
void WanderRandomly()
{
if (!agent.hasPath || agent.remainingDistance < 1f)
{
// Generate a random point on the NavMesh with a min and max radius
Vector3 randomPoint = RandomNavSphere(transform.position, wanderRadius, minWanderRadius);
if (randomPoint != Vector3.zero)
{
agent.SetDestination(randomPoint);
}
}
}
Vector3 RandomNavSphere(Vector3 origin, float maxRadius, float minRadius)
{
Vector3 randomDirection;
do
{
randomDirection = Random.insideUnitSphere * maxRadius; // Generate a random point within the max radius
}
while (randomDirection.magnitude < minRadius); // Ensure it is outside the minimum radius
randomDirection += origin;
if (NavMesh.SamplePosition(randomDirection, out NavMeshHit navHit, maxRadius, NavMesh.AllAreas))
{
return navHit.position;
}
return Vector3.zero; // Return zero if no valid NavMesh point found
}
void CheckIfArrived()
{
if (agent.remainingDistance <= agent.stoppingDistance && !agent.pathPending)
{
agent.velocity = Vector3.zero; // Stop sliding
agent.isStopped = true;
}
else
{
agent.isStopped = false; // Allow movement
}
}
public void MoveToOrb(Vector3 orbPosition)
{
isChasing = false;
isSearching = false;
agent.speed = chaseSpeed;
agent.SetDestination(orbPosition);
agent.isStopped = false; // Start moving
// Continuously check if the enemy has arrived at the orb
StartCoroutine(CheckArrivalAtOrb());
}
IEnumerator CheckArrivalAtOrb()
{
while (true)
{
CheckIfArrived();
// Break the loop once the agent has stopped
if (agent.isStopped) yield break;
yield return null; // Wait for the next frame
}
}
public void ReactToFlash(Vector3 flashPosition)
{
// Interrupt any current behavior
isChasing = false;
isSearching = false;
agent.isStopped = false; // Ensure the agent can move
// Calculate the direction opposite to the flash
Vector3 directionAwayFromFlash = (transform.position - flashPosition).normalized;
// Determine a point far away in that direction
Vector3 runAwayPoint = transform.position + directionAwayFromFlash * detectionRadius;
// Check if the point is valid on the NavMesh
if (NavMesh.SamplePosition(runAwayPoint, out NavMeshHit hit, detectionRadius, NavMesh.AllAreas))
{
agent.SetDestination(hit.position);
agent.speed = chaseSpeed; // Use chase speed for running away
}
else
{
Debug.LogWarning("Failed to find a valid run-away point on the NavMesh.");
}
}
private void OnDrawGizmosSelected()
{
// Draw the detection radius
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, detectionRadius);
// Draw the wandering area
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(transform.position, wanderRadius);
// Draw the minimum wandering radius
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, minWanderRadius);
// Draw field of view
Gizmos.color = Color.blue;
Vector3 leftBoundary = Quaternion.Euler(0, -fieldOfViewAngle / 2, 0) * transform.forward;
Vector3 rightBoundary = Quaternion.Euler(0, fieldOfViewAngle / 2, 0) * transform.forward;
Gizmos.DrawRay(transform.position, leftBoundary * detectionRadius);
Gizmos.DrawRay(transform.position, rightBoundary * detectionRadius);
}
}