2365 lines
71 KiB
C#
2365 lines
71 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.UIElements;
|
|
|
|
public class AINavMesh : MonoBehaviour
|
|
{
|
|
[Header ("Main Settings")]
|
|
[Space]
|
|
|
|
public float walkSpeed = 1;
|
|
|
|
public float targetChangeTolerance = 1;
|
|
|
|
public float patrolSpeed;
|
|
|
|
[Space]
|
|
|
|
public float maxDistanceToRecalculatePath = 1;
|
|
|
|
public bool smoothSpeedWhenCloseToTarget = true;
|
|
|
|
public float updateNavMeshPositionRate = 0.5f;
|
|
|
|
public float updateNavMeshPositionRate2_5d = 0.6f;
|
|
|
|
public float calculatePathRate = 0.5f;
|
|
|
|
public bool getClosestPositionIfTargetCantBeReached = true;
|
|
|
|
public bool ignoreLookAtTargetDirection;
|
|
|
|
[Space]
|
|
|
|
public float minDistanceToTargetNotVisibleMultiplier = 0.5f;
|
|
public float minDistanceToTargetNotVisibleClamp = 1.5f;
|
|
|
|
public bool useMinDistanceOffsetItTargetReached;
|
|
public float currentDistanceToTargetOffset;
|
|
|
|
[Space]
|
|
[Header ("Regular Min Distances Settings")]
|
|
[Space]
|
|
|
|
public float minDistanceToFriend;
|
|
public float minDistanceToEnemy;
|
|
public float minDistanceToObjects;
|
|
|
|
public float minDistanceToMoveBack;
|
|
|
|
[Space]
|
|
[Header ("Jump Settings")]
|
|
[Space]
|
|
|
|
public bool checkOffMeshLinkJumpsEnabled = true;
|
|
|
|
public bool checkDistanceOnOffMeshLink;
|
|
|
|
public float minDistanceOnOffMeshLink;
|
|
|
|
public bool checkHorizontalDistanceOnOffMeshLink;
|
|
|
|
public float minHorizontalDistanceOnOffMeshLink;
|
|
|
|
public bool checkVerticalDistanceOnOffMeshLink;
|
|
|
|
public float minVerticalDistanceOnOffMeshLink;
|
|
|
|
public bool adjustJumpPowerToDistance = true;
|
|
|
|
public float regularJumpPower = 6;
|
|
|
|
public float maxJumpPower = 15;
|
|
|
|
public float jumpMultiplierPercentage = 0.5f;
|
|
|
|
[Space]
|
|
[Header ("Run From Target Settings")]
|
|
[Space]
|
|
|
|
public float minDistanceToRunFromTarget = 10;
|
|
|
|
[Space]
|
|
[Header ("Inital Target Settings")]
|
|
[Space]
|
|
|
|
public bool setInitialTarget;
|
|
public Transform initialTargetTransform;
|
|
public bool setMainPlayerAsTarget;
|
|
|
|
[Space]
|
|
[Header ("Partner Settings")]
|
|
[Space]
|
|
|
|
public string addAIToFriendListManagerEventName = "Add AI To Friend List Manager";
|
|
public string removeAIToFriendListManagerEventName = "Remove AI From Friend List Manager";
|
|
|
|
public bool checkToLeaveSpaceToPartner;
|
|
public float minDistanceWithPartner;
|
|
public float maxDistanceToReturnWithPartner;
|
|
|
|
public bool addAIAsPlayerPartner = true;
|
|
|
|
[Space]
|
|
[Header ("Guide Partner Settings")]
|
|
[Space]
|
|
|
|
public float maxDistanceToPartnerWhenGuidingHim = 10;
|
|
public float targetToGuideOutOfRangeLerpSpeed = 10;
|
|
public float distanceOffsetToSetGuideBackToRange = 1;
|
|
public bool returnToTargetToGuideWhenOutOfRange;
|
|
public float maxDistanceToReturnToTargetToGuide;
|
|
|
|
[Space]
|
|
[Header ("Dynamic Obstacle Detection Settings")]
|
|
[Space]
|
|
|
|
public bool useDynamicObstacleDetection;
|
|
public LayerMask dynamicObstacleLayer;
|
|
public float dynamicAvoidSpeed = 4;
|
|
public float dynamicRaycastDistanceForward = 3;
|
|
public float dynamicRaycastDistanceDiagonal = 0.5f;
|
|
public float dynamicRaycastDistanceSides = 1;
|
|
public float dynamicRaycastDistanceAround = 4;
|
|
|
|
public bool useDynamicObstacleWhenTargetIsEnemyEnabled = true;
|
|
|
|
public bool checkCustomListToIgnoreOnDynamicObstacleEnabled;
|
|
|
|
public bool checkForExtraCollidersOnOwnerIfDetected;
|
|
|
|
[Space]
|
|
|
|
public float minObstacleRotation = 45;
|
|
public float mediumObstacleRotation = 65;
|
|
public float maximumObstacleRotation = 85;
|
|
|
|
[Space]
|
|
[Header ("Event Settings")]
|
|
[Space]
|
|
|
|
public UnityEvent eventToPauseAI;
|
|
public UnityEvent eventToResumeAI;
|
|
|
|
public UnityEvent eventOnPartnerFound;
|
|
|
|
public UnityEvent eventOnDeath;
|
|
|
|
public UnityEvent eventOnAlive;
|
|
|
|
[Space]
|
|
[Header ("AI State")]
|
|
[Space]
|
|
|
|
public Transform currentTarget;
|
|
|
|
public bool targetIsFriendly;
|
|
public bool targetIsObject;
|
|
|
|
public bool navMeshPaused;
|
|
public bool patrolling;
|
|
public bool patrollingPaused;
|
|
|
|
public bool attacking;
|
|
public bool following;
|
|
public bool waiting;
|
|
public bool hiding;
|
|
|
|
public bool followingTarget;
|
|
|
|
public bool usingSamplePosition;
|
|
|
|
public bool checkingToResumeNavmesh;
|
|
|
|
public bool onGround;
|
|
|
|
public bool canReachCurrentTarget;
|
|
|
|
public float currentDistanceToTarget;
|
|
|
|
public float currentMinDistance;
|
|
|
|
public bool useCustomMinDistance;
|
|
public float customMinDistance;
|
|
|
|
public bool followingPartner;
|
|
|
|
public bool partnerLocated;
|
|
|
|
public bool leavingSpaceToPartner;
|
|
|
|
public bool AIDead;
|
|
|
|
public bool moveNavMeshPaused;
|
|
|
|
public bool moveNavMeshPausedDuringAction;
|
|
|
|
public float navSpeed = 1;
|
|
|
|
public bool useCustomNavMeshSpeed;
|
|
public float customNavMeshSpeed;
|
|
|
|
public bool strafeModeActive;
|
|
|
|
public AINavMeshMoveInfo AIMoveInput = new AINavMeshMoveInfo ();
|
|
|
|
public Vector3 desiredVelocity;
|
|
|
|
public bool useHalfMinDistance;
|
|
|
|
public bool runFromTarget;
|
|
|
|
public bool rangeToTargetReached;
|
|
|
|
public bool turnBasedCombatActionActive;
|
|
|
|
public bool locked2_5dModeActive;
|
|
public bool moveInXAxisOn2_5dMode;
|
|
|
|
[Space]
|
|
[Header ("Dynamic Obstacle Debug")]
|
|
[Space]
|
|
|
|
public bool obstacleOnForward;
|
|
public bool obstacleOnRight;
|
|
public bool obstacleOnLeft;
|
|
public bool obstacleOnRightForward;
|
|
public bool obstacleOnLeftForward;
|
|
|
|
public int numberOfObstacleDirectionDetected;
|
|
|
|
public float obstacleDistance;
|
|
|
|
public bool obstacleDetected;
|
|
|
|
[Space]
|
|
|
|
public GameObject lastObstacleDetected;
|
|
|
|
public List<GameObject> objectListToIgnoreOnDynamicObstacle = new List<GameObject> ();
|
|
|
|
[Space]
|
|
[Header ("Path Corners Debug")]
|
|
[Space]
|
|
|
|
public List<Vector3> pathCorners = new List<Vector3> ();
|
|
|
|
[Space]
|
|
[Header ("Guide Target Debug")]
|
|
[Space]
|
|
|
|
public bool guidingPartnerActive;
|
|
public bool partnerToGuideOnRange;
|
|
public float currentDistanceToPartnerToGuide;
|
|
public bool returningToTargetToGuideActive;
|
|
public Transform currentPositionTransformToGuide;
|
|
|
|
public Transform temporalTargetPositionTransform;
|
|
|
|
[Space]
|
|
[Header ("Debug Settings")]
|
|
[Space]
|
|
|
|
public bool showDynamicObstacleDebugPrint;
|
|
|
|
public bool pauseMovementToTarget;
|
|
|
|
public bool showDebugPrint;
|
|
public bool showMoveInputDebugPrint;
|
|
|
|
public bool showSetAgentDestinationDebugPrint;
|
|
|
|
[Space]
|
|
[Header ("Gizmo Settings")]
|
|
[Space]
|
|
|
|
public bool showGizmo;
|
|
public bool showPathRenderer;
|
|
|
|
[Space]
|
|
[Header ("Element Settings")]
|
|
[Space]
|
|
|
|
public NavMeshAgent agent;
|
|
public playerController playerControllerManager;
|
|
public playerCamera playerCameraManager;
|
|
|
|
public Transform rayCastPosition;
|
|
public GameObject AIGameObject;
|
|
|
|
public Transform AITransform;
|
|
|
|
Vector3 currentTargetPosition;
|
|
Color currentLineRendererColor = Color.white;
|
|
|
|
//OffMeshLinkData _currLink;
|
|
bool lookingPathAfterJump;
|
|
|
|
float lastTimeJumpDetected;
|
|
|
|
LineRenderer lineRenderer;
|
|
bool lineRendererAdded;
|
|
bool lineRendererActive;
|
|
|
|
Transform partner;
|
|
Vector3 targetOffset;
|
|
|
|
float originalMinDistanceToFriend;
|
|
float originalMinDistanceToEnemy;
|
|
|
|
Vector3 lastTargetPosition;
|
|
NavMeshPath currentNavMeshPath;
|
|
|
|
NavMeshPathStatus currentNavMeshPathStatus;
|
|
|
|
Vector3 lastPathTargetPosition;
|
|
NavMeshHit hit;
|
|
Vector3 currentDestinationPosition;
|
|
Vector3 samplePosition;
|
|
float positionOffset = 0.1f;
|
|
Coroutine waitToResumeCoroutine;
|
|
float lastTimeCalculatePath;
|
|
float lastTimeUpdateNavMeshPosition;
|
|
|
|
Vector3 currentPosition;
|
|
Vector3 targetCurrentPosition;
|
|
|
|
Vector3 targetTransformUp;
|
|
|
|
Vector3 currentUp;
|
|
Vector3 currentForward;
|
|
|
|
remoteEventSystem partnerRemoteEventSystem;
|
|
|
|
RaycastHit rayhit;
|
|
|
|
bool moveToRight = true;
|
|
|
|
Vector3 avoidDirection;
|
|
|
|
Vector3 currentCheckObstalceDirection;
|
|
|
|
Vector3 newMoveDirection;
|
|
Vector3 currentMoveDirection;
|
|
|
|
bool checkForPartnerToGuidDistance;
|
|
Vector3 lastMoveDirection;
|
|
|
|
bool originalUseDynamicObstacleDetection;
|
|
|
|
Vector3 currentMovementDirection;
|
|
bool calculateMoveValueWithDirectionToTargetActive;
|
|
|
|
bool warpPositionAssigned;
|
|
|
|
bool moveToTargetActive;
|
|
|
|
Vector3 Vector3Zero = Vector3.zero;
|
|
|
|
Vector3 Vector3Up = Vector3.up;
|
|
|
|
float originalAIWalkSpeed;
|
|
|
|
int pathCornersCount;
|
|
|
|
Vector3 currentNavmeshOffLinkEndPos = Vector3.zero;
|
|
|
|
bool initialTargetChecked;
|
|
|
|
bool ignoreGetClosestPositionIfTargetCantBeReached;
|
|
|
|
bool useExtraColliderList;
|
|
|
|
List<Collider> extraColliderList = new List<Collider> ();
|
|
|
|
Collider mainCollider;
|
|
|
|
|
|
public virtual void Start ()
|
|
{
|
|
if (AIGameObject == null) {
|
|
AIGameObject = gameObject;
|
|
}
|
|
|
|
AITransform = AIGameObject.transform;
|
|
|
|
if (showPathRenderer) {
|
|
addLineRendererGizmo ();
|
|
}
|
|
|
|
originalMinDistanceToFriend = minDistanceToFriend;
|
|
originalMinDistanceToEnemy = minDistanceToEnemy;
|
|
|
|
originalUseDynamicObstacleDetection = useDynamicObstacleDetection;
|
|
|
|
agent.Warp (AITransform.position);
|
|
|
|
originalAIWalkSpeed = walkSpeed;
|
|
}
|
|
|
|
void Update ()
|
|
{
|
|
if (!navMeshPaused) {
|
|
|
|
if (!initialTargetChecked) {
|
|
if (setInitialTarget) {
|
|
Transform newTarget = initialTargetTransform;
|
|
|
|
if (setMainPlayerAsTarget) {
|
|
newTarget = GKC_Utils.findMainPlayerTransformOnScene ();
|
|
}
|
|
|
|
if (newTarget != null) {
|
|
setTarget (newTarget);
|
|
}
|
|
}
|
|
|
|
initialTargetChecked = true;
|
|
}
|
|
|
|
if (onGround) {
|
|
if (lookingPathAfterJump) {
|
|
if (Time.time > lastTimeJumpDetected + 0.6f) {
|
|
lookingPathAfterJump = false;
|
|
|
|
jumpEnded ();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (checkingToResumeNavmesh) {
|
|
if (onGround) {
|
|
agent.isStopped = false;
|
|
checkingToResumeNavmesh = false;
|
|
usingSamplePosition = false;
|
|
|
|
return;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (guidingPartnerActive && !returningToTargetToGuideActive && !attacking && (targetIsFriendly || targetIsObject)) {
|
|
if (currentPositionTransformToGuide != null && (currentTarget == null || currentTarget != currentPositionTransformToGuide)) {
|
|
setTarget (currentPositionTransformToGuide);
|
|
}
|
|
}
|
|
|
|
if (currentTarget != null && agent.enabled) {
|
|
|
|
if (partnerLocated) {
|
|
if (currentTarget == partner) {
|
|
followingPartner = true;
|
|
} else {
|
|
followingPartner = false;
|
|
}
|
|
} else {
|
|
followingPartner = false;
|
|
}
|
|
|
|
currentPosition = AITransform.position;
|
|
|
|
targetCurrentPosition = currentTarget.position;
|
|
|
|
targetTransformUp = currentTarget.up;
|
|
|
|
currentDistanceToTarget = GKC_Utils.distance (targetCurrentPosition, currentPosition);
|
|
|
|
if (followingPartner) {
|
|
|
|
if (checkToLeaveSpaceToPartner) {
|
|
|
|
if (currentDistanceToTarget < minDistanceWithPartner) {
|
|
|
|
if (!leavingSpaceToPartner) {
|
|
|
|
bool temporalPositionFound = false;
|
|
|
|
float randomDirection = Random.Range (0, 2);
|
|
|
|
if (randomDirection == 1) {
|
|
randomDirection = 1;
|
|
} else {
|
|
randomDirection = -1;
|
|
}
|
|
|
|
Vector3 temporalPosition = partner.position + (3 * randomDirection) * partner.right + 1.5f * partner.forward;
|
|
|
|
updateCurrentNavMeshPath (temporalPosition);
|
|
|
|
if (temporalTargetPositionTransform == null) {
|
|
GameObject newTemporalTargetPositionGameObject = new GameObject ();
|
|
newTemporalTargetPositionGameObject.name = "Temporal Target Position Transform";
|
|
|
|
temporalTargetPositionTransform = newTemporalTargetPositionGameObject.transform;
|
|
}
|
|
|
|
currentNavMeshPathStatus = currentNavMeshPath.status;
|
|
|
|
if (currentNavMeshPath != null && currentNavMeshPathStatus == NavMeshPathStatus.PathComplete) {
|
|
temporalTargetPositionTransform.position = temporalPosition;
|
|
|
|
temporalPositionFound = true;
|
|
} else {
|
|
temporalPosition = partner.position - (3 * randomDirection) * partner.right + 1.5f * partner.forward;
|
|
|
|
updateCurrentNavMeshPath (temporalPosition);
|
|
|
|
if (currentNavMeshPath != null && currentNavMeshPathStatus == NavMeshPathStatus.PathComplete) {
|
|
temporalTargetPositionTransform.position = temporalPosition;
|
|
|
|
temporalPositionFound = true;
|
|
}
|
|
}
|
|
|
|
if (temporalPositionFound) {
|
|
leavingSpaceToPartner = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (leavingSpaceToPartner) {
|
|
targetCurrentPosition = temporalTargetPositionTransform.position;
|
|
|
|
targetTransformUp = temporalTargetPositionTransform.up;
|
|
|
|
if (currentDistanceToTarget > maxDistanceToReturnWithPartner || GKC_Utils.distance (targetCurrentPosition, currentPosition) < 0.3f) {
|
|
leavingSpaceToPartner = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (patrolling) {
|
|
currentTargetPosition = targetCurrentPosition + positionOffset * targetTransformUp;
|
|
|
|
setFollowingTargetState (true);
|
|
|
|
if (patrollingPaused) {
|
|
navSpeed = 0;
|
|
} else {
|
|
navSpeed = patrolSpeed;
|
|
}
|
|
} else {
|
|
if (runFromTarget) {
|
|
Vector3 direction = currentPosition - targetCurrentPosition;
|
|
|
|
if (reverseMoveInputDirectionActive) {
|
|
direction = targetCurrentPosition - currentPosition;
|
|
}
|
|
|
|
direction = direction / direction.magnitude;
|
|
|
|
currentTargetPosition = currentPosition + minDistanceToRunFromTarget * direction;
|
|
|
|
// use the values to move the character
|
|
if (smoothSpeedWhenCloseToTarget) {
|
|
navSpeed = 20 / currentDistanceToTarget;
|
|
navSpeed = Mathf.Clamp (navSpeed, 0.1f, 1);
|
|
} else {
|
|
navSpeed = 1;
|
|
}
|
|
|
|
setFollowingTargetState (true);
|
|
} else {
|
|
if (targetIsObject) {
|
|
currentMinDistance = minDistanceToObjects;
|
|
} else {
|
|
if (targetIsFriendly) {
|
|
currentMinDistance = minDistanceToFriend;
|
|
} else {
|
|
currentMinDistance = minDistanceToEnemy;
|
|
}
|
|
}
|
|
|
|
if (useCustomMinDistance) {
|
|
currentMinDistance = customMinDistance;
|
|
}
|
|
|
|
if (useHalfMinDistance) {
|
|
currentMinDistance *= minDistanceToTargetNotVisibleMultiplier;
|
|
|
|
if (currentMinDistance < minDistanceToTargetNotVisibleClamp) {
|
|
currentMinDistance = minDistanceToTargetNotVisibleClamp;
|
|
}
|
|
|
|
useHalfMinDistance = false;
|
|
}
|
|
|
|
moveToTargetActive = false;
|
|
|
|
if (rangeToTargetReached) {
|
|
if (currentDistanceToTarget > (currentMinDistance + currentDistanceToTargetOffset)) {
|
|
moveToTargetActive = true;
|
|
}
|
|
} else {
|
|
if (currentDistanceToTarget > currentMinDistance) {
|
|
moveToTargetActive = true;
|
|
}
|
|
}
|
|
|
|
if (moveToTargetActive || leavingSpaceToPartner || calculateMoveValueWithDirectionToTargetActive) {
|
|
// update the progress if the character has made it to the previous target
|
|
//if ((target.position - targetPos).magnitude > targetChangeTolerance) {
|
|
currentTargetPosition = targetCurrentPosition + positionOffset * targetTransformUp;
|
|
|
|
// use the values to move the character
|
|
if (smoothSpeedWhenCloseToTarget && !leavingSpaceToPartner) {
|
|
navSpeed = currentDistanceToTarget / 20;
|
|
navSpeed = Mathf.Clamp (navSpeed, 0.1f, 1);
|
|
} else {
|
|
navSpeed = 1;
|
|
}
|
|
|
|
setFollowingTargetState (true);
|
|
|
|
rangeToTargetReached = false;
|
|
|
|
} else if (currentDistanceToTarget < minDistanceToMoveBack) {
|
|
// update the progress if the character has made it to the previous target
|
|
Vector3 direction = currentPosition - targetCurrentPosition;
|
|
|
|
targetOffset = direction / currentDistanceToTarget;
|
|
|
|
currentTargetPosition = targetCurrentPosition + positionOffset * targetTransformUp + (minDistanceToMoveBack + 1) * targetOffset;
|
|
|
|
// use the values to move the character
|
|
navSpeed = currentDistanceToTarget / 20;
|
|
|
|
navSpeed = Mathf.Clamp (navSpeed, 0.1f, 1);
|
|
|
|
setFollowingTargetState (true);
|
|
} else {
|
|
// We still need to call the character's move function, but we send zeroed input as the move param.
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
|
|
setFollowingTargetState (false);
|
|
|
|
usingSamplePosition = false;
|
|
|
|
if (targetIsObject) {
|
|
removeTarget ();
|
|
}
|
|
|
|
if (useMinDistanceOffsetItTargetReached) {
|
|
rangeToTargetReached = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (followingTarget) {
|
|
if ((!targetIsFriendly || targetIsObject) && !patrolling) {
|
|
navSpeed = 1;
|
|
}
|
|
|
|
if (useCustomNavMeshSpeed) {
|
|
navSpeed = customNavMeshSpeed;
|
|
}
|
|
|
|
if (lookingPathAfterJump) {
|
|
currentTargetPosition = currentNavmeshOffLinkEndPos;
|
|
|
|
navSpeed = 1;
|
|
}
|
|
|
|
if (!usingSamplePosition) {
|
|
setAgentDestination (currentTargetPosition);
|
|
currentDestinationPosition = currentTargetPosition;
|
|
}
|
|
|
|
if (!updateCurrentNavMeshPath (currentDestinationPosition) || !canReachCurrentTarget) {
|
|
//print ("first path search not complete");
|
|
|
|
bool getClosestPosition = false;
|
|
|
|
if (currentNavMeshPath.status != NavMeshPathStatus.PathComplete) {
|
|
getClosestPosition = true;
|
|
}
|
|
|
|
if (getClosestPosition &&
|
|
getClosestPositionIfTargetCantBeReached &&
|
|
!ignoreGetClosestPositionIfTargetCantBeReached &&
|
|
!locked2_5dModeActive) {
|
|
//get closest position to target that can be reached
|
|
//maybe a for bucle checking every position ofthe corner and get the latest reachable
|
|
|
|
Vector3 positionToGet = currentDestinationPosition;
|
|
|
|
if (pathCorners.Count > 1) {
|
|
positionToGet = pathCorners [pathCorners.Count - 2];
|
|
}
|
|
|
|
usingSamplePosition = true;
|
|
|
|
if (NavMesh.SamplePosition (positionToGet + Vector3Up, out hit, 4, agent.areaMask)) {
|
|
if (samplePosition != hit.position) {
|
|
samplePosition = hit.position;
|
|
currentDestinationPosition = hit.position;
|
|
updateCurrentNavMeshPath (hit.position);
|
|
}
|
|
}
|
|
|
|
lastPathTargetPosition = samplePosition;
|
|
} else {
|
|
usingSamplePosition = false;
|
|
}
|
|
}
|
|
|
|
if (usingSamplePosition) {
|
|
// agent.SetDestination (lastPathTargetPosition);
|
|
//
|
|
// agent.transform.position = currentPosition;
|
|
|
|
setAgentDestination (lastPathTargetPosition);
|
|
|
|
updateCurrentNavMeshPath (lastPathTargetPosition);
|
|
|
|
if (agent.remainingDistance < 0.1f || GKC_Utils.distance (lastPathTargetPosition, currentTargetPosition) > maxDistanceToRecalculatePath) {
|
|
usingSamplePosition = false;
|
|
}
|
|
}
|
|
|
|
if (currentNavMeshPath != null) {
|
|
currentNavMeshPathStatus = currentNavMeshPath.status;
|
|
|
|
if (currentNavMeshPathStatus == NavMeshPathStatus.PathComplete) {
|
|
desiredVelocity = agent.desiredVelocity;
|
|
|
|
moveNavMesh (navSpeed * desiredVelocity, false, false);
|
|
|
|
if (showPathRenderer) {
|
|
currentLineRendererColor = Color.white;
|
|
}
|
|
|
|
canReachCurrentTarget = true;
|
|
} else if (currentNavMeshPathStatus == NavMeshPathStatus.PathPartial) {
|
|
if (showPathRenderer) {
|
|
currentLineRendererColor = Color.yellow;
|
|
}
|
|
|
|
bool setZeroMoveNavmeshResult = false;
|
|
|
|
if (locked2_5dModeActive) {
|
|
if (GKC_Utils.distance (currentPosition, pathCorners [pathCorners.Count - 1]) < 2) {
|
|
setZeroMoveNavmeshResult = true;
|
|
}
|
|
} else {
|
|
if (GKC_Utils.distance (currentPosition, pathCorners [pathCorners.Count - 1]) < 2) {
|
|
setZeroMoveNavmeshResult = true;
|
|
}
|
|
}
|
|
|
|
if (setZeroMoveNavmeshResult) {
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
} else {
|
|
desiredVelocity = agent.desiredVelocity;
|
|
|
|
moveNavMesh (navSpeed * desiredVelocity, false, false);
|
|
}
|
|
|
|
canReachCurrentTarget = false;
|
|
|
|
} else if (currentNavMeshPathStatus == NavMeshPathStatus.PathInvalid) {
|
|
if (showPathRenderer) {
|
|
currentLineRendererColor = Color.red;
|
|
}
|
|
|
|
canReachCurrentTarget = false;
|
|
|
|
if (locked2_5dModeActive) {
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
}
|
|
}
|
|
|
|
// print (canReachCurrentTarget);
|
|
|
|
if (checkOffMeshLinkJumpsEnabled) {
|
|
if (agent.isOnOffMeshLink && !lookingPathAfterJump) {
|
|
bool canActivateJump = true;
|
|
|
|
currentNavmeshOffLinkEndPos = agent.currentOffMeshLinkData.endPos;
|
|
|
|
Vector3 currentOffMeshLinkStartPos = agent.currentOffMeshLinkData.startPos;
|
|
|
|
float offMeshLinkDistance = GKC_Utils.distance (currentNavmeshOffLinkEndPos, currentOffMeshLinkStartPos);
|
|
|
|
float horizontalOffMeshLinkDistance =
|
|
GKC_Utils.distance (new Vector3 (currentNavmeshOffLinkEndPos.x, 0, currentNavmeshOffLinkEndPos.z),
|
|
new Vector3 (currentOffMeshLinkStartPos.x, 0, currentOffMeshLinkStartPos.z));
|
|
|
|
float verticalOffMeshLinkDistance = Mathf.Abs (currentNavmeshOffLinkEndPos.y - currentOffMeshLinkStartPos.y);
|
|
|
|
|
|
// print (offMeshLinkDistance + " " + verticalOffMeshLinkDistance + " " + horizontalOffMeshLinkDistance);
|
|
|
|
|
|
if (checkDistanceOnOffMeshLink) {
|
|
if (offMeshLinkDistance < minDistanceOnOffMeshLink) {
|
|
canActivateJump = false;
|
|
}
|
|
}
|
|
|
|
if (checkVerticalDistanceOnOffMeshLink) {
|
|
if (verticalOffMeshLinkDistance < minVerticalDistanceOnOffMeshLink) {
|
|
canActivateJump = false;
|
|
}
|
|
}
|
|
|
|
if (checkHorizontalDistanceOnOffMeshLink) {
|
|
if (horizontalOffMeshLinkDistance < minHorizontalDistanceOnOffMeshLink) {
|
|
canActivateJump = false;
|
|
}
|
|
}
|
|
|
|
if (canActivateJump) {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentNavmeshOffLinkEndPos, 5 * Vector3.up, Color.white, 5);
|
|
}
|
|
|
|
//_currLink = agent.currentOffMeshLinkData;
|
|
lookingPathAfterJump = true;
|
|
|
|
desiredVelocity = agent.desiredVelocity;
|
|
|
|
agent.autoTraverseOffMeshLink = false;
|
|
|
|
|
|
if (adjustJumpPowerToDistance) {
|
|
float newJumpPower = regularJumpPower;
|
|
|
|
newJumpPower += offMeshLinkDistance * jumpMultiplierPercentage;
|
|
|
|
newJumpPower = Mathf.Clamp (newJumpPower, 0, maxJumpPower);
|
|
|
|
playerControllerManager.setJumpPower (newJumpPower);
|
|
}
|
|
|
|
|
|
moveNavMesh (navSpeed * desiredVelocity, false, true);
|
|
|
|
// print ("jump detected");
|
|
|
|
lastTimeJumpDetected = Time.time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (showPathRenderer) {
|
|
if (lineRendererAdded) {
|
|
|
|
if (!lineRendererActive) {
|
|
lineRenderer.enabled = true;
|
|
|
|
lineRendererActive = true;
|
|
}
|
|
|
|
lineRenderer.startColor = currentLineRendererColor;
|
|
lineRenderer.endColor = currentLineRendererColor;
|
|
|
|
int currentPartCornersCount = pathCorners.Count;
|
|
|
|
lineRenderer.positionCount = currentPartCornersCount;
|
|
|
|
for (int i = 0; i < currentPartCornersCount; i++) {
|
|
lineRenderer.SetPosition (i, pathCorners [i]);
|
|
}
|
|
} else {
|
|
addLineRendererGizmo ();
|
|
}
|
|
}
|
|
} else {
|
|
if (showPathRenderer) {
|
|
if (lineRendererAdded) {
|
|
if (lineRendererActive) {
|
|
lineRenderer.enabled = false;
|
|
|
|
lineRendererActive = false;
|
|
}
|
|
} else {
|
|
addLineRendererGizmo ();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
|
|
usingSamplePosition = false;
|
|
|
|
if (followingTarget) {
|
|
if (agent.enabled) {
|
|
agent.ResetPath ();
|
|
}
|
|
|
|
setFollowingTargetState (false);
|
|
}
|
|
|
|
if (showPathRenderer) {
|
|
if (lineRendererAdded) {
|
|
if (lineRendererActive) {
|
|
lineRenderer.enabled = false;
|
|
|
|
lineRendererActive = false;
|
|
}
|
|
} else {
|
|
addLineRendererGizmo ();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
usingSamplePosition = false;
|
|
|
|
if (followingTarget) {
|
|
if (agent.enabled) {
|
|
agent.ResetPath ();
|
|
}
|
|
|
|
setFollowingTargetState (false);
|
|
}
|
|
|
|
if (showPathRenderer) {
|
|
if (lineRendererAdded) {
|
|
if (lineRendererActive) {
|
|
lineRenderer.enabled = false;
|
|
|
|
lineRendererActive = false;
|
|
}
|
|
} else {
|
|
addLineRendererGizmo ();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void resetInitialTargetCheckedOnCharacterSpawn ()
|
|
{
|
|
initialTargetChecked = false;
|
|
}
|
|
|
|
public void activateJumpExternally (float jumpDistance)
|
|
{
|
|
if (!lookingPathAfterJump && onGround) {
|
|
if (currentTarget != null) {
|
|
currentNavmeshOffLinkEndPos = currentTarget.position;
|
|
} else {
|
|
currentNavmeshOffLinkEndPos = targetCurrentPosition;
|
|
}
|
|
|
|
lookingPathAfterJump = true;
|
|
|
|
desiredVelocity = agent.desiredVelocity;
|
|
|
|
agent.autoTraverseOffMeshLink = false;
|
|
|
|
if (jumpDistance != 0) {
|
|
float newJumpPower = regularJumpPower;
|
|
|
|
newJumpPower += jumpDistance * jumpMultiplierPercentage;
|
|
|
|
newJumpPower = Mathf.Clamp (newJumpPower, 0, maxJumpPower);
|
|
|
|
playerControllerManager.setJumpPower (newJumpPower);
|
|
}
|
|
|
|
moveNavMesh (navSpeed * desiredVelocity, false, true);
|
|
|
|
lastTimeJumpDetected = Time.time;
|
|
}
|
|
}
|
|
|
|
public void setJumpPower (float newValue)
|
|
{
|
|
playerControllerManager.setJumpPower (newValue);
|
|
}
|
|
|
|
public void setOriginalJumpPower ()
|
|
{
|
|
playerControllerManager.setOriginalJumpPower ();
|
|
}
|
|
|
|
void addLineRendererGizmo ()
|
|
{
|
|
if (!lineRendererAdded) {
|
|
lineRenderer = AIGameObject.GetComponent<LineRenderer> ();
|
|
|
|
if (lineRenderer == null) {
|
|
lineRenderer = AIGameObject.AddComponent<LineRenderer> ();
|
|
lineRenderer.material = new Material (Shader.Find ("Sprites/Default")) { color = currentLineRendererColor };
|
|
lineRenderer.startWidth = 0.5f;
|
|
lineRenderer.endWidth = 0.5f;
|
|
lineRenderer.startColor = currentLineRendererColor;
|
|
lineRenderer.endColor = currentLineRendererColor;
|
|
|
|
lineRendererAdded = true;
|
|
|
|
lineRendererActive = true;
|
|
}
|
|
}
|
|
}
|
|
public void setAgentDestination (Vector3 targetPosition)
|
|
{
|
|
bool setAgentDestinationResult = false;
|
|
|
|
if (GKC_Utils.distance (lastTargetPosition, targetPosition) > maxDistanceToRecalculatePath ||
|
|
Time.time > lastTimeUpdateNavMeshPosition + updateNavMeshPositionRate ||
|
|
forceToSetAgentDestinationActive) {
|
|
setAgentDestinationResult = true;
|
|
}
|
|
|
|
if (setAgentDestinationResult) {
|
|
if (locked2_5dModeActive && !canReachCurrentTarget) {
|
|
if (Time.time < lastTimeUpdateNavMeshPosition + updateNavMeshPositionRate2_5d) {
|
|
setAgentDestinationResult = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (setAgentDestinationResult) {
|
|
|
|
if (!warpPositionAssigned) {
|
|
agent.Warp (AITransform.position);
|
|
warpPositionAssigned = true;
|
|
}
|
|
|
|
lastTargetPosition = targetPosition;
|
|
agent.SetDestination (targetPosition);
|
|
lastTimeUpdateNavMeshPosition = Time.time;
|
|
|
|
if (showSetAgentDestinationDebugPrint) {
|
|
print ("setAgentDestination " + agent.desiredVelocity);
|
|
}
|
|
}
|
|
|
|
agent.transform.position = AITransform.position;
|
|
}
|
|
|
|
public bool updateCurrentNavMeshPath (Vector3 targetPosition)
|
|
{
|
|
bool hasFoundPath = true;
|
|
|
|
if (GKC_Utils.distance (lastPathTargetPosition, targetPosition) > maxDistanceToRecalculatePath || pathCorners.Count == 0 || Time.time > calculatePathRate + lastTimeCalculatePath) {
|
|
lastPathTargetPosition = targetPosition;
|
|
|
|
setAgentDestination (lastPathTargetPosition);
|
|
|
|
currentNavMeshPath = new NavMeshPath ();
|
|
|
|
pathCorners.Clear ();
|
|
|
|
hasFoundPath = agent.CalculatePath (lastPathTargetPosition, currentNavMeshPath);
|
|
|
|
pathCorners.AddRange (currentNavMeshPath.corners);
|
|
|
|
lastTimeCalculatePath = Time.time;
|
|
}
|
|
|
|
return hasFoundPath;
|
|
}
|
|
|
|
public void setOnGroundState (bool state)
|
|
{
|
|
onGround = state;
|
|
}
|
|
|
|
public bool isAIOnGround ()
|
|
{
|
|
return onGround;
|
|
}
|
|
|
|
public void setLocked2_5dModeActiveState (bool state)
|
|
{
|
|
locked2_5dModeActive = state;
|
|
}
|
|
|
|
public bool isLocked2_5dModeActive ()
|
|
{
|
|
return locked2_5dModeActive;
|
|
}
|
|
|
|
public void setMoveInXAxisOn2_5dModeState (bool state)
|
|
{
|
|
moveInXAxisOn2_5dMode = state;
|
|
}
|
|
|
|
public bool getCanReachCurrentTargetValue ()
|
|
{
|
|
return canReachCurrentTarget;
|
|
}
|
|
|
|
public float getRemainingPathDistanceToTarget ()
|
|
{
|
|
if (followingTarget) {
|
|
if (calculateMoveValueWithDirectionToTargetActive) {
|
|
return -100;
|
|
}
|
|
|
|
pathCornersCount = pathCorners.Count;
|
|
|
|
if (pathCornersCount > 1) {
|
|
float currentDistance = GKC_Utils.distance (AITransform.position, pathCorners [1]);
|
|
|
|
if (pathCornersCount > 2) {
|
|
for (int i = 2; i < pathCornersCount; ++i) {
|
|
currentDistance += GKC_Utils.distance (pathCorners [i - 1], pathCorners [i]);
|
|
}
|
|
}
|
|
|
|
return currentDistance;
|
|
} else {
|
|
return -100;
|
|
}
|
|
} else {
|
|
return -100;
|
|
}
|
|
}
|
|
|
|
public float getCurrentDistanceToTarget ()
|
|
{
|
|
return currentDistanceToTarget;
|
|
}
|
|
|
|
public Vector3 getMovementDirection ()
|
|
{
|
|
if (pathCorners.Count > 0) {
|
|
if (GKC_Utils.distance (pathCorners [0], AITransform.position) < 0.1f) {
|
|
pathCorners.RemoveAt (0);
|
|
}
|
|
|
|
if (pathCorners.Count > 0) {
|
|
Vector3 direction = pathCorners [0] - AITransform.position;
|
|
return direction.normalized;
|
|
}
|
|
}
|
|
|
|
return Vector3Zero;
|
|
}
|
|
|
|
public Vector3 getCurrentMovementDirection ()
|
|
{
|
|
return currentMovementDirection;
|
|
}
|
|
|
|
public Vector3 getDesiredVelocity ()
|
|
{
|
|
return desiredVelocity;
|
|
}
|
|
|
|
public void setPauseMoveNavMeshState (bool state)
|
|
{
|
|
moveNavMeshPaused = state;
|
|
|
|
if (showDebugPrint) {
|
|
print ("setPauseMoveNavMeshState " + moveNavMeshPaused);
|
|
}
|
|
}
|
|
|
|
public void setMoveNavMeshPausedDuringActionState (bool state)
|
|
{
|
|
moveNavMeshPausedDuringAction = state;
|
|
}
|
|
|
|
public void setNavmeshPausedState (bool state)
|
|
{
|
|
navMeshPaused = state;
|
|
|
|
// print ("nav mesh " + navMeshPaused);
|
|
}
|
|
|
|
public void setCalculateMoveValueWithDirectionToTargetActiveState (bool state)
|
|
{
|
|
calculateMoveValueWithDirectionToTargetActive = state;
|
|
}
|
|
|
|
public bool isCalculateMoveValueWithDirectionToTargetActive ()
|
|
{
|
|
return calculateMoveValueWithDirectionToTargetActive;
|
|
}
|
|
|
|
|
|
public void updateUseExtraColliderListState ()
|
|
{
|
|
useExtraColliderList = playerControllerManager.isUseExtraColliderListActive ();
|
|
|
|
if (useExtraColliderList) {
|
|
extraColliderList = playerControllerManager.getExtraColliderList ();
|
|
} else {
|
|
extraColliderList.Clear ();
|
|
}
|
|
|
|
mainCollider = playerControllerManager.getMainCollider ();
|
|
}
|
|
|
|
bool updateUseExtraColliderListStateChecked;
|
|
|
|
bool checkIfObstacleDetected (Vector3 raycastPosition, Vector3 raycastDirection, float raycastDistance)
|
|
{
|
|
if (checkForExtraCollidersOnOwnerIfDetected) {
|
|
if (!updateUseExtraColliderListStateChecked) {
|
|
updateUseExtraColliderListState ();
|
|
|
|
updateUseExtraColliderListStateChecked = true;
|
|
}
|
|
}
|
|
|
|
if (useExtraColliderList) {
|
|
|
|
bool loopFinished = false;
|
|
|
|
int loopCount = 0;
|
|
|
|
while (!loopFinished) {
|
|
if (Physics.Raycast (raycastPosition, raycastDirection, out rayhit, raycastDistance, dynamicObstacleLayer)) {
|
|
if (extraColliderList.Contains (rayhit.collider)) {
|
|
raycastPosition = rayhit.point;
|
|
|
|
//print ("own collider list detected " + extraColliderList.Count + " " + rayhit.collider.name);
|
|
} else if (mainCollider == rayhit.collider) {
|
|
raycastPosition = rayhit.point;
|
|
|
|
//print ("own collider detected");
|
|
} else {
|
|
return true;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
loopCount++;
|
|
|
|
if (loopCount > 10) {
|
|
loopFinished = true;
|
|
}
|
|
}
|
|
} else {
|
|
if (Physics.Raycast (raycastPosition, raycastDirection, out rayhit, raycastDistance, dynamicObstacleLayer)) {
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public virtual void moveNavMesh (Vector3 moveInput, bool crouch, bool jump)
|
|
{
|
|
bool canCheckDynamicObstacleResult =
|
|
useDynamicObstacleDetection &&
|
|
(targetIsFriendly || targetIsObject || useDynamicObstacleWhenTargetIsEnemyEnabled) &&
|
|
moveInput != Vector3Zero &&
|
|
!locked2_5dModeActive;
|
|
|
|
if (canCheckDynamicObstacleResult) {
|
|
currentUp = AITransform.up;
|
|
currentForward = AITransform.forward;
|
|
|
|
if (moveNavMeshPaused) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
|
|
if (moveNavMeshPausedDuringAction) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
|
|
if (moveInput != Vector3Zero) {
|
|
|
|
Vector3 currentRaycastPosition = AITransform.position + currentUp;
|
|
|
|
|
|
if (!obstacleDetected) {
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentForward, dynamicRaycastDistanceForward)) {
|
|
obstacleDetected = true;
|
|
|
|
avoidDirection = moveInput;
|
|
|
|
currentCheckObstalceDirection = Quaternion.Euler (60 * currentUp) * currentForward;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = rayhit.collider.gameObject;
|
|
}
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentCheckObstalceDirection, dynamicRaycastDistanceForward)) {
|
|
|
|
moveToRight = false;
|
|
}
|
|
}
|
|
|
|
if (!obstacleDetected) {
|
|
currentCheckObstalceDirection = Quaternion.Euler (60 * currentUp) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentCheckObstalceDirection, dynamicRaycastDistanceDiagonal)) {
|
|
|
|
obstacleDetected = true;
|
|
|
|
avoidDirection = moveInput;
|
|
|
|
moveToRight = false;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = rayhit.collider.gameObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!obstacleDetected) {
|
|
currentCheckObstalceDirection = Quaternion.Euler (60 * (-currentUp)) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentCheckObstalceDirection, dynamicRaycastDistanceDiagonal)) {
|
|
|
|
obstacleDetected = true;
|
|
|
|
avoidDirection = moveInput;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = rayhit.collider.gameObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!obstacleDetected) {
|
|
currentCheckObstalceDirection = Quaternion.Euler (90 * currentUp) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentCheckObstalceDirection, dynamicRaycastDistanceSides)) {
|
|
|
|
obstacleDetected = true;
|
|
|
|
avoidDirection = moveInput;
|
|
|
|
moveToRight = false;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = rayhit.collider.gameObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!obstacleDetected) {
|
|
currentCheckObstalceDirection = Quaternion.Euler (90 * (-currentUp)) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, currentCheckObstalceDirection, dynamicRaycastDistanceSides)) {
|
|
|
|
obstacleDetected = true;
|
|
|
|
avoidDirection = moveInput;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = rayhit.collider.gameObject;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (obstacleDetected) {
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
if (lastObstacleDetected != null) {
|
|
if (objectListToIgnoreOnDynamicObstacle.Contains (lastObstacleDetected)) {
|
|
obstacleDetected = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obstacleDetected) {
|
|
obstacleOnForward = false;
|
|
obstacleOnRight = false;
|
|
obstacleOnLeft = false;
|
|
obstacleOnRightForward = false;
|
|
obstacleOnLeftForward = false;
|
|
|
|
numberOfObstacleDirectionDetected = 0;
|
|
|
|
obstacleDistance = 3;
|
|
|
|
bool newObstacleFound = false;
|
|
|
|
if (pathCorners.Count > 0) {
|
|
currentForward = (pathCorners [pathCorners.Count - 1] - AITransform.position);
|
|
|
|
currentForward.Normalize ();
|
|
} else {
|
|
currentForward = moveInput;
|
|
|
|
currentForward.Normalize ();
|
|
}
|
|
|
|
Vector3 rayDirection = currentForward;
|
|
|
|
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, rayDirection, dynamicRaycastDistanceForward)) {
|
|
|
|
obstacleDistance = rayhit.distance;
|
|
|
|
newObstacleFound = true;
|
|
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.red, 2);
|
|
}
|
|
|
|
obstacleOnForward = true;
|
|
|
|
numberOfObstacleDirectionDetected++;
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.green, 2);
|
|
}
|
|
}
|
|
|
|
rayDirection = Quaternion.Euler (45 * currentUp) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, rayDirection, dynamicRaycastDistanceAround)) {
|
|
|
|
newObstacleFound = true;
|
|
|
|
if (rayhit.distance < obstacleDistance) {
|
|
obstacleDistance = rayhit.distance;
|
|
}
|
|
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.red, 2);
|
|
}
|
|
|
|
obstacleOnRightForward = true;
|
|
|
|
numberOfObstacleDirectionDetected++;
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.green, 2);
|
|
}
|
|
}
|
|
|
|
rayDirection = Quaternion.Euler (45 * (-currentUp)) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, rayDirection, dynamicRaycastDistanceAround)) {
|
|
|
|
newObstacleFound = true;
|
|
|
|
if (rayhit.distance < obstacleDistance) {
|
|
obstacleDistance = rayhit.distance;
|
|
}
|
|
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.red, 2);
|
|
}
|
|
|
|
obstacleOnLeftForward = true;
|
|
|
|
numberOfObstacleDirectionDetected++;
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.green, 2);
|
|
}
|
|
}
|
|
|
|
rayDirection = Quaternion.Euler (90 * currentUp) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, rayDirection, dynamicRaycastDistanceAround)) {
|
|
|
|
newObstacleFound = true;
|
|
|
|
if (rayhit.distance < obstacleDistance) {
|
|
obstacleDistance = rayhit.distance;
|
|
}
|
|
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.red, 2);
|
|
}
|
|
|
|
obstacleOnRight = true;
|
|
|
|
numberOfObstacleDirectionDetected++;
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.green, 2);
|
|
}
|
|
}
|
|
|
|
rayDirection = Quaternion.Euler (90 * (-currentUp)) * currentForward;
|
|
|
|
if (checkIfObstacleDetected (currentRaycastPosition, rayDirection, dynamicRaycastDistanceAround)) {
|
|
|
|
newObstacleFound = true;
|
|
|
|
if (rayhit.distance < obstacleDistance) {
|
|
obstacleDistance = rayhit.distance;
|
|
}
|
|
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.red, 2);
|
|
}
|
|
|
|
obstacleOnLeft = true;
|
|
|
|
numberOfObstacleDirectionDetected++;
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (currentRaycastPosition, rayDirection, Color.green, 2);
|
|
}
|
|
}
|
|
|
|
|
|
if (obstacleOnLeft || obstacleOnLeftForward || obstacleOnForward) {
|
|
moveToRight = true;
|
|
} else {
|
|
moveToRight = false;
|
|
}
|
|
|
|
|
|
if (!newObstacleFound) {
|
|
obstacleDetected = false;
|
|
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
lastObstacleDetected = null;
|
|
}
|
|
} else {
|
|
float avoidAngle = 30;
|
|
|
|
if (obstacleDistance < 3) {
|
|
avoidAngle = minObstacleRotation;
|
|
}
|
|
|
|
if (obstacleDistance < 2) {
|
|
avoidAngle = mediumObstacleRotation;
|
|
}
|
|
|
|
if (obstacleDistance < 1) {
|
|
avoidAngle = maximumObstacleRotation;
|
|
}
|
|
|
|
if (!moveToRight) {
|
|
avoidAngle = -avoidAngle;
|
|
}
|
|
|
|
Vector3 newDirection = Quaternion.Euler (avoidAngle * currentUp) * avoidDirection;
|
|
|
|
newMoveDirection = newDirection;
|
|
|
|
// newMoveDirection *= navSpeed;
|
|
|
|
if (showDynamicObstacleDebugPrint) {
|
|
print ("obstacle detected, moving to the right is " + moveToRight);
|
|
print ("avoid angle is " + avoidAngle);
|
|
}
|
|
}
|
|
} else {
|
|
newMoveDirection = moveInput;
|
|
|
|
if (showDynamicObstacleDebugPrint) {
|
|
print ("no obstacle detected");
|
|
}
|
|
}
|
|
} else {
|
|
newMoveDirection = moveInput;
|
|
|
|
if (showDynamicObstacleDebugPrint) {
|
|
print ("no obstacle detected");
|
|
}
|
|
}
|
|
|
|
if (currentDistanceToTarget > currentMinDistance + 3) {
|
|
if (newMoveDirection.magnitude > 1) {
|
|
newMoveDirection.Normalize ();
|
|
}
|
|
}
|
|
|
|
currentMoveDirection = Vector3.Lerp (currentMoveDirection, newMoveDirection, Time.fixedDeltaTime * dynamicAvoidSpeed);
|
|
|
|
moveInput = currentMoveDirection;
|
|
} else {
|
|
|
|
if (moveNavMeshPaused) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
|
|
if (moveNavMeshPausedDuringAction) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
}
|
|
|
|
if (guidingPartnerActive && partnerLocated && !attacking && (targetIsFriendly || targetIsObject)) {
|
|
currentDistanceToPartnerToGuide = GKC_Utils.distance (partner.position, currentPosition);
|
|
|
|
if (currentTarget != partner) {
|
|
if (!checkForPartnerToGuidDistance) {
|
|
partnerToGuideOnRange = currentDistanceToPartnerToGuide < maxDistanceToPartnerWhenGuidingHim;
|
|
|
|
lastMoveDirection = moveInput.normalized;
|
|
}
|
|
|
|
if (!partnerToGuideOnRange) {
|
|
lastMoveDirection = Vector3.Lerp (lastMoveDirection, Vector3Zero, Time.deltaTime * targetToGuideOutOfRangeLerpSpeed);
|
|
|
|
moveInput = lastMoveDirection;
|
|
|
|
checkForPartnerToGuidDistance = true;
|
|
|
|
if (currentDistanceToPartnerToGuide < (maxDistanceToPartnerWhenGuidingHim - distanceOffsetToSetGuideBackToRange)) {
|
|
checkForPartnerToGuidDistance = false;
|
|
}
|
|
|
|
if (returnToTargetToGuideWhenOutOfRange) {
|
|
if (currentDistanceToPartnerToGuide > maxDistanceToReturnToTargetToGuide) {
|
|
returningToTargetToGuideActive = true;
|
|
setTarget (partner);
|
|
|
|
lastMoveDirection = Vector3Zero;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (currentDistanceToPartnerToGuide < (maxDistanceToPartnerWhenGuidingHim + 0.5f)) {
|
|
returningToTargetToGuideActive = false;
|
|
|
|
setTarget (currentPositionTransformToGuide);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (moveInput.magnitude < 0.01f) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
|
|
if (pauseMovementToTarget) {
|
|
moveInput = Vector3Zero;
|
|
}
|
|
|
|
if (locked2_5dModeActive) {
|
|
moveInput.z = 0;
|
|
}
|
|
|
|
currentMovementDirection = moveInput;
|
|
|
|
// if (moveInput == Vector3Zero) {
|
|
// print ("ZERO");
|
|
// }
|
|
|
|
if (showMoveInputDebugPrint) {
|
|
print (moveInput);
|
|
}
|
|
|
|
currentMoveInput = walkSpeed * moveInput;
|
|
|
|
AIMoveInput.moveInput = currentMoveInput;
|
|
AIMoveInput.crouchInput = crouch;
|
|
AIMoveInput.jumpInput = jump;
|
|
|
|
AIMoveInput.AIEnableInputMovementOnStrafe = calculateMoveValueWithDirectionToTargetActive;
|
|
|
|
updateAIControllerInputValues ();
|
|
|
|
updateAICameraInputValues ();
|
|
}
|
|
|
|
Vector3 currentMoveInput;
|
|
|
|
bool reverseMoveInputDirectionActive;
|
|
|
|
public void setReverseMoveInputDirectionActiveState (bool state)
|
|
{
|
|
reverseMoveInputDirectionActive = state;
|
|
}
|
|
|
|
public virtual void updateAIControllerInputValues ()
|
|
{
|
|
playerControllerManager.Move (AIMoveInput);
|
|
}
|
|
|
|
public virtual void updateAICameraInputValues ()
|
|
{
|
|
playerCameraManager.Rotate (rayCastPosition.forward);
|
|
}
|
|
|
|
public void setAIWalkSpeed (float newValue)
|
|
{
|
|
walkSpeed = newValue;
|
|
}
|
|
|
|
public void setOriginalAIWalkSpeed (float newValue)
|
|
{
|
|
setAIWalkSpeed (originalAIWalkSpeed);
|
|
}
|
|
|
|
public void setResetVerticalCameraRotationActiveState (bool state)
|
|
{
|
|
playerCameraManager.setResetVerticalCameraRotationActiveState (state);
|
|
}
|
|
|
|
public void setTurnBasedCombatActionActiveState (bool state)
|
|
{
|
|
turnBasedCombatActionActive = state;
|
|
|
|
if (turnBasedCombatActionActive) {
|
|
lookAtTaget (true);
|
|
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
}
|
|
}
|
|
|
|
public void pauseAI (bool state)
|
|
{
|
|
if (AIDead && !state) {
|
|
if (showDebugPrint) {
|
|
print ("WARNING: trying to resume a dead AI");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (turnBasedCombatActionActive) {
|
|
if (!state) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// print ("setting AI pause state " + state);
|
|
|
|
setNavmeshPausedState (state);
|
|
|
|
if (navMeshPaused) {
|
|
if (agent != null) {
|
|
if (agent.enabled) {
|
|
agent.Warp (AITransform.position);
|
|
|
|
agent.isStopped = true;
|
|
agent.enabled = false;
|
|
}
|
|
}
|
|
|
|
lookAtTaget (false);
|
|
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
} else {
|
|
if (!agent.enabled) {
|
|
agent.enabled = true;
|
|
|
|
if (waitToResumeCoroutine != null) {
|
|
StopCoroutine (waitToResumeCoroutine);
|
|
}
|
|
waitToResumeCoroutine = StartCoroutine (resumeCoroutine ());
|
|
}
|
|
}
|
|
|
|
if (navMeshPaused) {
|
|
eventToPauseAI.Invoke ();
|
|
} else {
|
|
eventToResumeAI.Invoke ();
|
|
}
|
|
|
|
if (showPathRenderer) {
|
|
if (lineRendererAdded) {
|
|
if (!state) {
|
|
lineRenderer.enabled = !state;
|
|
|
|
lineRendererActive = !state;
|
|
}
|
|
} else {
|
|
addLineRendererGizmo ();
|
|
}
|
|
}
|
|
|
|
rangeToTargetReached = false;
|
|
|
|
if (turnBasedCombatActionActive) {
|
|
if (state) {
|
|
lookAtTaget (true);
|
|
|
|
moveNavMesh (Vector3Zero, false, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
IEnumerator resumeCoroutine ()
|
|
{
|
|
WaitForSeconds delay = new WaitForSeconds (0.0001f);
|
|
|
|
yield return delay;
|
|
|
|
if (agent.enabled) {
|
|
agent.isStopped = false;
|
|
}
|
|
|
|
checkingToResumeNavmesh = true;
|
|
}
|
|
|
|
//disable ai when it dies
|
|
public void setAIStateToDead ()
|
|
{
|
|
AIDead = true;
|
|
|
|
eventOnDeath.Invoke ();
|
|
|
|
reverseMoveInputDirectionActive = false;
|
|
}
|
|
|
|
public void setAIStateToAlive ()
|
|
{
|
|
AIDead = false;
|
|
|
|
eventOnAlive.Invoke ();
|
|
|
|
agent.Warp (AITransform.position);
|
|
}
|
|
|
|
public bool isAIDead ()
|
|
{
|
|
return AIDead;
|
|
}
|
|
|
|
public void recalculatePath ()
|
|
{
|
|
if (agent.enabled) {
|
|
agent.isStopped = false;
|
|
}
|
|
}
|
|
|
|
public void jumpStart ()
|
|
{
|
|
|
|
}
|
|
|
|
public void jumpEnded ()
|
|
{
|
|
agent.enabled = true;
|
|
|
|
agent.CompleteOffMeshLink ();
|
|
|
|
//Resume normal navmesh behaviour
|
|
agent.isStopped = false;
|
|
|
|
lookingPathAfterJump = false;
|
|
|
|
setNavmeshPausedState (false);
|
|
|
|
agent.Warp (AITransform.position);
|
|
|
|
agent.transform.position = AITransform.position;
|
|
}
|
|
|
|
public void placeAIOnNewPosition (Vector3 newPosition)
|
|
{
|
|
AITransform.position = newPosition;
|
|
|
|
agent.Warp (AITransform.position);
|
|
|
|
agent.transform.position = AITransform.position;
|
|
}
|
|
|
|
public void setAINewRotation (Vector3 newRotation)
|
|
{
|
|
AITransform.eulerAngles = newRotation;
|
|
}
|
|
|
|
public virtual void setPatrolTarget (Transform newTarget)
|
|
{
|
|
if (patrollingPaused) {
|
|
return;
|
|
}
|
|
|
|
// print ("setting patrol point " + newTarget.name);
|
|
|
|
setTarget (newTarget);
|
|
}
|
|
|
|
public void setTarget (Transform newTarget)
|
|
{
|
|
currentTarget = newTarget;
|
|
|
|
if (showDebugPrint) {
|
|
if (currentTarget) {
|
|
print ("SETTING NEW TARGET ON AI NAVMESH " + newTarget.name);
|
|
} else {
|
|
print ("target NULL");
|
|
}
|
|
}
|
|
|
|
rangeToTargetReached = false;
|
|
|
|
checkStateOnSetTarget ();
|
|
}
|
|
|
|
public virtual void checkStateOnSetTarget ()
|
|
{
|
|
|
|
}
|
|
|
|
public Transform getCurrentTarget ()
|
|
{
|
|
return currentTarget;
|
|
}
|
|
|
|
public void avoidTarget (Transform targetToAvoid)
|
|
{
|
|
setTarget (targetToAvoid);
|
|
}
|
|
|
|
public void setAvoidTargetState (bool state)
|
|
{
|
|
runFromTarget = state;
|
|
}
|
|
|
|
public virtual void removeTarget ()
|
|
{
|
|
setTarget (null);
|
|
}
|
|
|
|
bool forceToSetAgentDestinationActive;
|
|
|
|
public void recalculateSetAgentDestination ()
|
|
{
|
|
if (currentTarget != null) {
|
|
targetCurrentPosition = currentTarget.position;
|
|
|
|
currentTargetPosition = targetCurrentPosition + positionOffset * targetTransformUp;
|
|
|
|
forceToSetAgentDestinationActive = true;
|
|
|
|
setAgentDestination (currentTargetPosition);
|
|
|
|
forceToSetAgentDestinationActive = false;
|
|
|
|
currentDestinationPosition = currentTargetPosition;
|
|
|
|
updateCurrentNavMeshPath (currentDestinationPosition);
|
|
|
|
// print ("recalculate");
|
|
}
|
|
}
|
|
|
|
public void resetCustomSpeedAndDistanceValues ()
|
|
{
|
|
disableCustomNavMeshSpeed ();
|
|
|
|
disableCustomMinDistance ();
|
|
}
|
|
|
|
public bool anyTargetToReach ()
|
|
{
|
|
return currentTarget != null;
|
|
}
|
|
|
|
public void setGuidingPartnerActiveState (bool state)
|
|
{
|
|
guidingPartnerActive = state;
|
|
|
|
if (guidingPartnerActive && currentTarget != null) {
|
|
currentPositionTransformToGuide = currentTarget;
|
|
}
|
|
|
|
checkForPartnerToGuidDistance = false;
|
|
}
|
|
|
|
public void partnerFound (Transform currentPartner)
|
|
{
|
|
partner = currentPartner;
|
|
|
|
setTarget (partner);
|
|
|
|
setPartnerFoundInfo (partner);
|
|
}
|
|
|
|
public void setPartnerFoundInfo (Transform currentPartner)
|
|
{
|
|
partner = currentPartner;
|
|
|
|
if (patrolling) {
|
|
patrolling = false;
|
|
}
|
|
|
|
eventOnPartnerFound.Invoke ();
|
|
|
|
if (addAIAsPlayerPartner) {
|
|
partnerRemoteEventSystem = partner.GetComponent<remoteEventSystem> ();
|
|
|
|
if (partnerRemoteEventSystem != null) {
|
|
partnerRemoteEventSystem.callRemoteEventWithGameObject (addAIToFriendListManagerEventName, AIGameObject);
|
|
}
|
|
}
|
|
|
|
if (partner != null) {
|
|
partnerLocated = true;
|
|
} else {
|
|
partnerLocated = false;
|
|
}
|
|
}
|
|
|
|
public Transform getCurrentPartner ()
|
|
{
|
|
return partner;
|
|
}
|
|
|
|
bool removePartnerPausedState;
|
|
|
|
public void setRemovePartnerPausedState (bool state)
|
|
{
|
|
removePartnerPausedState = state;
|
|
}
|
|
|
|
public void removeFromPartnerList ()
|
|
{
|
|
if (addAIAsPlayerPartner) {
|
|
if (removePartnerPausedState) {
|
|
if (showDebugPrint) {
|
|
print ("trying to remove partner on dead AI during turn combat system active, cancelling");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (partner != null) {
|
|
if (partnerRemoteEventSystem != null) {
|
|
partnerRemoteEventSystem.callRemoteEventWithTransform (removeAIToFriendListManagerEventName, AITransform);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void removePartner ()
|
|
{
|
|
if (partner != null) {
|
|
removeFromPartnerList ();
|
|
|
|
if (currentTarget == partner) {
|
|
setTarget (null);
|
|
}
|
|
|
|
partner = null;
|
|
|
|
partnerLocated = false;
|
|
|
|
followingPartner = false;
|
|
}
|
|
}
|
|
|
|
public void lookAtTaget (bool state)
|
|
{
|
|
if (ignoreLookAtTargetDirection) {
|
|
return;
|
|
}
|
|
|
|
if (showDebugPrint) {
|
|
print ("LOOK AT TARGET VALUE " + state);
|
|
}
|
|
|
|
//make the character to look or not to look towards its target, pointing the camera towards it
|
|
AIMoveInput.lookAtTarget = state;
|
|
}
|
|
|
|
public void setStrafeModeActiveState (bool state)
|
|
{
|
|
AIMoveInput.strafeModeActive = state;
|
|
}
|
|
|
|
public void setPatrolState (bool state)
|
|
{
|
|
patrolling = state;
|
|
}
|
|
|
|
public void setPatrolPauseState (bool state)
|
|
{
|
|
patrollingPaused = state;
|
|
}
|
|
|
|
public bool isPatrolPaused ()
|
|
{
|
|
return patrollingPaused;
|
|
}
|
|
|
|
public bool isPatrolling ()
|
|
{
|
|
return patrolling;
|
|
}
|
|
|
|
public void setPatrolSpeed (float value)
|
|
{
|
|
patrolSpeed = value;
|
|
}
|
|
|
|
public void attack (Transform newTarget)
|
|
{
|
|
setTarget (newTarget);
|
|
|
|
setCharacterStates (true, false, false, false);
|
|
}
|
|
|
|
public void follow (Transform newTarget)
|
|
{
|
|
setFollowingTargetState (true);
|
|
|
|
setTarget (newTarget);
|
|
|
|
setCharacterStates (false, true, false, false);
|
|
}
|
|
|
|
public void wait (Transform newTarget)
|
|
{
|
|
removeTarget ();
|
|
|
|
setCharacterStates (false, false, true, false);
|
|
}
|
|
|
|
public void hide (Transform newTarget)
|
|
{
|
|
setTarget (newTarget);
|
|
|
|
setCharacterStates (false, false, false, true);
|
|
}
|
|
|
|
public void setFollowingTargetState (bool state)
|
|
{
|
|
followingTarget = state;
|
|
}
|
|
|
|
public bool isCharacterAttacking ()
|
|
{
|
|
return attacking;
|
|
}
|
|
|
|
public bool isCharacterFollowing ()
|
|
{
|
|
return following;
|
|
}
|
|
|
|
public bool isCharacterWaiting ()
|
|
{
|
|
return waiting;
|
|
}
|
|
|
|
public bool isCharacterHiding ()
|
|
{
|
|
return hiding;
|
|
}
|
|
|
|
public bool isPartnerLocated ()
|
|
{
|
|
return partnerLocated;
|
|
}
|
|
|
|
public void setCharacterStates (bool attackValue, bool followValue, bool waitValue, bool hideValue)
|
|
{
|
|
attacking = attackValue;
|
|
following = followValue;
|
|
waiting = waitValue;
|
|
hiding = hideValue;
|
|
}
|
|
|
|
public void setTargetType (bool isFriendly, bool isObject)
|
|
{
|
|
targetIsFriendly = isFriendly;
|
|
targetIsObject = isObject;
|
|
|
|
if (targetIsFriendly) {
|
|
setCharacterStates (false, false, false, false);
|
|
}
|
|
}
|
|
|
|
public void setExtraMinDistanceState (bool state, float extraDistance)
|
|
{
|
|
if (state) {
|
|
minDistanceToFriend = originalMinDistanceToFriend + extraDistance;
|
|
minDistanceToEnemy = originalMinDistanceToEnemy + extraDistance;
|
|
} else {
|
|
minDistanceToFriend = originalMinDistanceToFriend;
|
|
minDistanceToEnemy = originalMinDistanceToEnemy;
|
|
}
|
|
}
|
|
|
|
public bool isFollowingTarget ()
|
|
{
|
|
return followingTarget;
|
|
}
|
|
|
|
public bool isUseHalfMinDistanceActive ()
|
|
{
|
|
return useHalfMinDistance;
|
|
}
|
|
public void startOverride ()
|
|
{
|
|
overrideTurretControlState (true);
|
|
}
|
|
|
|
public void stopOverride ()
|
|
{
|
|
overrideTurretControlState (false);
|
|
}
|
|
|
|
public void overrideTurretControlState (bool state)
|
|
{
|
|
pauseAI (state);
|
|
}
|
|
|
|
public void setDistanceToEnemy (float newDistance)
|
|
{
|
|
minDistanceToEnemy = newDistance;
|
|
|
|
originalMinDistanceToEnemy = minDistanceToEnemy;
|
|
}
|
|
|
|
public void setUseDynamicObstacleDetectionState (bool state)
|
|
{
|
|
useDynamicObstacleDetection = state;
|
|
}
|
|
|
|
public void setOriginalUseDynamicObstacleDetection ()
|
|
{
|
|
setUseDynamicObstacleDetectionState (originalUseDynamicObstacleDetection);
|
|
}
|
|
|
|
public void addObjectToIgnoreOnDynamicObstacle (GameObject newObject)
|
|
{
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
addOrRemoveObjectToIgnoreOnDynamicObstacle (newObject, true);
|
|
}
|
|
}
|
|
|
|
public void removeObjectToIgnoreOnDynamicObstacle (GameObject newObject)
|
|
{
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
addOrRemoveObjectToIgnoreOnDynamicObstacle (newObject, false);
|
|
}
|
|
}
|
|
|
|
void addOrRemoveObjectToIgnoreOnDynamicObstacle (GameObject newObject, bool state)
|
|
{
|
|
if (checkCustomListToIgnoreOnDynamicObstacleEnabled) {
|
|
if (state) {
|
|
if (!objectListToIgnoreOnDynamicObstacle.Contains (newObject)) {
|
|
objectListToIgnoreOnDynamicObstacle.Add (newObject);
|
|
}
|
|
} else {
|
|
if (objectListToIgnoreOnDynamicObstacle.Contains (newObject)) {
|
|
objectListToIgnoreOnDynamicObstacle.Remove (newObject);
|
|
}
|
|
}
|
|
|
|
for (int i = objectListToIgnoreOnDynamicObstacle.Count - 1; i >= 0; i--) {
|
|
if (objectListToIgnoreOnDynamicObstacle [i] == null) {
|
|
objectListToIgnoreOnDynamicObstacle.RemoveAt (i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setMinObstacleRotation (float newValue)
|
|
{
|
|
minObstacleRotation = newValue;
|
|
}
|
|
|
|
public void setMediumObstacleRotation (float newValue)
|
|
{
|
|
mediumObstacleRotation = newValue;
|
|
}
|
|
|
|
public void setMaximumObstacleRotation (float newValue)
|
|
{
|
|
maximumObstacleRotation = newValue;
|
|
}
|
|
|
|
public void enableCustomNavMeshSpeed (float newValue)
|
|
{
|
|
customNavMeshSpeed = newValue;
|
|
|
|
useCustomNavMeshSpeed = true;
|
|
}
|
|
|
|
public void disableCustomNavMeshSpeed ()
|
|
{
|
|
useCustomNavMeshSpeed = false;
|
|
}
|
|
|
|
public void enableCustomMinDistance (float newValue)
|
|
{
|
|
useCustomMinDistance = true;
|
|
|
|
customMinDistance = newValue;
|
|
}
|
|
|
|
public void enableHalfMinDistance ()
|
|
{
|
|
useHalfMinDistance = true;
|
|
}
|
|
|
|
public void disableCustomMinDistance ()
|
|
{
|
|
useCustomMinDistance = false;
|
|
}
|
|
|
|
public void setIgnoreGetClosestPositionIfTargetCantBeReachedState (bool state)
|
|
{
|
|
ignoreGetClosestPositionIfTargetCantBeReached = state;
|
|
}
|
|
|
|
public void setUseMinDistanceOffsetItTargetReachedState (bool state)
|
|
{
|
|
useMinDistanceOffsetItTargetReached = state;
|
|
}
|
|
|
|
public void setCheckCustomListToIgnoreOnDynamicObstacleEnabledState (bool state)
|
|
{
|
|
checkCustomListToIgnoreOnDynamicObstacleEnabled = state;
|
|
}
|
|
|
|
|
|
//EDITOR FUNCTIONS
|
|
public void setCheckCustomListToIgnoreOnDynamicObstacleEnabledStateFromEditor (bool state)
|
|
{
|
|
setCheckCustomListToIgnoreOnDynamicObstacleEnabledState (state);
|
|
|
|
updateComponent ();
|
|
}
|
|
|
|
public void setMinDistanceToEnemyFromEditor (float newDistance)
|
|
{
|
|
minDistanceToEnemy = newDistance;
|
|
|
|
updateComponent ();
|
|
}
|
|
|
|
public void updateComponent ()
|
|
{
|
|
GKC_Utils.updateComponent (this);
|
|
|
|
GKC_Utils.updateDirtyScene ("Update AI Navmesh " + gameObject.name, gameObject);
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
void OnDrawGizmos ()
|
|
{
|
|
if (!showGizmo) {
|
|
return;
|
|
}
|
|
|
|
if (GKC_Utils.isCurrentSelectionActiveGameObject (gameObject)) {
|
|
DrawGizmos ();
|
|
}
|
|
}
|
|
|
|
void OnDrawGizmosSelected ()
|
|
{
|
|
DrawGizmos ();
|
|
}
|
|
|
|
//draw the pivot and the final positions of every door
|
|
void DrawGizmos ()
|
|
{
|
|
if (showGizmo) {
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawSphere (lastPathTargetPosition, 1);
|
|
Gizmos.color = Color.green;
|
|
Gizmos.DrawSphere (samplePosition, 1);
|
|
|
|
Gizmos.color = Color.gray;
|
|
|
|
Gizmos.DrawSphere (currentTargetPosition, 0.2f);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} |