Beispiel #1
0
    // This does ALL the settings of values on aiUtilRecs because anything I set in the Inspector
    //   is not copied when I use GameObject.AddComponent() in ArenaManager
    void SetAIUtilRecs()
    {
        aiUtilRecs = new List <UtilRec>();
        UtilRec ur;

        // Explore
        ur            = new UtilRec();
        ur.stratType  = eStrat.explore;
        ur.enabled    = true;
        ur.utilMinMax = new Vector2(0.0f, 0.4f);
        ur.curveFunc  = x => x;
        ur.strat      = new JBS_Explore(ur);
        aiUtilRecs.Add(ur);

        // Wander
        ur            = new UtilRec();
        ur.stratType  = eStrat.wander;
        ur.enabled    = true;
        ur.utilMinMax = new Vector2(0.3f, 0.3f);
        ur.curveFunc  = x => x;
        ur.strat      = new JBS_Wander(ur);
        aiUtilRecs.Add(ur);

        // I've removed the rest of these for you to figure out yourself. – JGB
    }
Beispiel #2
0
 public JBStrat(UtilRec ur)
 {
     uRec = ur;
 }
Beispiel #3
0
 public JBS_Wander(UtilRec ur) : base(ur)    // ": base(ur)" calls the JBStrat constructor and passes in ur
 {
 }
Beispiel #4
0
    /// <summary>
    /// The main method that you should override in your Agent subclass is AIUpdate().
    /// </summary>
    /// <param name="inputs"></param>
    public override void AIUpdate(List <SensoryInput> inputs)
    {
        base.AIUpdate(inputs);
        // THE FIRST LINE OF YOUR AIUpdate() override MUST be: base.AIUpdate(inputs);
        // AIUpdate copies inputs into sensed

        if (!inited)
        {
            Init();
        }

        // AIUpdate copies inputs into sensed
        SensedObject sawSomeone = null;

        toClosestEnemy = Vector3.one * 1000;
        closestEnemy   = null;
        foreach (SensoryInput si in sensed)
        {
            switch (si.sense)
            {
            case SensoryInput.eSense.vision:
                if (si.type == eSensedObjectType.enemy)
                {
                    sawSomeone = si.obj;
                    // Check to see whether the Enemy is within the firing arc
                    // The dot product of two vectors is the magnitude of A * the magnitude of B * cos(the angle between them)
                    Vector3 toEnemy = si.pos - pos;
                    if (toEnemy.magnitude < toClosestEnemy.magnitude)
                    {
                        toClosestEnemy = toEnemy;
                        closestEnemy   = si.obj as Agent;
                    }
//                        float dotProduct = Vector3.Dot(headTrans.forward, toEnemy.normalized);
//                        float theta = Mathf.Acos(dotProduct) * Mathf.Rad2Deg;
//                        if (theta <= ArenaManager.AGENT_SETTINGS.bulletAimVarianceDeg) {
//                            if (ammo > 0) {
//                                Fire();
//                            }
//                        }
                }
                break;
            }

            // Regardless of the sense type, I want to know if it was a PickUp and what it was
            if (si.type == eSensedObjectType.item)
            {
                PickUp.eType puType = (si.obj as PickUp).puType;
                // Check the position of this item relative to the position of known item SpawnPoints
                if (MEM[PickUp.eType.none].Count > 0)
                {
                    SpawnPoint foundSP = null;
                    foreach (SpawnPoint sp in MEM[PickUp.eType.none])
                    {
                        if ((sp.pos - si.obj.pos).magnitude < 0.1f)   // We found it!
                        {
                            foundSP = sp;
                            break;
                        }
                    }
                    if (foundSP != null)
                    {
                        MEM[PickUp.eType.none].Remove(foundSP);
                        if (!MEM.ContainsKey(puType))
                        {
                            MEM.Add(puType, new List <SpawnPoint>());
                        }
                        MEM[puType].Add(foundSP);
                    }
                    else
                    {
                        // No big deal, this just means that we already know about the SpawnPoint at that loc.
                    }
                }
            }

            if (si.type == eSensedObjectType.enemy)
            {
                // tracker.Track(si);
            }
        }
        if (sawSomeone == null)
        {
            LookCenter();
//            leadObj = null;
        }
        else
        {
            // Turn head to track enemies
            // How far is the enemy from current headTrans.forward
            float dotProdToClosest = Vector3.Dot(toClosestEnemy.normalized, headTrans.forward);
            // Account for the NaN errors that happen if Mathf.Acos(x) is called for x outside of -1 < x < 1
            dotProdToClosest = Mathf.Clamp(dotProdToClosest, -1, 1);
            float angToClosest = Mathf.Acos(dotProdToClosest) * Mathf.Rad2Deg;
            // This shouldn't be needed because of the Clamp above
//            if (Mathf.Approximately(dotProdToClosest,1)) {
//                angToClosest = 0;
//            } else if (Mathf.Approximately(dotProdToClosest,-1)) {
//                angToClosest = 180;
//            } else {
//                angToClosest = Mathf.Acos( dotProdToClosest ) * Mathf.Rad2Deg;
//            }
//            // The following is here because the Acos of 1 is NaN.
//            if (float.IsNaN(angToClosest)) {
//                angToClosest = 0;
//            }
            // A dot product of toEnemy and transform.right will tell you whether to look left or right
            float posNeg = (Vector3.Dot(toClosestEnemy.normalized, headTrans.right) < 0) ? -1 : 1;
            angToClosest *= posNeg;
//            print("AngleToClosest: "+angToClosest);
            LookTheta(angToClosest);
            if (angToClosest <= ArenaManager.AGENT_SETTINGS.bulletAimVarianceDeg)
            {
                if (ammo > 0)
                {
                    Fire();
                }
            }
        }



        // Utility AI – Iterate through all the aiUtilRecs and find the one with the highest utility
        float   maxUtil  = -1;
        UtilRec uRecBest = null;

        foreach (UtilRec ur in aiUtilRecs)
        {
            if (ur.strat.Utility(this) > maxUtil)
            {
                uRecBest = ur;
                maxUtil  = ur.u;
            }
        }
        aiU     = maxUtil;
        aiStrat = uRecBest.stratType;

        if (uRecBest.dest != nmAgent.destination && health > 0)
        {
            nmAgent.SetDestination(uRecBest.dest);
            navMeshTargetLoc = uRecBest.dest;
        }

        // report on knowledge
        spawnPointKnowledge.x = MEM.ContainsKey(PickUp.eType.none) ? MEM[PickUp.eType.none].Count : 0;
        spawnPointKnowledge.y = MEM.ContainsKey(PickUp.eType.health) ? MEM[PickUp.eType.health].Count : 0;
        spawnPointKnowledge.z = MEM.ContainsKey(PickUp.eType.ammo) ? MEM[PickUp.eType.ammo].Count : 0;



        if (health > 0)
        {
            nmAgent.SetDestination(nmAgent.destination);
        }
    }