private void checkEnemies() { // If the sight range is negative, do nothing. if (SightRange <= 0) { return; } // Add the passed time to the time since the last check. timeSinceLastSightCheck += Time.fixedDeltaTime; if (timeSinceLastSightCheck >= TimeBetweenSightChecks) { // Finds all creature colliders in the area around this creature. int seenCreaturesCount = Physics.OverlapSphereNonAlloc(eyeOrigin.position, SightRange, seenColliders, 1 << LayerMask.NameToLayer("Creatures")); // Clear the seen enemies list and fill it with all enemies in the colliders collection. seenEnemies.Clear(); for (int i = 0; i < seenCreaturesCount; i++) { if (seenColliders[i] != null && seenColliders[i].TryGetComponent(out Creature creature) && creature.Player != Creature.Player) { seenEnemies.Add(new CreatureTarget() { Target = creature, TargetRigidbody = creature.GetComponent <Rigidbody>(), TargetCollider = seenColliders[i], NormalisedDistance = NeuralNetworkHelper.ExpandRangeToNegative(Vector3.Distance(eyeOrigin.position, seenColliders[i].ClosestPoint(eyeOrigin.position)) / SightRange), NormalisedHealth = NeuralNetworkHelper.ExpandRangeToNegative(creature.Health / maxHealth) }); } } // Sort the enemies based on the score using the mutated filters. seenEnemies.Sort((firstEnemy, secondEnemy) => { // Calculate the scores for both enemies. float firstScore = (float)Math.Tanh(Bias + firstEnemy.NormalisedHealth * HealthWeight + firstEnemy.NormalisedDistance * DistanceWeight); float secondScore = (float)Math.Tanh(Bias + secondEnemy.NormalisedHealth * HealthWeight + secondEnemy.NormalisedDistance * DistanceWeight); // Return the result of the compare function. return(firstScore.CompareTo(secondScore)); }); // Set the max concurrent seen creatures if the number of seen creatures is higher than the old value. setLifetimeStat("MaxConcurrentSeenCreatures", (uint)Math.Max(LifetimeStats["MaxConcurrentSeenCreatures"], seenEnemies.Count)); // If enemies were seen, take the last one (the one with the highest score) and set the current target to it, otherwise set the current target to null. CurrentTarget = (seenEnemies.Count > 0) ? seenEnemies[seenEnemies.Count - 1] : (CreatureTarget?)null; if (seenCreaturesCount == seenColliders.Length) { Array.Resize(ref seenColliders, seenColliders.Length + 10); } // Reset the timer. timeSinceLastSightCheck = 0; } }
private void handleAttackLogic() { // Add the elapsed time to the attack timer. timeSinceLastAttack += Time.fixedDeltaTime; // If the creature has a target, attempt to move towards it. if (targetingBehaviour.HasCurrentTarget) { CreatureTarget creatureTarget = targetingBehaviour.CurrentTarget.Value; // Stop moving. movementBehaviour.StopMoving(); // Face the target. transform.LookAt(creatureTarget.Transform); // If it has been long enough since the last attack, attack again. if (timeSinceLastAttack >= AttackInterval && creatureTarget.Target.IsAlive) { // Calculate the power of the throw. float power = Mathf.Clamp01(PowerBias + creatureTarget.NormalisedHealth * PowerHealthWeight + creatureTarget.NormalisedDistance * PowerDistanceWeight); // Calculate the pitch of the throw. float pitch = Mathf.Clamp(PitchBias + creatureTarget.NormalisedDistance * PitchDistanceWeight + NeuralNetworkHelper.ExpandRangeToNegative(creatureTarget.TargetRigidbody.velocity.magnitude / 1000) * PitchSpeedWeight + power * PitchPowerWeight, -1, 1); // Calculate the yaw of the throw. float yaw = Mathf.Clamp(YawBias + creatureTarget.NormalisedDistance * YawDistanceWeight + power * YawPowerWeight + NeuralNetworkHelper.ExpandRangeToNegative(creatureTarget.TargetRigidbody.velocity.magnitude / 1000) * YawSpeedWeight, -1, 1); // Calcualte the normalised direction to the target, then the angles (in degrees) from that. Vector3 direction = Quaternion.LookRotation((creatureTarget.Transform.position - transform.position).normalized).eulerAngles; direction.y += yaw * Mathf.Clamp(YawDeviation, 0, 180); direction.x += pitch * Mathf.Clamp(PitchDeviation, 0, 180); // Create a new spear. GameObject spearObject = Instantiate(projectilePrefab.gameObject, heldWeapon.position, Quaternion.Euler(direction), Creature.ProjectileContainer); //spearObject.transform.position = heldWeapon.position; spearObject.transform.localScale = Vector3.Scale(heldWeapon.localScale, transform.localScale); // Get the projectile component from the created spear. Projectile spearProjectile = spearObject.GetComponent <Projectile>(); spearProjectile.InitialiseProjectile(onProjectileHitEnemy, Creature, creatureTarget.Target, creatureTarget.Transform.position, spearObject.transform.position); // Add the force to the spear. spearProjectile.Rigidbody.AddForce(spearObject.transform.forward * (power + 1) * MaxPower, ForceMode.Impulse); // Increment the thrown shots counter. thrownShots++; // Reset the attack timer. timeSinceLastAttack = 0; } } // Otherwise, just move towards the goal. else { movementBehaviour.SetTarget(Creature.GoalObject); movementBehaviour.StoppingDistance = 0; } }