private void Patrol() { // === Patrol === if (patrolEnabled == true) { // It returns the next transform only when the object has reached its current target. Transform next = patrolPath.CheckAndHandleTargetReached(patrolThresholdDistance); if (next != null) { navMeshAgent.SetDestination(next.position); } } // === Find Hostile === Actor target = FindNearestVisibleHostile(); if (target != null) { lockedTarget = target; StartTransitionTo(State.ATTACK); } else { // === Find Suspecious Point === AttractionSource source = FindNearestAttraction(); if (source != null) { Debug.Log(source); TargetLostAtPosition(source.transform.position); StartTransitionTo(State.ATTACK); } } }
void Awake() { lineRenderer = CommonUtil.GetComponentFromSelfOrChildren <LineRenderer>(this); // Make attraction. AI use this to check attraction point. attractionSource = gameObject.AddComponent <AttractionSource>(); AttractionSourceManager.Register(attractionSource); bodyToAimRelative = weaponAimPoint.position - transform.position; }
// ==== Life span ==== protected override void Awake() { base.Awake(); motor = GetComponent <PlayerMotor>(); CommonUtil.IfNullLogError <PlayerMotor>(motor); weaponManager = GetComponent <PlayerWeaponManager>(); CommonUtil.IfNullLogError <PlayerWeaponManager>(weaponManager); attractionSource = gameObject.AddComponent <AttractionSource>(); AttractionSourceManager.Register(attractionSource); ikController = GetComponentInChildren <AvatarIKController>(); }
private AttractionSource FindNearestAttraction() { AttractionSource tgt = null; float distance, actualNoiseVolume; float cmp = float.MaxValue; // Traverse each actor to get its [AttractionSource] foreach (AttractionSource src in AttractionSourceManager.attractionSources) { // Find loudest noise source position. if (src != null) { distance = Vector3.Distance(src.transform.position, transform.position); actualNoiseVolume = CommonUtil.CalcNoiseAfterDecay(src.currentAttraction, distance); if (actualNoiseVolume > noiseDetectThreshold && actualNoiseVolume < cmp) { cmp = actualNoiseVolume; tgt = src; } } } return(tgt); }
// @Warning: lossy design! private void Attack() { // === Target insight === if (isTargetLost == false) { // Do possible retarget /* * Actor target = FindNearestVisibleHostile(); * if(target != null) { * lockedTarget = target; * } */ // Face towards target navMeshAgent.updateRotation = false; OrientTowardsTarget(lockedTarget); if (!IsVisible(lockedTarget)) { // Target already lost Debug.Log("Lost"); TargetLostAtPosition(lockedTarget.transform.position); } else { // Target not lost // Already in attack angle. if (angleToTarget < attackAngle) { if (distanceToTarget < minAttackRange) { // Too close, move back. navMeshAgent.isStopped = false; navMeshAgent.SetDestination(transform.position + -transform.forward * stepBackAmount); } else if (distanceToTarget > maxAttackRange) { // Too far, move close. Walk backward without automatic rotation. navMeshAgent.isStopped = false; navMeshAgent.SetDestination(lockedTarget.transform.position); } else { // Start to attack navMeshAgent.isStopped = true; shootTransform.rotation = Quaternion.LookRotation(lockedTarget.transform.position - transform.position); // Randomize shooting to make AI stupid and inaccurate. if (Random.Range(0f, 1f) < shootingAccuracy) { weaponData.TryShoot(shootTransform); } else { // Inaccurate fire, has a big possibility to miss. float yBiasAngle = Random.Range(-biasAngle, biasAngle); float zBiasAngle = Random.Range(-biasAngle, biasAngle); Quaternion originalRotation = shootTransform.rotation; shootTransform.rotation = Quaternion.Euler(0, yBiasAngle, zBiasAngle) * shootTransform.rotation; weaponData.TryShoot(shootTransform); shootTransform.rotation = originalRotation; } } } } } else { // === Target lost === lockedTarget = null; navMeshAgent.updateRotation = true; navMeshAgent.isStopped = false; // Do target find // Target might change. Actor target = FindNearestVisibleHostile(); if (target != null) { lockedTarget = target; isTargetLost = false; } else { // No visible target. Find some evidence AttractionSource source = FindNearestAttraction(); if (source != null) { // Detected noise Debug.Log(source); TargetLostAtPosition(source.transform.position); } else { // Go to target if (Vector3.Distance(transform.position, lastKnownPosition) > targetReachThreshold) { navMeshAgent.SetDestination(lastKnownPosition); } else { // Already reached destination, but still no evidence. if (Time.time - lastTargetLostTime > maxTargetLostTime) { StartTransitionTo(State.PATROL); navMeshAgent.SetDestination(patrolPath.GetNextTransform().position); } else { // Do random orientation if (lastThinkTime + 2f < Time.time) { lastThinkTime = Time.time; randomQuaternion = Quaternion.Euler(0, Random.Range(90, 180) * (Random.Range(0, 2) == 0?-1:1), 0) * transform.rotation; } else { OrientTowardsQuaternion(randomQuaternion); } } } } } } // Debug Debug.DrawLine(transform.position, lastKnownPosition, Color.blue); }
public static void Register(AttractionSource src) { attractionSources.Add(src); }
public static void Unregister(AttractionSource src) { attractionSources.Remove(src); }