Search Unity

Ranged attack in Unity3D

Discussion in 'Navigation' started by KitPolosa, Aug 23, 2022.

?

Ranged attack in Unity3D

  1. Trigger

    4 vote(s)
    100.0%
  2. AI

    0 vote(s)
    0.0%
  1. KitPolosa

    KitPolosa

    Joined:
    Sep 21, 2020
    Posts:
    2
    The topic is not simple, but I will try to explain clearly. In general, I have two objects: the player and the enemy. The main problem is the enemy, which should start shooting at the player when it approaches him at a certain distance (in short, just start the animation). At first I tried to implement this through Vector 3, as with other ordinary opponents. But he is as stupid and crutch as possible, however, you yourself can see everything in the pinned. I started to implement it more allegedly correctly, through the trigger and the collider (box collider) of the enemy itself. And everything works right as it should, but there is a nuance. The enemy also has boxing implemented through the box collider, the player, hitting which, causes damage to him. There is only one box collider for these two tasks, and since I had to increase this collider so that the enemy could stop in front of the player at a certain distance. Because of this, the player can hit at a great distance (at which the enemy can shoot) from the enemy and the enemy takes damage anyway. I tried to make a separate object the size of the enemy himself and use it as a box to receive damage. Then he already transmits data about receiving damage to the enemy object. But this does not work, all links between scripts and objects are made, but he does not want to transfer data. That is, simply making two colliders for different tasks does not work. In general, here my powers are all. I searched the entire Internet, but I did not find how to implement this mechanic in a different way so that it does not conflict with others. Therefore, I ask the help of the local experts, where I screwed up.
    Code (CSharp):
    1. private Animator ch_animator;
    2.     // Start is called before the first frame update
    3.     void Start()
    4.     {
    5.         myAgent = GetComponent<NavMeshAgent>();
    6.         myAnim = GetComponent<Animator>();
    7.         EnemyH = GetComponent<GDHealth>();
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.         dist = Vector3.Distance(/*checker.*/transform.position, target.transform.position);
    14.         if (dist > range)
    15.         {
    16.             myAgent.enabled = false;
    17.             myAnim.SetBool("Idle", true);
    18.             myAnim.SetBool("Move", false);
    19.             myAnim.SetBool("Attack", false);
    20.         }
    21.         if (dist <= range & dist > atRange)
    22.         {
    23.             myAgent.enabled = true;
    24.             myAgent.SetDestination(target.position);
    25.             myAnim.SetBool("Idle", false);
    26.             myAnim.SetBool("Move", true);
    27.             myAnim.SetBool("Attack", false);
    28.         }
    29.         if (dist <= atRange)
    30.         {
    31.             StartCoroutine(Attack());
    32.         }
    33.         if (PlayerH._health <= 0)
    34.         {
    35.             atRange = 0;
    36.         }
    37.         if (EnemyH._health < 0)
    38.         {
    39.             myAgent.enabled = false;
    40.         }
    41.     }
    42.  
    43.     public IEnumerator Attack()
    44.     {
    45.         yield return new WaitForSeconds(0.5f);
    46.         myAgent.enabled = false;
    47.         myAnim.SetBool("Idle", false);
    48.         myAnim.SetBool("Move", false);
    49.         myAnim.SetBool("Attack", true);
    50.     }
    51.  
    52.     void OnTriggerStay(Collider col)
    53.     {
    54.         if (col.tag == "Player")
    55.         {
    56.             //gameObject.GetComponent<Animator>().SetBool("Attack", true);
    57.             StartCoroutine(Attack());
    58.             transform.LookAt(col.transform.position);
    59.             transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
    60.         }
    61.     }
    62.     void OnTriggerExit(Collider col)
    63.     {
    64.         if (col.tag == "Player")
    65.         {
    66.             myAgent.enabled = true;
    67.             myAgent.SetDestination(target.position);
    68.             myAnim.SetBool("Idle", false);
    69.             myAnim.SetBool("Move", true);
    70.             myAnim.SetBool("Attack", false);
    71.             //gameObject.GetComponent<Animator>().SetBool("Attack", false);
    72.         }
    73.     }
     
  2. jessee03

    jessee03

    Joined:
    Apr 27, 2011
    Posts:
    729
    You probably don't want to use triggers for this but instead colliders and using OnCollisionEnter and OnCollisionStay.

    https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html

    Also found a boxcast. Which seems to be like a raycast or spherecast. You should use this instead. Triggers are just not good for attacks.

    https://docs.unity3d.com/ScriptReference/Physics.BoxCast.html

    With boxcast you can check if you hit a certain tagged object and then call a method inside of a script thats on that object. I use attacks for my game that are AOE like this to hit an enemy.


    Code (CSharp):
    1.             Vector3 center = new Vector3(this.transform.position.x, this.transform.position.y, this.transform.position.z);
    2.             Collider[] hitColliders = Physics.OverlapSphere(center, 60);
    3.             int i = 0;
    4.             while (i < hitColliders.Length)
    5.             {
    6.                 if (hitColliders[i].transform.tag == "Enemy")
    7.                 {
    8.                     if (hitColliders[i].transform.gameObject.GetComponent<Enemy>().isDead == false)
    9.                     {
    10. //Call damage method
    11. hitColliders[i].transform.gameObject.GetComponent<Enemy>().DealDamage(100);
     
    Last edited: Sep 18, 2022