private void OnTriggerStay(Collider other) { if (_stateMachine.Health.IsDead) { return; } bool enemyOrPlayerThreatInSight = false; // This is for potential threats if (other.CompareTag("Player") || other.CompareTag("Enemy")) { if (_angryAt.Count == 0) { goto NotAngryAtAnyoneInSight; } // First check if we are angry at the potential target GameObject potentialTargetObject = _angryAt.Find(potentialTarget => potentialTarget == other.gameObject); if (potentialTargetObject == null) { goto NotAngryAtAnyoneInSight; } // If we are already seeing a player or enemy and the target we just saw is a different one, then we don't do anything if (_stateMachine.CurrentTarget != null && _stateMachine.CurrentTarget.TargetTransform.gameObject != other.gameObject && (_stateMachine.CurrentTarget.Type == AITargetType.Player || _stateMachine.CurrentTarget.Type == AITargetType.Enemy)) { return; } // At this point, we are only interacting with either the target that we already have as a target or a new one (since we don't have a target at all) RaycastHit hitInfo; if (Physics.Raycast(transform.position, (other.transform.position + Vector3.up) - transform.position, out hitInfo, _sphereCollider.radius, _seeablesMask)) { if (hitInfo.transform.gameObject == other.gameObject) { float angle = Vector3.Angle(transform.forward, (other.transform.position + Vector3.up) - transform.position); if (angle <= _fieldOfView) { _stateMachine.SetTarget(other.transform, AITargetType.Player); enemyOrPlayerThreatInSight = true; } } } // Resetting target for when the player or the enemy is inside the scanner collider but not inside the field of view // If we were seeing the player or the enemy and no longer see him, then we reset the target after the tolerance time if (_stateMachine.CurrentTarget != null && _stateMachine.CurrentTarget.Type == AITargetType.Player && !enemyOrPlayerThreatInSight) { _targetOutOfSightTime += Time.deltaTime; if (_targetOutOfSightTime >= _targetOutOfSightTolerance) { _targetOutOfSightTime = 0f; _stateMachine.ResetTarget(); } } } if (enemyOrPlayerThreatInSight) { return; } NotAngryAtAnyoneInSight: if (other.CompareTag("AIVehicleDetector") && (_stateMachine.CurrentTarget == null || _stateMachine.CurrentTarget.Type != AITargetType.Vehicle) && _stateMachine.CurrentState.GetStateType() != AIState.AIStateType.Vehicle) { InteractiveVehicle interactiveVehicle = other.GetComponent <InteractiveVehicle>(); if (interactiveVehicle != null && !interactiveVehicle.Occupied) { AIStateVehicle aiStateDriving = (AIStateVehicle)(_stateMachine.GetState(AIState.AIStateType.Vehicle)); if ((aiStateDriving.WantToDrive && interactiveVehicle.DriverSeat) || (aiStateDriving.WantToBePassenger && !interactiveVehicle.DriverSeat)) { _stateMachine.SetTarget(other.transform, AITargetType.Vehicle); return; } } } if (other.CompareTag("Chair") && (_stateMachine.CurrentTarget == null || _stateMachine.CurrentTarget.Type != AITargetType.Chair) && _stateMachine.CurrentState.GetStateType() != AIState.AIStateType.Sitting) { InteractiveChair interactiveChair = other.GetComponent <InteractiveChair>(); if (interactiveChair != null && !interactiveChair.IsOccupied) { AIStateSitting aiStateDriving = (AIStateSitting)(_stateMachine.GetState(AIState.AIStateType.Sitting)); if (aiStateDriving.IsTired) { _stateMachine.SetTarget(other.transform, AITargetType.Chair); return; } } } // For social Interaction if (other.CompareTag("Enemy")) { // if we are already interacting socially, then there is nothing to do here if (_stateMachine.CurrentTarget != null && _stateMachine.CurrentTarget.Type == AITargetType.Friend) { return; } AIStateMachine otherStateMachine = other.GetComponent <AIStateMachine>(); AIStateSocialInteraction mySocialInteractionState = (AIStateSocialInteraction)(_stateMachine.GetState(AIState.AIStateType.SocialInteraction)); AIStatePursuit myPursuitState = (AIStatePursuit)(_stateMachine.GetState(AIState.AIStateType.Pursuit)); AIStateSocialInteraction friendSocialInteractionState = (AIStateSocialInteraction)(otherStateMachine.GetState(AIState.AIStateType.SocialInteraction)); AIStatePursuit friendPursuitState = (AIStatePursuit)(otherStateMachine.GetState(AIState.AIStateType.Pursuit)); if (mySocialInteractionState.IsFeelingLonely && friendSocialInteractionState.IsFeelingLonely && !otherStateMachine.Health.IsDead) { // If the friend hasn't gotten into social mode yet by setting a target of type friend, then we are the ones who are going to be making the first move if (otherStateMachine.CurrentTarget == null || otherStateMachine.CurrentTarget.Type == AITargetType.None || otherStateMachine.CurrentTarget.Type == AITargetType.NavigationPoint || otherStateMachine.CurrentTarget.Type == AITargetType.BoomBox) { myPursuitState.ShouldMakeAMove = true; mySocialInteractionState.FriendSocialInteraction = friendSocialInteractionState; // We set our pursuit mode by setting a target _stateMachine.SetTarget(other.transform, AITargetType.Friend); // the friend should instantly get into social mode friendSocialInteractionState.FriendSocialInteraction = mySocialInteractionState; otherStateMachine.SetTarget(transform, AITargetType.Friend); otherStateMachine.SwitchState(AIState.AIStateType.SocialInteraction); } } } if (other.CompareTag("BoomBox")) { // If we have a more important target: Another AI Agent as an enemy, a friend or a player, then we ignore the boombox if (_stateMachine.CurrentTarget != null && (_stateMachine.CurrentTarget.Type == AITargetType.Player || _stateMachine.CurrentTarget.Type == AITargetType.Enemy || _stateMachine.CurrentTarget.Type == AITargetType.Friend)) { return; } AIStateDancing aiStateDancing = (AIStateDancing)(_stateMachine.GetState(AIState.AIStateType.Dancing)); if (aiStateDancing.IsHungry) { _stateMachine.SetTarget(other.transform, AITargetType.BoomBox); } } }
private void OnTriggerStay(Collider other) { bool playerInSight = false; bool foodInSight = false; if (other.CompareTag("Player") || other.CompareTag("Food")) { RaycastHit hitInfo; float upCoeffecient = other.CompareTag("Player") ? 1 : 0; Debug.DrawRay(transform.position, (other.transform.position + Vector3.up * upCoeffecient) - transform.position, Color.red); if (Physics.Raycast(transform.position, (other.transform.position + Vector3.up * upCoeffecient) - transform.position, out hitInfo, _sphereCollider.radius, LayerMask.GetMask("EnemyThreat", "Default", "Gravel", "Wood", "Grass", "Metal"))) { if (hitInfo.transform.gameObject == other.gameObject) { float angle = Vector3.Angle(transform.forward, (other.transform.position + Vector3.up * upCoeffecient) - transform.position); if (angle <= _fieldOfView) { // We have the player directly in sight if (other.CompareTag("Player")) { _stateMachine.SetTarget(other.transform, AITargetType.Player); playerInSight = true; } if (other.CompareTag("Food")) { // We only start feeding when there is no other target in sight // or when the target is neither a player neither a sound if (_stateMachine.CurrentTarget == null || (_stateMachine.CurrentTarget != null && _stateMachine.CurrentTarget.Type != AITargetType.Player && _stateMachine.CurrentTarget.Type != AITargetType.Sound)) { // We need to check if we are hungry AIState state = _stateMachine.GetState(AIState.AIStateType.Feeding); if (state != null) { AIStateFeeding stateFeeding = (AIStateFeeding)state; if (stateFeeding.IsHungry) { _stateMachine.SetTarget(other.transform, AITargetType.Food); foodInSight = true; } } } } } } } } // We shouldn't detect our own sound if (other.CompareTag("Sound") && _stateMachine.AISoundManager.SoundEmitter.gameObject != other.gameObject) { if (_stateMachine.CurrentTarget == null || _stateMachine.CurrentTarget != null && (_stateMachine.CurrentTarget.Type == AITargetType.Food || _stateMachine.CurrentTarget.Type == AITargetType.NavigationPoint || _stateMachine.CurrentTarget.Type == AITargetType.None)) { _stateMachine.SetTarget(other.transform, AITargetType.Sound); } } if (_stateMachine.CurrentTarget != null) { // If we were seeing the player and no longer see him, then we reset the target if (other.CompareTag("Player") && !playerInSight && _stateMachine.CurrentTarget.Type == AITargetType.Player) { _stateMachine.ResetTarget(); } // If we aren't seeing the player nor are we seeing the food and the previous target was food, then we reset the target // Food is the least prioritary out of all targets if (other.CompareTag("Food") && !foodInSight && _stateMachine.CurrentTarget.Type == AITargetType.Food) { _stateMachine.ResetTarget(); } } }