Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

AI Prefab Issues

Discussion in 'Scripting' started by PhantomProgramming, Jan 21, 2019.

  1. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    Hey there! I'm trying to make a goofy battle simulator game but I'm having trouble with AI.
    I have it so if the enemy touches a trigger radius around the player they chase him. But they don't stop chasing him and they don't attack the player's teammates (also AI). if somebody knows how to make a script that will also make the enemy chase the teammates without using NavMesh that'd be great!
    Enemiesattackonlyplayer.PNG
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    You probably won't get a ton of help with questions like this (where you're just asking someone to write all the code for you). I'd start by googling for AI approaches you could take, or see if there's something on the Asset Store. Create a thread when you have a more specific question on how to proceed.

    In general, the tricky thing about AI pathfinding is obstacle avoidance. If you don't care about that (allow your enemies to walk through walls) you could just move the AI's position a certain distance closer to the player each frame until they're sufficiently close. If you want them to walk around obstacles, that's much more difficult. What's your reasoning for not using NavMesh? What about some other pathfinding asset?
     
  3. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    Sorry I have no problem with tracking the player its tracking other tagged objects in the world, any idea on how to make a gameobject chase another one ontrigger?
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    It really depends on how complex your world is. If it's just some big flat space, with no up and downs, you'd just compute a new position for your AI agent that moves it closer to the player, such as using Vector3.MoveTowards, which you'd call in the Update method. But chances are you have obstacles, hills, ledges, stairs, or some other things besides a huge flat plane, in which case the problem becomes much more difficult. Can your agent jump? Can your agent walk over certain objects, but gets stuck on others?

    Navigation and pathfinding a really non-trivial things to implement. It might sound simple to want to have your AI "chase" the player, but there's a lot of stuff going on with such behavior. Again, what's the reason for not using Navmesh, which does a lot of this stuff for you?
     
  5. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    I'm not sure you heard me, they already track the player fine.
    I need them to track other gameobjects with tags in the world.
    I need an enemy to touch a teammates collider and chase that object, not the player.
    If you need more of a reference:
    https://gamejolt.com/games/BattleSimulatorBeta/391319
     
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    You should show what code you're using. You're asking a very specific question and giving extremely vague information. What does "they already track the player fine" mean? Are you already using some navigation solution? If you are, and it's targetting the "player's" position, what difficulty are you having extending that code to track the position of other things besides the player?
     
  7. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    Sorry, they track the player with Vector3.MoveTowards and that works well. I want them to be able to chase other tagged objects in the world, like a teammate prefab without having to write out thirty different gameobjects for the friendly.
    Here's my code if this helps:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. public class Enemy : MonoBehaviour
    6. {
    7.     public Transform[] Friendly;
    8.     public bool hard;
    9.     public float currentHealth = 3;
    10.     public float maxSpeed = 12;
    11.     public string whichType;
    12.     public GameObject player;
    13.     public Transform Player;
    14.     public float MoveSpeed = 4f;
    15.     public float MaxDist = 10f;
    16.     public float MinDist = 5f;
    17.     public GameManager gm;
    18.     public Player playerS;
    19.  
    20.     public bool canSee;
    21.  
    22.     public float health = 3;
    23.     public GameObject sparks;
    24.     public GameObject explode;
    25.  
    26.     [Header("Bullet Mechanics")]
    27.  
    28.     public float bulletSpeed;
    29.     public GameObject bulletPrefab;
    30.     public Transform bulletSpawn;
    31.    
    32.  
    33.     void Start()
    34.     {
    35.        
    36.         if (hard && canSee)
    37.         {
    38.             StartCoroutine("MakeBullets");
    39.         }
    40.  
    41.         gm = GameObject.FindObjectOfType<GameManager>();
    42.         playerS = GameObject.FindObjectOfType<Player>();
    43.  
    44.         transform.LookAt(Player);
    45.     }
    46.     private void FixedUpdate()
    47.     {
    48.        
    49.      
    50.  
    51.         if (hard)
    52.         {
    53.            // Fire();
    54.         }
    55.  
    56.     }
    57.    
    58.  
    59.     void Update()
    60.     {
    61.  
    62.  
    63.  
    64.  
    65.         if (!canSee)
    66.         transform.Rotate(Vector3.up * Time.deltaTime * 1);
    67.  
    68.         if (canSee)
    69.         {
    70.             Chase();
    71.         }
    72.         else { }
    73.      
    74.     }
    75.  
    76.     void OnTriggerEnter(Collider col)
    77.     {
    78.         if (col.tag == "PlayerRadius")
    79.         {
    80.             canSee = true;
    81.  
    82.  
    83.  
    84.         }
    85.         if (col.tag == "Bullet")
    86.         {
    87.             health -= 1;
    88.            
    89.  
    90.  
    91.         }
    92.         if (col.tag == "Friendly")
    93.         {
    94.  
    95.             transform.LookAt(Friendly[1]);
    96.  
    97.  
    98.         }
    99.     }
    100.  
    101.  
    102.  
    103.     void OnCollisionEnter(Collision other)
    104.     {
    105.  
    106.  
    107.         if (other.gameObject.CompareTag("Bullet"))
    108.         {
    109.             other.gameObject.SetActive(false);
    110.          
    111.         }
    112.  
    113.  
    114.         if (other.gameObject.CompareTag("Player"))
    115.         {
    116.          
    117.                 //StartCoroutine("HurtPlayerCo");
    118.                 playerS.health -= 1f;
    119.  
    120.                 if (playerS.health <= 0.1)
    121.                 {
    122.                    
    123.                    
    124.                     playerS.dead = true;
    125.                     playerS.deadScreen.SetActive(true);
    126.                  
    127.  
    128.                 }
    129.            
    130.         }
    131.      
    132.     }
    133.     public void Chase()
    134.     {
    135.         transform.LookAt(Player);
    136.  
    137.         if (Vector3.Distance(transform.position, Player.position) >= MinDist)
    138.         {
    139.  
    140.             transform.position += transform.forward * MoveSpeed * Time.deltaTime;
    141.  
    142.  
    143.          
    144.            
    145.  
    146.  
    147.         }
    148.  
    149.     }
    150.     public IEnumerator HurtPlayerCo()
    151.     {
    152.  
    153.         playerS.hurt.SetActive(true);
    154.         yield return new WaitForSeconds(0.2f);
    155.         playerS.hurt.SetActive(false);
    156.         yield return new WaitForSeconds(0.2f);
    157.         playerS.hurt.SetActive(true);
    158.         yield return new WaitForSeconds(0.2f);
    159.         playerS.hurt.SetActive(false);
    160.         yield return new WaitForSeconds(0.2f);
    161.  
    162.     }
    163.  
    164.     IEnumerator MakeBullets()
    165.     {
    166.         while (true)
    167.         {
    168.             var bullet = (GameObject)Instantiate(
    169.                bulletPrefab,
    170.                bulletSpawn.position,
    171.                bulletSpawn.rotation);
    172.  
    173.             // Add velocity to the bullet
    174.             bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * bulletSpeed;
    175.  
    176.             // Destroy the bullet after 2 seconds
    177.             Destroy(bullet, 2.0f);
    178.  
    179.             StopCoroutine("MakeBullets");
    180.         }
    181.     }
    182.     void Fire()
    183.     {
    184.        
    185.         // Create the Bullet from the Bullet Prefab
    186.        
    187.  
    188.         var bullet = (GameObject)Instantiate(
    189.             bulletPrefab,
    190.             bulletSpawn.position,
    191.             bulletSpawn.rotation);
    192.  
    193.         // Add velocity to the bullet
    194.         bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * bulletSpeed;
    195.  
    196.         // Destroy the bullet after 2 seconds
    197.         Destroy(bullet, 2.0f);
    198.     }
    199.  
    200. }
    201.  
     
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    Your "Chase" method is currently hard-coded to work only on the Player object. I would recommend refactoring it so that it works against an arbitrary object. Something like this:

    Code (CSharp):
    1.     private Transform _currentTarget;
    2.     public void Chase()
    3.     {
    4.         transform.LookAt(_currentTarget);
    5.         if (Vector3.Distance(transform.position, _currentTarget.position) >= MinDist)
    6.         {
    7.             transform.position += transform.forward * MoveSpeed * Time.deltaTime;
    8.         }
    9.     }
    Now you just need to set _currentTarget to whatever you want. Your OnTriggerEnter method can check for various tags, and then set _currentTarget to the object that entered the AI's radius if the object has one of the tags you want to chase.
     
  9. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,615
    Change your code so that instead of chasing the player, it chases a generic "target". Then you would write a routine to select the "target", whether that be the player, or something else.

    Edit: Yeah, what dgoyette said.
     
  10. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    @dgoyette
    How would I get it to chase any prefab with a certain tag?
     
  11. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,615
  12. PhantomProgramming

    PhantomProgramming

    Joined:
    Jan 16, 2019
    Posts:
    61
    Okay, I'll look into, thanks for all your help, both of you! :)