void StatusUpdate() { int hitsInPerson = 0; targetTransformInSight = null; foreach (RaycastHit hit in eyes.hits) { if (hit.transform && hit.transform.tag == "Player") { hitsInPerson++; targetTransformInSight = hit.transform; shootTarget = targetTransformInSight.FindChild("ShootTarget"); if (!shootTarget) { shootTarget = targetTransformInSight; } } } animator.SetLookAtWeight(lookWeight); float lookWeightFinal = 0; // If it is idle time after shooting some intruder if (idleAfterShootingTimeCounter > 0) { sawOrHeardTargetPerson = false; status = Status.Idle; } // If see or hear a person else if (hitsInPerson > 0 || ears.hearSteps) { if (hitsInPerson > 0) { targetPosition = targetTransformInSight.position; lookWeightFinal = 1f; } else if (ears.hearSteps) { targetPosition = ears.soundSourcePosition; } sawOrHeardTargetPerson = true; status = Status.Following; agent.speed = runSpeed; alertSign.AttachTo(new Vector3(targetPosition.x, 0, targetPosition.z)); visionCone.status = FOV2DVisionCone.Status.Alert; } lookWeight = Mathf.Lerp(lookWeight, lookWeightFinal, Time.deltaTime * 3f); if (shootTarget) { animator.SetLookAtPosition(shootTarget.position); } // Use a state machine for a behaviour actions of our "AI". // Idle if (status == Status.Idle) { if (waypointManager.TargetPoint) { float distanceToTargetWaypoint = Vector3.Distance(waypointManager.TargetPoint.transform.position, transform.position); // Go to the base point if not yet there if (distanceToTargetWaypoint > 1.5f) { targetPosition = waypointManager.TargetPoint.transform.position; status = Status.Following; } else { waypointManager.SetNextPoint(); } } agent.speed = walkSpeed; alertSign.Detach(); visionCone.status = FOV2DVisionCone.Status.Idle; } // Following the target position else if (status == Status.Following) { float distanceToTarget = Vector3.Distance(targetPosition, transform.position); // If close enought to shoot a laser beam in the target person if (distanceToTarget <= shootDistance && targetTransformInSight && lookWeight >= 0.9f) { targetTransformInSight.gameObject.SendMessage("Shot"); idleAfterShootingTimeCounter = idleTimeAfterShooting; } // If the target position has reached else if (distanceToTarget < 1.5f) { // Follow the target agent.destination = transform.position; // If previously saw the target person if (sawOrHeardTargetPerson) { status = Status.Searching; sawOrHeardTargetPerson = false; } // If still searching for the target person else if (searchTimeCurrent > 0) { status = Status.Searching; } else { status = Status.Idle; } } // Go for the target position else { // If found the target or the searching time has expired if (sawOrHeardTargetPerson && searchTimeCurrent > 0) { searchTimeCurrent = 0; visionCone.status = FOV2DVisionCone.Status.Idle; } else if (searchTimeCurrent >= searchTime) { searchTimeCurrent = 0; status = Status.Idle; } // If the searching timer on — add new delta-time to it else if (searchTimeCurrent > 0) { searchTimeCurrent += Time.deltaTime; } // Follow the target position agent.destination = targetPosition; } } // Searching for the target person else if (status == Status.Searching) { // If the searching time has expired if (searchTimeCurrent >= searchTime) { status = Status.Idle; searchTimeCurrent = 0; } else { if (searchTimeCurrent == 0) { centerOfSearchArea = targetPosition + (transform.forward * searchRadius); } searchTimeCurrent += Time.deltaTime; NavMeshPath newPath = new NavMeshPath();; int maxAttempts = 100; int attempts = 0; // Find a new random target position in the radius. do { targetPosition = new Vector3( centerOfSearchArea.x + Random.Range(-searchRadius, searchRadius), centerOfSearchArea.y, centerOfSearchArea.z + Random.Range(-searchRadius, searchRadius)); attempts++; if (attempts >= maxAttempts) { targetPosition = transform.position; break; } } // The target position should be accessible on the NavMesh while(agent.CalculatePath(targetPosition, newPath) == false); agent.destination = targetPosition; status = Status.Following; alertSign.AttachTo(new Vector3(targetPosition.x, 0, targetPosition.z)); } } }