Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Trouble with minion Targeting System

Discussion in 'Scripting' started by jdelaay025, Dec 3, 2016.

  1. jdelaay025

    jdelaay025

    Joined:
    Jun 12, 2015
    Posts:
    5
    I'm working on a moba that is a work in progress of course, but I'm having way too much issue with the targeting system. I'm more about the logic of it I guess. I can pretty much put anything together with help from documentation and a little thinking. But, I've come up on a brick wall for this one.

    My minions are supposed to only have five things that they can target. A player, waypoints, another minion, a neutral monster (P v E), and towers of some sort(tower, keeps, heals, core). I will post the code here so I'm not just trying to explain air to you.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class CreepEnemy : MonoBehaviour
    6. {
    7.     #region Global variable Declaration
    8.  
    9.     public float timeTillAttack = 5f;
    10.     public float minDamage = 5f;
    11.     public float maxDamage = 10f;
    12.     public float acceptableSDistance = 5f;
    13.     public float canAgroEnemy = 50f;
    14.     public float outLimitsOfDetection = 1500f;
    15.     public float distanceFromEnemy = 5f;
    16.  
    17.     public float movementSpeed = 4f;
    18.     public float turnSpeed = 3f;
    19.     public float distToEnemy;
    20.     public float distToTower;
    21.  
    22.     public Transform target = null;
    23.     public Transform wayPoint;
    24.     public int wayPointIndex = 0;
    25.     public Transform targetEnemy;
    26.     public Transform tower;
    27.  
    28.     Transform myTransform;
    29.  
    30.     float attackTimer = 5f;
    31.     Animator anim;
    32.     bool running = false;
    33.     bool canAttack = false;
    34.     bool goForTower = false;
    35.  
    36.     float targetingTimer = 2.5f;
    37.     float targetingTimerLimit = 2.5f;
    38.  
    39.  
    40.     float closeEnoughToWP = 0.5f;
    41.  
    42.     #endregion
    43.  
    44.     void Awake()
    45.     {
    46.         myTransform = transform;
    47.         anim = GetComponent<Animator>();
    48.     }
    49.     void Start()
    50.     {
    51.         GameMasterObject.enemyCreeps.Add(myTransform);
    52.         wayPointIndex = WayPointManager.points.Length - 1;
    53.  
    54.     }
    55.     void Update()
    56.     {
    57.         MoveToTarget();
    58.         //Debug.Log(WayPointManager.points.Length - 1);
    59.         #region set attack state      
    60.  
    61.         if (attackTimer > 0)
    62.         {
    63.             attackTimer -= Time.deltaTime;
    64.         }
    65.         else if (attackTimer <= 0 && canAttack)
    66.         {
    67.             if (anim != null)
    68.             {
    69.                 anim.SetTrigger("Attack");
    70.             }
    71.             attackTimer = timeTillAttack;
    72.         }
    73.         #endregion
    74.         FindWayPoints:
    75.         #region move towards a target
    76.  
    77.         #region if targetEnemy is not null
    78.  
    79.         if (targetEnemy != null)
    80.         {
    81.             try
    82.             {
    83.                 distToEnemy = Vector3.Distance(targetEnemy.position, myTransform.position);
    84.                 if (distToEnemy > acceptableSDistance && distToEnemy > canAgroEnemy && distToEnemy < outLimitsOfDetection)
    85.                 {
    86.                     RotateToTarget(wayPoint);
    87.                     canAttack = false;
    88.  
    89.                     #region check for Tower
    90.  
    91.                     if (tower == null)
    92.                     {
    93.                         try
    94.                         {
    95.                             RotateToTarget(wayPoint);
    96.                         }
    97.                         catch (System.Exception e)
    98.                         {
    99.                             Debug.Log(e);
    100.                         }
    101.                     }
    102.                     if (tower != null)
    103.                     {
    104.                         try
    105.                         {
    106.                             RotateToTarget(tower);
    107.  
    108.                             distToTower = Vector3.Distance(tower.position, myTransform.position);
    109.  
    110.                             if (distToTower <= acceptableSDistance)
    111.                             {
    112.                                 canAttack = true;
    113.                             }
    114.                             else
    115.                             {
    116.                                 canAttack = false;
    117.                             }
    118.                         }
    119.                         catch (System.Exception e)
    120.                         {
    121.                             Debug.Log(e);
    122.                         }
    123.                     }
    124.  
    125.                     #endregion
    126.  
    127.  
    128.                 }
    129.                 else if (distToEnemy > acceptableSDistance && distToEnemy <= canAgroEnemy)
    130.                 {
    131.                     RotateToTarget(targetEnemy);
    132.                     canAttack = false;
    133.  
    134.                     //Debug.Log("canAgro");
    135.  
    136.  
    137.                 }
    138.                 else if (distToEnemy <= acceptableSDistance)
    139.                 {
    140.                     //Debug.Log("canAttack");
    141.                    
    142.                     canAttack = true;
    143.                 }
    144.                 else if (distToEnemy > outLimitsOfDetection)
    145.                 {
    146.                     canAttack = false;
    147.                     targetEnemy = null;
    148.                 }
    149.             }
    150.             catch (System.Exception e)
    151.             {
    152.                 goto FindWayPoints;
    153.             }
    154.         }
    155.  
    156.         #endregion
    157.  
    158.         #region if targetEnemy is null      
    159.  
    160.         else if (targetEnemy == null)
    161.         {
    162.             if (tower == null)
    163.             {
    164.                 try
    165.                 {
    166.                     RotateToTarget(wayPoint);
    167.                 }
    168.                 catch (System.Exception e)
    169.                 {
    170.                     Debug.Log(e);
    171.                 }
    172.             }
    173.             if (tower != null)
    174.             {
    175.                 try
    176.                 {
    177.                     RotateToTarget(tower);
    178.  
    179.                     distToTower = Vector3.Distance(tower.position, myTransform.position);
    180.  
    181.                     if (distToTower <= acceptableSDistance)
    182.                     {
    183.                         canAttack = true;
    184.                     }
    185.                     else
    186.                     {
    187.                         canAttack = false;
    188.                     }
    189.                 }
    190.                 catch (System.Exception e)
    191.                 {
    192.                     Debug.Log(e);
    193.                 }
    194.             }
    195.  
    196.             if (targetingTimer <= 0)
    197.             {
    198.                 targetEnemy = FindTargetEnemy();
    199.                 targetingTimer = targetingTimerLimit;
    200.             }
    201.             else if (targetingTimer > 0)
    202.             {
    203.                 targetingTimer -= Time.deltaTime;
    204.             }
    205.         }
    206.  
    207.         #endregion
    208.  
    209.         #region set states
    210.  
    211.         if (target != null)
    212.         {
    213.             if (!canAttack)
    214.             {
    215.                 running = true;
    216.  
    217.             }
    218.             else if (canAttack)
    219.             {
    220.                 running = false;
    221.             }
    222.         }
    223.         else if (target == null)
    224.         {
    225.             canAttack = false;
    226.             running = false;
    227.         }
    228.  
    229.         #endregion
    230.  
    231.         #endregion
    232.     }
    233.     void Attack()
    234.     {
    235.         if (target == null)
    236.             return;
    237.  
    238.         if (tower == null)
    239.         {
    240.             IDamageable enemy = target.GetComponent<IDamageable>();
    241.             if (enemy != null)
    242.             {
    243.                 enemy.TakeDamage(Random.Range(minDamage, maxDamage), target.position);
    244.             }
    245.         }
    246.     }
    247.     void RotateToTarget(Transform _target)
    248.     {
    249.         target = _target;
    250.  
    251.         Vector3 dir = target.position - myTransform.position;
    252.         Quaternion lookDirection = Quaternion.LookRotation(dir);
    253.         Quaternion facingDir = Quaternion.Slerp(myTransform.rotation, lookDirection, Time.deltaTime * turnSpeed);
    254.         Quaternion faceNow = Quaternion.Euler(0f, facingDir.eulerAngles.y, 0f);
    255.  
    256.         myTransform.rotation = faceNow;
    257.     }
    258.     void MoveToTarget()
    259.     {
    260.         if (anim != null)
    261.         {
    262.             anim.SetBool("Running", running);
    263.         }
    264.  
    265.         if (running)
    266.         {
    267.             myTransform.Translate(Vector3.forward * Time.deltaTime * movementSpeed);
    268.         }
    269.     }
    270.     Transform FindTargetEnemy()
    271.     {
    272.         //Debug.Log("Checking for enemies");
    273.  
    274.         Transform tempTarget = null;
    275.         float lastEnemyDist = Mathf.Infinity;
    276.  
    277.         #region if shark lions are here
    278.         if (GameMasterObject.dragonsMonsters.Count > 0)
    279.         {
    280.             for (int j = 0; j < GameMasterObject.enemyCreeps.Count; j++)
    281.             {
    282.                 float dist = Vector3.Distance(myTransform.position, GameMasterObject.dragonsMonsters[j].position);
    283.                 if (dist < lastEnemyDist && dist < outLimitsOfDetection && GameMasterObject.dragonsMonsters[j].gameObject.activeInHierarchy)
    284.                 {
    285.  
    286.                     tempTarget = GameMasterObject.dragonsMonsters[j];
    287.                     lastEnemyDist = dist;
    288.                 }
    289.             }
    290.             acceptableSDistance = 9f;
    291.         }
    292.         #endregion
    293.  
    294.         else if (GameMasterObject.dragonsMonsters.Count <= 0)
    295.         {
    296.             for (int i = 0; i < GameMasterObject.heroCreeps.Count; i++)
    297.             {
    298.  
    299.                 tempTarget = GameMasterObject.heroCreeps[Random.Range(0, GameMasterObject.enemyCreeps.Count - 1)];
    300.  
    301.             }
    302.         }
    303.         return tempTarget;
    304.     }
    305.     void OnTriggerEnter(Collider other)
    306.     {
    307.         if (other.gameObject.tag == "WayPoint")
    308.         {
    309.             wayPoint = other.gameObject.GetComponent<WayPoint>().nextEnemyWayPoint;
    310.         }
    311.  
    312.         if (other.gameObject.tag == "Tower")
    313.         {
    314.             goForTower = true;
    315.             tower = other.gameObject.GetComponentInChildren<TowerHealth>().transform;
    316.  
    317.             acceptableSDistance = other.gameObject.GetComponentInChildren<TowerHealth>().distanceFromMe;
    318.         }
    319.         if (other.gameObject.tag == "Ally")
    320.         {
    321.             targetEnemy = other.gameObject.transform;
    322.  
    323.             acceptableSDistance = distanceFromEnemy;
    324.         }
    325.     }
    326.     void OnCollisionEnter(Collision collision)
    327.     {
    328.         if (collision.gameObject.tag == "Ally")
    329.         {
    330.             Debug.Log("Ally");
    331.             targetEnemy = collision.gameObject.transform;
    332.             acceptableSDistance = distanceFromEnemy;
    333.         }
    334.     }
    335.     void OncollsionStay(Collision collision)
    336.     {
    337.         Debug.Log("Ally");
    338.         targetEnemy = collision.gameObject.transform;
    339.         acceptableSDistance = distanceFromEnemy;
    340.     }
    341. }
    342.  
    ok. So that's all of my minion code.

    So what happens is, they are supposed to choose a random enemy from the list of enemies in my GameMasterObject script. If there is an enemy(another minion), then that is the priority. No one else should come first. Then once that's done, they are supposed to choose another random. They do that just fine. The problem is, they will bump into each other trying to pass and get to another enemy. Well, I set an OnCollisionEnter and Stay for that so that they grab the minion that they just bumped into as their new target enemy. But it doesn't work. Well at least not like I want it to. It's not consistent. And then sometimes they stop and act as if they are attacking something in front of them but they are actually targeting something across the field. The on collision stay should have fixed that.

    Now, I know if I change to trigger, that would fix the problem but I kinda wanted to keep the real colliders for more collsions instead of using trigger detection that let's you pass through. Feel free to take what you want for your game. If implemented without the dynamic change based on collisions, the code works.
     
  2. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    hey jdelaay025,
    the code is a quite hard read (lots of if/else && bools) :) I'm not gonna look for the actually line where it goes wrong, but i do want to share with you that there are better ways of writing this... at the risk you don't want to hear that.
    Get your self into design patterns :) a state machine would come in handy here, among other...
    Sometimes programming is more about a clear and solid structure than al the right lines of code to make it do what you want.
     
  3. jdelaay025

    jdelaay025

    Joined:
    Jun 12, 2015
    Posts:
    5
    Absolutely!!! I'm not a touchy programmer lol I understand there are better ways. I will definitely look into the state machines instead of this situation. I've just been trying to catch every possible situation thus killing readablity. You're absolutely right. Thanks so much for the answer!!! Do you have any games. I love looking at peoples work!!! It helps motivate me to finish what I'm working on!!!
     
  4. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,749
    hahaha i hear you, i have the hardest time finishing games i start. and for my job i mostly have to make demo's so no finishing there...
    you can see some stuff here

    As for your code, i would rewrite. It will save you lots of headache further along. I know most of the time you think: "well it works, but next time I'll do it better and cleaner... " but i learned it's better to rewrite if you think you have a better way, your whole game will improve that way.
     
  5. jdelaay025

    jdelaay025

    Joined:
    Jun 12, 2015
    Posts:
    5
    Absolutely. I'll do that for sure. I need to anyway. I haven't looked at the interfaces tutorial video yet but the scripts look pretty simple to implement. I'll work on this type of organizational coding as it's going to be something that is a part of my life for a long time. I would love to work somewhere making games. Right now I work at a logistics company doing basic business solution coding and business intelligence and analysis. Good stuff and I love my coworkers but they know my finish line is in the gaming industry. My boss has been teaching me so much about development from the stand point of the end user and not just from the coder side. I have to work harder on the stuff he's taught me because what you said reminds me a lot about what my boss says to me about my other work. It has to do more than just work... lol So thank you so much. I look forward to learning more and continuing this process