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);
            }
        }
    }
Beispiel #2
0
    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);
 }