// STATE end ----------------------------------------------- // STATE start --------------------------------------------- void state_MoveRandomly() { if (obstacle1) { activeState = state_AvoidingObstacle; return; } if (enemyShip) { Vector3 playerShipDirection = enemyShip.transform.forward; playerShipDirection.y = 0; Vector3 ourShipDirection = transform.forward; ourShipDirection.y = 0; float angleBetweenPlayerShipDirectionAndOurShipDirection = Vector3.Angle(playerShipDirection, ourShipDirection); if (angleBetweenPlayerShipDirectionAndOurShipDirection > 90) { angleBetweenPlayerShipDirectionAndOurShipDirection = 180 - angleBetweenPlayerShipDirectionAndOurShipDirection; } if ((angleBetweenPlayerShipDirectionAndOurShipDirection <= 5) && (AIHelperFunctions.GetDistanceBetweenPerpendicular(this.gameObject, enemyShip) <= 3)) { activeState = state_Battle; return; } } //change ship direction periodically if (Time.time > changeDirectionTime) { changeDirectionTime = Time.time + RandomPeriodOfTime(); float currentShipToWindAngle = angleBetweenShipAndWind.GetCurrentShipToWindAngle(); float angle = Random.Range(-45.0f, 45.0f); Vector3 rotatedVector; if (currentShipToWindAngle - angle > 150) { rotatedVector = AIHelperFunctions.GetRotatedVector(windArea.windDirection, -150 * Mathf.Deg2Rad); } else if (currentShipToWindAngle - angle < -150) { rotatedVector = AIHelperFunctions.GetRotatedVector(windArea.windDirection, 150 * Mathf.Deg2Rad); } else { rotatedVector = AIHelperFunctions.GetRotatedVector(transform.forward, angle * Mathf.Deg2Rad); } enemyBoatController.SetNewShipDirection(rotatedVector); } }
private void Update() { if (Time.time > changeDirectiontime) { changeDirectiontime = Time.time + Random.Range(10.0f, 20.0f); float rotationAngleInDeg = Random.Range(-90.0f, 90.0f); windDirection = AIHelperFunctions.GetRotatedVector(windDirection, rotationAngleInDeg * degToRad); arrow.transform.eulerAngles = new Vector3(0, Vector3.SignedAngle(Vector3.forward, windDirection, Vector3.up), 0);; } }
// STATE end ----------------------------------------------- // STATE start --------------------------------------------- void state_GoToLastKnownPlayerShipPosition() { // START of checking the state change conditions --------------------- if (obstacle1) { activeState = state_AvoidObstacles; return; } if (playerShip) { lostPlayerLastKnownPosition = doesNotExist; activeState = state_GoToPlayerShip; return; } Vector3 towardsLostPlayerLastKnownPositionDirection = lostPlayerLastKnownPosition - transform.position; towardsLostPlayerLastKnownPositionDirection.y = 0; // if player not found near lostPlayerLastKnownPosition if (towardsLostPlayerLastKnownPositionDirection.magnitude < 20) { lostPlayerLastKnownPosition = doesNotExist; activeState = state_PlayerSearch; return; } // END of checking the state change conditions--------------- Debug.DrawLine(transform.position, lostPlayerLastKnownPosition, Color.magenta, 0.0f, true); // float angleBetweenOurShipDirectionAndTowardsLostPlayerLastKnownPositionDirection = // Vector3.SignedAngle(ourShipDirection, towardsLostPlayerLastKnownPositionDirection, Vector3.up); // Taking wind into account float angleBetweenTowardsLostPlayerLastKnownPositionDirectionAndWindDirection = Vector3.SignedAngle(towardsLostPlayerLastKnownPositionDirection, windArea.windDirection, Vector3.up); if (angleBetweenTowardsLostPlayerLastKnownPositionDirectionAndWindDirection > 150) { towardsLostPlayerLastKnownPositionDirection = AIHelperFunctions.GetRotatedVector(windArea.windDirection, -150 * Mathf.Deg2Rad); } else if (angleBetweenTowardsLostPlayerLastKnownPositionDirectionAndWindDirection < -150) { towardsLostPlayerLastKnownPositionDirection = AIHelperFunctions.GetRotatedVector(windArea.windDirection, 150 * Mathf.Deg2Rad); } enemyBoatController.SetNewShipDirection(towardsLostPlayerLastKnownPositionDirection); }
// STATE end ----------------------------------------------- // STATE start --------------------------------------------- void state_PlayerSearch() { if (obstacle1) { activeState = state_AvoidObstacles; return; } if (playerShip) { activeState = state_GoToPlayerShip; return; } //change ship direction periodically if (Time.time > changeDirectionTime) { changeDirectionTime = Time.time + RandomPeriodOfTime(); float currentShipToWindAngle = angleBetweenShipAndWind.GetCurrentShipToWindAngle(); float angle = Random.Range(-45.0f, 45.0f); Vector3 rotatedVector; if (currentShipToWindAngle - angle > 150) { rotatedVector = AIHelperFunctions.GetRotatedVector(windArea.windDirection, -150 * Mathf.Deg2Rad); } else if (currentShipToWindAngle - angle < -150) { rotatedVector = AIHelperFunctions.GetRotatedVector(windArea.windDirection, 150 * Mathf.Deg2Rad); } else { rotatedVector = AIHelperFunctions.GetRotatedVector(transform.forward, angle * Mathf.Deg2Rad); } enemyBoatController.SetNewShipDirection(rotatedVector); } }
// ========================================================= // FSM STATES // ========================================================= // STATE start --------------------------------------------- void state_AvoidObstacles() { // START of checking the state change conditions --------------------- if (!obstacle1) { if (!playerShip) { ChangeStateTo_PlayerSearch_Or_GoToLastKnownPlayerShipPosition(); return; } if (playerShip) { activeState = state_GoToPlayerShip; return; } } // END of checking the state change conditions--------------- Vector3 ourShipDirection = transform.forward; ourShipDirection.y = 0; float angleInDegToAvoidObstacle; // if there is only one obstacle if (obstacle1 && !obstacle2) { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle1, windArea, additionalRandomAngle); } else // if there are two obstacles { float angleBetweenShortestShiptToObstacle1VectorAndShipDirection = AIHelperFunctions.GetAngleBetweenShortestShiptToObstacleVectorAndShipDirection(obstacle1, transform); float angleBetweenShortestShiptToObstacle2VectorAndShipDirection = AIHelperFunctions.GetAngleBetweenShortestShiptToObstacleVectorAndShipDirection(obstacle2, transform); if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0) || (angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0)) { if (Mathf.Abs(angleBetweenShortestShiptToObstacle1VectorAndShipDirection) < Mathf.Abs(angleBetweenShortestShiptToObstacle2VectorAndShipDirection)) { angleInDegToAvoidObstacle = AIHelperFunctions.GetGreaterAngleInDegToAvoidObstacle(ourShip, obstacle1, additionalRandomAngle); } else { angleInDegToAvoidObstacle = AIHelperFunctions.GetGreaterAngleInDegToAvoidObstacle(ourShip, obstacle2, additionalRandomAngle); } } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection == 0) || (angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle1VectorAndShipDirection == 0)) { angleInDegToAvoidObstacle = 90 + additionalRandomAngle; } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection == 0) || (angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle1VectorAndShipDirection == 0)) { angleInDegToAvoidObstacle = -90 - additionalRandomAngle; } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0) || (angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0)) { if (Mathf.Abs(angleBetweenShortestShiptToObstacle1VectorAndShipDirection) < Mathf.Abs(angleBetweenShortestShiptToObstacle2VectorAndShipDirection)) { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle1, windArea, additionalRandomAngle); } else { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle2, windArea, additionalRandomAngle); } } else //such situation should not exist!!! { angleInDegToAvoidObstacle = 0; Debug.Log("Such situation should not exist!!!"); } } Vector3 rotatedVector = AIHelperFunctions.GetRotatedVector(ourShipDirection, angleInDegToAvoidObstacle * Mathf.Deg2Rad); enemyBoatController.SetNewShipDirection(rotatedVector); }
// STATE end ----------------------------------------------- // STATE start --------------------------------------------- void state_GoToPlayerShip() { // START of checking the state change conditions --------------------- if (obstacle1) { activeState = state_AvoidObstacles; return; } if (!playerShip) { Debug.Log("GoToPlayerShip ------> ChangeStateTo_PlayerSearch_Or_GoToLastKnownPosition"); ChangeStateTo_PlayerSearch_Or_GoToLastKnownPlayerShipPosition(); return; } Vector3 towardsPlayerShipDirection = playerShip.transform.position - transform.position; towardsPlayerShipDirection.y = 0; Vector3 playerShipDirection = playerShip.transform.forward; playerShipDirection.y = 0; Vector3 shipDirection = transform.forward; shipDirection.y = 0; // This check can be performed only if playerShip != null DetermineInWhichZoneIsOurShip(); ourShipDirectionIsConsistentWithTowardsPlayerShipDirection = AIHelperFunctions.IsOurShipDirectionConsistentWithTowardsOtherShipDirection(shipDirection, towardsPlayerShipDirection); if (ourShipIsInParallelZone) { if (closeToPlayerShip) { activeState = state_SailParallelToPlayerShip; return; } if (!closeToPlayerShip) { if (ourShipDirectionIsConsistentWithTowardsPlayerShipDirection) { activeState = state_SailParallelToPlayerShip; return; } } } if (ourShipIsInZoneBetweenParallelZones) { activeState = state_GoToParallelZone; return; } // END of checking the state change conditions--------------- Debug.DrawLine(transform.position, playerShip.transform.position, Color.white, 0.0f, true); // Taking wind into account float angleBetweenTowardsPlayerShipDirectionAndWindDirection = Vector3.SignedAngle(towardsPlayerShipDirection, windArea.windDirection, Vector3.up); if (angleBetweenTowardsPlayerShipDirectionAndWindDirection > 150) { towardsPlayerShipDirection = AIHelperFunctions.GetRotatedVector(windArea.windDirection, -150 * Mathf.Deg2Rad); } else if (angleBetweenTowardsPlayerShipDirectionAndWindDirection < -150) { towardsPlayerShipDirection = AIHelperFunctions.GetRotatedVector(windArea.windDirection, 150 * Mathf.Deg2Rad); } enemyBoatController.SetNewShipDirection(towardsPlayerShipDirection); }
// ========================================================= // FSM STATES // ========================================================= // STATE start --------------------------------------------- void state_AvoidingObstacle() { if (!obstacle1) { activeState = state_MoveRandomly; return; } // if (!obstacle1) { // if (!playerShip) { // activeState = state_PlayerSearching; // return; // } else { // activeState = state_GoToPlayerShip; // return; // } // } // Vector3 shipPosition = transform.position; Vector3 shipDirection = transform.forward; float angleInDegToAvoidObstacle; if (obstacle1 && !obstacle2) { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle1, windArea, additionalRandomAngle); } else { float angleBetweenShortestShiptToObstacle1VectorAndShipDirection = AIHelperFunctions.GetAngleBetweenShortestShiptToObstacleVectorAndShipDirection(obstacle1, transform); float angleBetweenShortestShiptToObstacle2VectorAndShipDirection = AIHelperFunctions.GetAngleBetweenShortestShiptToObstacleVectorAndShipDirection(obstacle2, transform); if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0) || (angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0)) { if (Mathf.Abs(angleBetweenShortestShiptToObstacle1VectorAndShipDirection) < Mathf.Abs(angleBetweenShortestShiptToObstacle2VectorAndShipDirection)) { angleInDegToAvoidObstacle = AIHelperFunctions.GetGreaterAngleInDegToAvoidObstacle(ourShip, obstacle1, additionalRandomAngle); } else { angleInDegToAvoidObstacle = AIHelperFunctions.GetGreaterAngleInDegToAvoidObstacle(ourShip, obstacle2, additionalRandomAngle); } } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection == 0) || (angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle1VectorAndShipDirection == 0)) { angleInDegToAvoidObstacle = 90 + 20; } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection == 0) || (angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle1VectorAndShipDirection == 0)) { angleInDegToAvoidObstacle = -90 - 20; } else if ((angleBetweenShortestShiptToObstacle1VectorAndShipDirection > 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection > 0) || (angleBetweenShortestShiptToObstacle1VectorAndShipDirection < 0 && angleBetweenShortestShiptToObstacle2VectorAndShipDirection < 0)) { if (Mathf.Abs(angleBetweenShortestShiptToObstacle1VectorAndShipDirection) < Mathf.Abs(angleBetweenShortestShiptToObstacle2VectorAndShipDirection)) { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle1, windArea, additionalRandomAngle); } else { angleInDegToAvoidObstacle = AIHelperFunctions.GetAngleInDegToAvoidObstacle(ourShip, obstacle2, windArea, additionalRandomAngle); } } else { angleInDegToAvoidObstacle = 0; Debug.Log("Such situation should not exist!!!"); } } Vector3 rotatedVector = AIHelperFunctions.GetRotatedVector(shipDirection, angleInDegToAvoidObstacle * Mathf.Deg2Rad); enemyBoatController.SetNewShipDirection(rotatedVector); }