Search Unity

I need guidance please.

Discussion in 'Scripting' started by panim0_unity, Jan 16, 2020 at 2:46 PM.

  1. panim0_unity

    panim0_unity

    Joined:
    Nov 13, 2018
    Posts:
    32
    Hi, the code below is kind of long way of doing what im trying to do. There is 3 allies and 3 enemies right now but I'll add more in future so i need to add more agents and enemyplayer gameobjects to this script.
    I need an advice here to shorten these lines, any suggestion,guide me a bit please. Basically you select which ally will attack to which enemy when round starts and repeats it 2 times.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. using UnityEngine.UI;
    6.  
    7.  
    8. public class PlayerControls : MonoBehaviour
    9. {
    10.  
    11.     GameObject closest;
    12.  
    13.     NavMeshAgent agent1;
    14.     GameObject agent1G;
    15.     bool agent1select;
    16.     NavMeshAgent agent2;
    17.     GameObject agent2G;
    18.     bool agent2select;
    19.     NavMeshAgent agent3;
    20.     GameObject agent3G;
    21.     bool agent3select;
    22.  
    23.     GameObject selectionQuad1;
    24.     GameObject selectionQuad2;
    25.     GameObject selectionQuad3;
    26.  
    27.     GameObject enemyPlayer1;
    28.     bool enemy1select;
    29.     GameObject enemyPlayer2;
    30.     bool enemy2select;
    31.     GameObject enemyPlayer3;
    32.     bool enemy3select;
    33.  
    34.     Combat combat1;
    35.     Combat combat2;
    36.     Combat combat3;
    37.  
    38.     Vector3 pos1;
    39.     Vector3 pos2;
    40.     Vector3 pos3;
    41.  
    42.     Quaternion rot1;
    43.     Quaternion rot2;
    44.     Quaternion rot3;
    45.  
    46.  
    47.     bool canClick;
    48.  
    49.     [SerializeField]
    50.     private Text waveTimer;
    51.  
    52.     Animator animator1;
    53.     Animator animator2;
    54.     Animator animator3;
    55.  
    56.  
    57.  
    58.  
    59.  
    60.     bool timeToAttack;
    61.     void Start()
    62.     {
    63.      
    64.         agent1select = false;
    65.         agent2select = false;
    66.         agent3select = false;
    67.  
    68.  
    69.         enemy1select = false;
    70.         enemy2select = false;
    71.         enemy3select = false;
    72.  
    73.         canClick = true;
    74.      
    75.         timeToAttack = false;
    76.  
    77.      StartCoroutine(Countdown(15));
    78.  
    79.  
    80.  
    81.     }
    82.  
    83.  
    84.  
    85.     void FixedUpdate()
    86.     {
    87.    
    88.        
    89.  
    90.         if (Input.GetMouseButtonDown(0)&&canClick==true)
    91.         {
    92.            
    93.                 RaycastHit hit = new RaycastHit();
    94.                 bool hitb = Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit);
    95.                 if (hitb)
    96.                 {
    97.                     Debug.Log("Hit " + hit.transform.gameObject.name);
    98.                     if (hit.transform.gameObject.tag == "Player1")
    99.                     {
    100.                         Debug.Log("Working until here");
    101.                         if (agent1select == false)
    102.                         {
    103.                             Debug.Log("Clicked");
    104.                             agent1G = hit.transform.gameObject;
    105.                             animator1 = agent1G.GetComponent<Animator>();
    106.                             agent1 = hit.transform.gameObject.GetComponent<NavMeshAgent>();
    107.                             pos1 = agent1G.transform.position;
    108.                             rot1 = agent1G.transform.rotation;
    109.                             Debug.Log("agent 1 selected");
    110.                             agent1select = true;
    111.                             selectionQuad1 = agent1G.transform.GetChild(2).gameObject;
    112.                             selectionQuad1.SetActive(true);
    113.  
    114.                         }
    115.                         else if (agent1select && agent2select == false)
    116.                         {
    117.                             agent2G = hit.transform.gameObject;
    118.                             animator2 = agent2G.GetComponent<Animator>();
    119.                             agent2 = hit.transform.gameObject.GetComponent<NavMeshAgent>();
    120.                             pos2 = agent2G.transform.position;
    121.                             rot2 = agent2G.transform.rotation;
    122.                             Debug.Log("agent 2 selected");
    123.                             agent2select = true;
    124.                             selectionQuad1.SetActive(false);
    125.                             selectionQuad2 = agent2G.transform.GetChild(2).gameObject;
    126.                             selectionQuad2.SetActive(true);
    127.                         }
    128.                         else if (agent2select && agent3select == false)
    129.                         {
    130.                             agent3G = hit.transform.gameObject;
    131.                             animator3 = agent3G.GetComponent<Animator>();
    132.                             agent3 = hit.transform.gameObject.GetComponent<NavMeshAgent>();
    133.                             pos3 = agent3G.transform.position;
    134.                             rot3 = agent3G.transform.rotation;
    135.                             Debug.Log("agent 3 selected");
    136.                             agent3select = true;
    137.                             selectionQuad2.SetActive(false);
    138.                             selectionQuad3 = agent3G.transform.GetChild(2).gameObject;
    139.                             selectionQuad3.SetActive(true);
    140.                         }
    141.  
    142.  
    143.                     }
    144.                     else
    145.                     {
    146.                         Debug.Log("no hit");
    147.                     }
    148.                 }
    149.            
    150.         }
    151.         if (Input.GetMouseButtonDown(0)&&canClick==true)
    152.         {
    153.          
    154.                 RaycastHit hit2 = new RaycastHit();
    155.  
    156.                 if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit2))
    157.                 {
    158.                     if (hit2.transform.gameObject.tag == "Player")
    159.                     {
    160.                         if (enemy1select == false&&agent1select==true)
    161.                         {
    162.                             enemyPlayer1 = hit2.transform.gameObject;
    163.                             combat1 = enemyPlayer1.GetComponent<Combat>();
    164.                             Debug.Log("Enemy1 Clicked");
    165.                             enemy1select = true;
    166.                         }
    167.                         else if (enemy1select && enemy2select == false&&agent2select==true)
    168.                         {
    169.                             enemyPlayer2 = hit2.transform.gameObject;
    170.                             combat2 = enemyPlayer2.GetComponent<Combat>();
    171.                             Debug.Log("Enemy2 Clicked");
    172.                             enemy2select = true;
    173.                         }
    174.                         else if (enemy2select && enemy3select == false&&agent3select==true)
    175.                         {
    176.                             enemyPlayer3 = hit2.transform.gameObject;
    177.                             combat3 = enemyPlayer3.GetComponent<Combat>();
    178.                             Debug.Log("Enemy 3 Clicked");
    179.                             enemy3select = true;
    180.                             selectionQuad3.SetActive(false);
    181.                         }
    182.  
    183.  
    184.  
    185.                     }
    186.                 }
    187.            
    188.         }
    189.  
    190.         if (timeToAttack==true)
    191.         {
    192.        
    193.  
    194.             if (enemy1select)
    195.             {
    196.                 agent1.SetDestination(enemyPlayer1.transform.position);
    197.                 FaceTarget1();
    198.                 if (combat1.isDeath == true)
    199.                 {
    200.                     enemyPlayer1 = null;
    201.                     enemyPlayer1 = FindClosestEnemy().transform.gameObject;
    202.                     agent1.SetDestination(enemyPlayer1.transform.position);
    203.                 }
    204.             }
    205.             if (enemy2select)
    206.             {
    207.                 agent2.SetDestination(enemyPlayer2.transform.position);
    208.                 FaceTarget2();
    209.                 if (combat2.isDeath == true)
    210.                 {
    211.                     enemyPlayer2 = null;
    212.                     enemyPlayer2 = FindClosestEnemy().transform.gameObject;
    213.                     agent2.SetDestination(FindClosestEnemy().transform.position);
    214.                 }
    215.             }
    216.  
    217.             if (enemy3select)
    218.             {
    219.                 agent3.SetDestination(enemyPlayer3.transform.position);
    220.                 FaceTarget3();
    221.                 if (combat3.isDeath == true)
    222.                 {
    223.                     enemyPlayer3 = null;
    224.                     enemyPlayer3 = FindClosestEnemy().transform.gameObject;
    225.                     agent3.SetDestination(FindClosestEnemy().transform.position);
    226.                 }
    227.             }
    228.          
    229.         }
    230.         if (timeToAttack)
    231.         {
    232.             Debug.Log("It is false");
    233.         }
    234.  
    235.    
    236.         if (enemyPlayer1 != null && agent1G != null)
    237.         {
    238.             float distance1 = Vector3.Distance(enemyPlayer1.transform.position, agent1G.transform.position);
    239.             if (distance1 <= 7)
    240.             {
    241.                 animator1.SetBool("Attack", true);
    242.             animator1.speed = 1.5f;
    243.             }
    244.         }
    245.        
    246.        
    247.  
    248.          
    249.      
    250.         if (enemyPlayer2 != null && agent2G != null)
    251.         {
    252.             float distance2 = Vector3.Distance(enemyPlayer2.transform.position, agent2G.transform.position);
    253.             if (distance2 <= 7)
    254.             {
    255.  
    256.                 animator2.SetBool("Attack", true);
    257.                 animator2.speed = 1.5f;
    258.             }
    259.         }
    260.      
    261.         if (enemyPlayer3 != null && agent3G != null)
    262.         {
    263.             float distance3 = Vector3.Distance(enemyPlayer3.transform.position, agent3G.transform.position);
    264.             if (distance3 <= 7)
    265.             {
    266.              
    267.                 animator3.SetBool("Attack", true);
    268.                 animator3.speed = 1.5f;
    269.             }
    270.         }
    271.        
    272.     }
    273.  
    274.     IEnumerator Countdown(int seconds)
    275.     {
    276.         canClick = true;
    277.         waveTimer = GameObject.Find("Canvas/Timer").GetComponent<Text>();
    278.         int counter = seconds;
    279.         int counter2 = seconds+5;
    280.        
    281.         while (counter > 0)
    282.         {
    283.            yield return new WaitForSeconds(1);
    284.             counter--;
    285.          
    286.             waveTimer.text = "" + counter;
    287.  
    288.         }
    289.         if (counter == 0)
    290.         {
    291.             timeToAttack = true;
    292.             canClick = false;
    293.             counter = seconds+5;
    294.         }
    295.         while (counter > 0)
    296.         {
    297.             yield return new WaitForSeconds(1);
    298.             counter--;
    299.             waveTimer.text = "" + counter;
    300.  
    301.             if (counter == 0)
    302.             {
    303.  
    304.                 timeToAttack = false;
    305.                 Debug.Log("timeToAttack= "+timeToAttack);
    306.                 canClick = true;
    307.  
    308.  
    309.                 Debug.Log("Fight Over!");
    310.                 if (agent1G != null)
    311.                 {
    312.                     agent1.isStopped = true;
    313.                     animator1.SetBool("Attack", false);
    314.                     agent1G.transform.position = pos1;
    315.                     agent1G.transform.rotation = rot1;
    316.                 }
    317.                 if (agent2G != null)
    318.                 {
    319.                     agent2.isStopped = true;
    320.                     animator2.SetBool("Attack", false);
    321.                     agent2G.transform.position = pos2;
    322.                     agent2G.transform.rotation = rot2;
    323.                 }
    324.                 if (agent3G != null)
    325.                 {
    326.                     agent3.isStopped = true;
    327.                     animator3.SetBool("Attack", false);
    328.                     agent3G.transform.position = pos3;
    329.                     agent3G.transform.rotation = rot3;
    330.                 }
    331.                 agent1 = null;
    332.                 agent1G = null;
    333.                 agent1select = false;
    334.                 agent2 = null;
    335.                 agent2G = null;
    336.                 agent2select = false;
    337.                 agent3 = null;
    338.                 agent3G = null;
    339.                 agent3select = false;
    340.  
    341.  
    342.                 enemyPlayer1 = null;
    343.                 enemy1select = false;
    344.                 enemyPlayer2 = null;
    345.                 enemy2select = false;
    346.                 enemyPlayer3 = null;
    347.                 enemy3select = false;
    348.                 counter = seconds;
    349.             }
    350.         }
    351.         while (counter > 0)
    352.         {
    353.             yield return new WaitForSeconds(1);
    354.             counter--;
    355.  
    356.             waveTimer.text = "" + counter;
    357.  
    358.         }
    359.         if (counter == 0)
    360.         {
    361.             timeToAttack = true;
    362.             canClick = false;
    363.             counter = seconds+5;
    364.         }
    365.         while (counter > 0)
    366.         {
    367.             yield return new WaitForSeconds(1);
    368.             counter--;
    369.             waveTimer.text = "" + counter;
    370.  
    371.             if (counter == 0)
    372.             {
    373.  
    374.                 timeToAttack = false;
    375.                 Debug.Log("timeToAttack= " + timeToAttack);
    376.                 canClick = true;
    377.  
    378.  
    379.                 Debug.Log("Fight Over!");
    380.                 if (agent1G != null)
    381.                 {
    382.                     agent1.isStopped = true;
    383.                     animator1.SetBool("Attack", false);
    384.                     agent1G.transform.position = pos1;
    385.                     agent1G.transform.rotation = rot1;
    386.                 }
    387.                 if (agent2G != null)
    388.                 {
    389.                     agent2.isStopped = true;
    390.                     animator2.SetBool("Attack", false);
    391.                     agent2G.transform.position = pos2;
    392.                     agent2G.transform.rotation = rot2;
    393.                 }
    394.                 if (agent3G != null)
    395.                 {
    396.                     agent3.isStopped = true;
    397.                     animator3.SetBool("Attack", false);
    398.                     agent3G.transform.position = pos3;
    399.                     agent3G.transform.rotation = rot3;
    400.                 }
    401.                 agent1 = null;
    402.                 agent1G = null;
    403.                 agent1select = false;
    404.                 agent2 = null;
    405.                 agent2G = null;
    406.                 agent2select = false;
    407.                 agent3 = null;
    408.                 agent3G = null;
    409.                 agent3select = false;
    410.  
    411.                 enemyPlayer1 = null;
    412.                 enemy1select = false;
    413.                 enemyPlayer2 = null;
    414.                 enemy2select = false;
    415.                 enemyPlayer3 = null;
    416.                 enemy3select = false;
    417.                 counter = seconds;
    418.             }
    419.         }
    420.  
    421.     }
    422.  
    423.  
    424.  
    425.     #region faceTarget
    426.     void FaceTarget1()
    427.     {
    428.         Vector3 direction = (enemyPlayer1.transform.position - agent1.transform.position).normalized;
    429.         Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
    430.         agent1.transform.rotation = Quaternion.Slerp(agent1.transform.rotation, lookRotation, Time.deltaTime * 10f);
    431.     }
    432.  
    433.     void FaceTarget2()
    434.     {
    435.         Vector3 direction = (enemyPlayer2.transform.position - agent2.transform.position).normalized;
    436.         Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
    437.         agent2.transform.rotation = Quaternion.Slerp(agent2.transform.rotation, lookRotation, Time.deltaTime * 10f);
    438.     }
    439.  
    440.     void FaceTarget3()
    441.     {
    442.         Vector3 direction = (enemyPlayer3.transform.position - agent3.transform.position).normalized;
    443.         Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
    444.         agent3.transform.rotation = Quaternion.Slerp(agent3.transform.rotation, lookRotation, Time.deltaTime * 10f);
    445.     }
    446.     #endregion
    447.  
    448.  
    449.     #region findClosest
    450.     GameObject FindClosestEnemy()
    451.     {
    452.         GameObject[] gos;
    453.         gos = GameObject.FindGameObjectsWithTag("Player");
    454.        
    455.         float distance = Mathf.Infinity;
    456.         Vector3 position = transform.position;
    457.         foreach (GameObject go in gos)
    458.         {
    459.             Vector3 diff = go.transform.position - position;
    460.             float curDistance = diff.sqrMagnitude;
    461.             if (curDistance < distance)
    462.             {
    463.                 closest = go;
    464.                 distance = curDistance;
    465.             }
    466.         }
    467.         return closest ;
    468.     }
    469.     #endregion
    470. }
    471.  
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    1,984
    Having different numbered variables for each entity and then writing tons of redundant code for each combination is completely unnecessary and will make your code impossible to work with. There are programming tools for working with groups of the same object.
    You should write a class or a struct that has all of the information for one single ally or enemy and then make a list or an array of these.

    You should research C# arrays:
    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/
    and lists:
    https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.8

    The array example shows how to use an array of ints but you can just as well make an array of GameObjects or whatever script your ally or enemy uses.
     
  3. panim0_unity

    panim0_unity

    Joined:
    Nov 13, 2018
    Posts:
    32
    I thought about that too but just I could not figure out how to make this click and select thing happen using arrays or list.
    so maybe rather than selecting wich to wich I will make auto select by using find closest. but if you may suggest a way of doşng selection that would be great. Sorry I am actuallny not new to this but I have two teams to handle so my braind kinda stopped working :)
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    7,058
    A few notes not related to your specific question:

    1) Don't used FixedUpdate for anything that's not physics-related. For input specifically, it will cause a lot of problems (as just one example, GetMouseButtonDown may return true for multiple FixedUpdates in a row if these FixedUpdates happen on the same frame.... or it may miss input entirely if your framerate is high enough that FixedUpdate isn't getting run every frame). Besides the input issues, anything in FixedUpdate has the potential to slow your game down exponentially, because the more the game slows down the more times FU needs to be called each frame. A more detailed explanation of this here. Long story short: only used FixedUpdate for physics-related code, period.
    2) GameObject tags suck. It's a badly designed, non-extensible system, and if you use it you'll just code yourself into corners. Avoid.

    For the actual question:
    I was going to write a way to redo your existing logic with a class and an array, but honestly I think the problem isn't really with your data structures but with your algorithm itself. (I mean, having those data structures would help make your algorithm more readable and extensible, but the things you need to do here don't really call for that, IMO.)

    STEP 1: First thing I'd do is to make a script that goes on each player and enemy object. If you want, you can use inheritance so that they share a type but also have their own type. You may already have a script like this, and if so, you can use it. And this script doesn't need to actually have any functionality of its own (yet) - here I'm mostly going to use it as fodder for GetComponent and the like. (I find this kind of thing much more useful as a "tag" system than Unity's GameObject.tag system, because A) it allows you to apply multiple tags per object, B) you can find objects tagged in the children of a given object, and C) the tags can use inheritance. The downside is that it's very very slightly slower, but as long as checking for tags isn't something that happens a thousand times per frame this isn't a difference that matters, and the added functionality is more than worth it.)

    So let's do this:
    Code (csharp):
    1. //each of these in its own script file
    2. public class SelectableUnit : MonoBehaviour {
    3. }
    4.  
    5. public class SelectablePlayer : SelectableUnit {
    6. }
    7.  
    8. public class SelectableEnemy : SelectableUnit {
    9. }
    Attach the appropriate script of these to each of your enemy and player objects - if your units have multiple parented GameObjects, attach the script to the one that contains the collider that you use for raycasting. (Probably the same GameObject you have tagged as Player1, Player2, etc)

    STEP 2: Now let's look at your selection code. You have a lot of different variables, and I think those are all pretty unnecessary. You should be able to boil this down to two things:
    1) Which, if any, friendly unit is selected?
    2) Which, if any, enemy unit is selected?
    Which we can represent as:
    Code (csharp):
    1. public SelectablePlayer selectedFriendlyUnit;
    2. public SelectableEnemy selectedEnemyUnit;
    STEP 3: Now let's take a look at Update. You do a raycast, good. Now, instead of checking the gameobject's tag, let's use the scripts we attached in step 1, like this:
    Code (csharp):
    1.  
    2. if (Input.GetMouseButtonDown(0)&&canClick==true)
    3.         {
    4.            
    5.                 RaycastHit hit = new RaycastHit();
    6.                 bool hitb = Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit);
    7.                 if (hitb)
    8.                 {
    9.                     Debug.Log("Hit " + hit.transform.gameObject.name);
    10.                     SelectablePlayer hitUnit = hit.gameObject.GetComponent<SelectablePlayer>();
    11.                     if (hitUnit != null)
    12.                     {
    13.                          selectedFriendlyUnit = hitUnit;
    14.                     }
    And just like that, you have selected an object - any object! At this point, if you want to do stuff like show an indicator of being selected, you can add a function to SelectableUnit to handle this, and just call it here using selectedFriendlyUnit.SetSelectionQuadVisible(true) or something like that. If it's on SelectableUnit, you don't need multiple copies of code.

    STEP 4: Now that we have an object selected, you can use the same logic to select the enemy you want to attack. You should be able to use the same logic we've used already to select this unit, so I'm going to leave that as an exercise for you.

    STEP 5: When it's time to attack, you should now be able to just use selectedFriendlyUnit and selectedEnemyUnit directly.

    Does all this make sense?
     
  5. panim0_unity

    panim0_unity

    Joined:
    Nov 13, 2018
    Posts:
    32
    much appreciated, REALLY...
     
  6. panim0_unity

    panim0_unity

    Joined:
    Nov 13, 2018
    Posts:
    32
    You said I should not use GameObject.tag system but I forgot to mention that this is going to be a multiplayer game so enemy units are somebodys friendly units, I use photon 2 like "if(photon.IsMine) tag=player1" like this. I deleted photon parts in this script, Im really appriciated for your time here but I guess I made you waste it for this so, really sorry about it
     
unityunity