void Start() { // get the transform of the main camera if (Camera.main != null) { cam = Camera.main.transform; } else { Debug.LogWarning("Where's your main camera?!"); } _detectionRadius = transform.GetComponentInChildren<DetectionRadius> (); }
// A manual way to change a target. I use this for having an AI // character randomly change their target to someone who attacked them if they // don't have them targeted already. public void ChangeTarget(Transform newTarget) { _charAttacking.TargetedCharacter = newTarget; // AI players also retarget the same way human players do. if(!_charStatus.IsEnemy) Manager_Targeting.instance.TargetACharacter(_charStatus.PlayerNumber, _charAttacking); if (newTarget) // Make sure the target is not null just in case. { targetCharStatus = newTarget.GetComponent<CharacterStatus>(); targetDetRadius = targetCharStatus.detectionRadius; this.targetForNavMesh = newTarget; } }
// Find our nearest target, whether it be a player, enemy, or item, based // on what state we are currently in and what is available. Transform FindNearestTarget() { Transform nearestTarget = null; if( (aiState != AIStates.Pursue_Item && ( (!IsEnemy && Manager_Targeting.instance.enemyTargets.Count == 0) || (IsEnemy && Manager_Targeting.instance.playerTargets.Count == 0) ) ) || (aiState == AIStates.Pursue_Item && (detectionRadius == null || detectionRadius.inRangeItems.Count == 0 && detectionRadius.itemStorersInRange.Count == 0))) { if(aiState == AIStates.Pursue_Item) aiState = AIStates.Pursue; // If we were pursuing an item, there were none nearby so pursue again. return null; } // Setup our correct target list to check from. float shortestSoFar = 100; List<Transform> targets = Manager_Targeting.instance.playerTargets; if(aiState == AIStates.Pursue_Item) { // Put the names of all of your healing items in that Any() and All() parts I have // since that checks for healing items. You can just put a part of // their name. They will only attempt to go after those if their // health isn't maxed. If any are not healing, they will go after any of the // ones that aren't healing then using All to make sure the item's name is not in _healingItemNames. // You can check below in the foreach loop where we check for dist < shortestSoFar if(detectionRadius.inRangeItems.Count > 0 && ( (_charStatus.Stats[0] < _charStatus.Stats[1] && detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.Any(itemName => item.name.Contains(itemName)) ) ) || (detectionRadius.inRangeItems.Any(item => item != null && _healingItemNames.All(itemName => !item.name.Contains(itemName)) ) )) ) targets = detectionRadius.inRangeItems; else if(detectionRadius.itemStorersInRange.Count > 0) targets = detectionRadius.itemStorersInRange; else { // No need to pursue item then. This stuff is here just in case we // reach here. aiState = AIStates.Wander; targetForNavMesh = null; return null; } } else // Not pursuing an item. { // For players to target enemies. if(!IsEnemy) targets = Manager_Targeting.instance.enemyTargets; } foreach(Transform curTarget in targets) { if(curTarget != null) { // Just another check seeing if an item checking doesn't have a parent. // Detection radius already does this but double checks can be good. // If a character is what we are looking at, we make sure they are // alive. if(((curTarget.tag == "Player" || curTarget.tag == "Enemy") && curTarget.GetComponent<CharacterStatus>().Stats[0] > 0) || (curTarget.tag == "ItemStorer" || (curTarget.tag == "Item" && curTarget.parent == null))) { if(curTarget.tag == "Item" && curTarget.GetComponent<Base_Item>().ItemType == Base_Item.ItemTypes.Collectable) { // If we are checking an item and we have less than // 90% health left and the item is a collectable, we will // go for that right away. if(_charStatus.Stats[0] < _charStatus.Stats[1] * 0.9f) { nearestTarget = curTarget; break; } } float dist = Vector3.Distance(transform.position, curTarget.position); // Here we check to see that the distance checking is less than the shortest so far. // Then we see if the curTarget is not an item, or if it is, we see that we have less than // max health and the curTarget is a healing item, otherwise, we simply check that it is not // a healing item. if(dist < shortestSoFar && (curTarget.tag != "Item" || ( (_charStatus.Stats[0] < _charStatus.Stats[1] && _healingItemNames.Any(itemName => curTarget.name.Contains(itemName) ) ) || (_healingItemNames.All(itemName => !curTarget.name.Contains(itemName) ) ) ) ) ) { shortestSoFar = dist; nearestTarget = curTarget; } } } } if(nearestTarget != null) { if(nearestTarget.tag == "Player" || nearestTarget.tag == "Enemy") { // We now have a targeted character. _charAttacking.TargetedCharacter = nearestTarget; // AI players also retarget the same way human players do. if(gameObject.tag == "Player") Manager_Targeting.instance.TargetACharacter(_charStatus.PlayerNumber, _charAttacking); // Get references from them. targetCharStatus = nearestTarget.GetComponent<CharacterStatus>(); targetDetRadius = targetCharStatus.detectionRadius; } this.targetForNavMesh = nearestTarget; } return nearestTarget; }