Basic AI avoidance in 2D
Greetings, I am new here and still trying to get used to non-custom engines =) I am currently making a simple game as a student project and I reached an impasse: I am implementing a basic AI for an enemy. The goal of the AI is simply to follow the player and stay at a safe distance from him in order to shot (That is already done and correctly working). I also decided to add some obstacle avoidance between enemies themselves and enemy with player. I decided to use Ray Casting in order to detect collision with any object to then modify the gameobject path. Even if I understand the general idea, I have difficulties putting it in practice. This is what I have in my script so fat. If the comments are not self-explanatory, don't hesitate to ask for more info.
using UnityEngine;
using System.Collections;
public class TrackingMovement : ModuleComponent {
//For tracking movement
private bool activated = false;
public float MoveSpeed = 5.0f;
public float DistFromPlayer = 10.0f;
public override void Request()
{
activated = true;
}
void LookAtTarget2D(GameObject target)
{
float angle = 0.0f;
Vector3 relative = transform.InverseTransformPoint(target.transform.position);
angle = Mathf.Atan2(relative.x, relative.y) * Mathf.Rad2Deg;
transform.Rotate(0, 0, -angle);
}
void TrackPlayer()
{
//Store the position of the player
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player)
{
Vector3 player_position = player.transform.position;
LookAtTarget2D(player);
var distance = Vector3.Distance(transform.position, player_position);
if (distance >= DistFromPlayer)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
}
}
}
public void AvoidObstacles()
{
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (!player)
return;
Vector3 direction = (player.transform.position - transform.position).normalized;
//Ray in front of the enemy
if (Physics2D.Raycast(transform.position, transform.forward, 4))
{
// Check if the collision is with a Player or an enemy tag only
//We need to get somehow the hit direction normalized
// add it to direction * repulsion force
}
//Create more rays (left and right) and repeat the process
//Apply the direction to the transform.rotation?
}
void Start ()
{
Button = ButtonType.Movement;
Category = CategoryType.Movement;
}
void Update ()
{
if (activated)
{
TrackPlayer();
AvoidObstacles();
}
}
}
And, in case of using this later for avoiding wall collision as well, how would I take that into account?
While raycasting could work i'm not sure how to get a intelligent behavior out of it. I would implement some pathfinding algorithm ins$$anonymous$$d and rely on that for all movement.
How you do this depends on your game, for example if its grid based you can quite easily make you own A* pathfinding (google it for some great tutorials), the same methods can be used even if you don't have a grid based system, you just need to define the grid some other way.
A easy way to do pathfinding would be to use Unitys Nav$$anonymous$$eshAgent, this only works in 3D (last i tried), but you can of course work around this and simply use a orthographic camera to "hide" the 3rd dimension.
The goal is to emulate some type of flocking behavior for the enemies. Like having them keeping a safe distance between each other while they all follow the player. Did not thought about implementing any kind of path-finding algorithm yet ^^ I am indeed familiar with A* and my rooms (levels) will be grid based, gonna check what I can do.
Answer by J0hn4n · Jan 27, 2017 at 03:19 AM
Nice for you, i dont know why i thinked about making A* for collision avoidance, well anyway i done that, already its no so much usefull unless you need move high amounts of units on the map, like a Tower Defense, unless you alredy need to move lots of units dont do A* , you can simpli make a physics.circle(something like that), and just pick up all obsticle objects on his aggro radius(something small like 3f or 2f).
if a object its under his aggro radius return new direction away from that object whitout lose his target, something like return new direction on the cosine or sine of the sight of view of the unit, so if he was goin to hit something he new direction will be a new pos on his angle of view.
you can also implement that using raycasting if raycast hit something return point if your agro radius its close of that point just make this
hit.position - transform.position;
that way the unit never will reach to collide whit the wall, because its directin vector its not a normalized so he eventually slow down and never reach;
Your answer
Follow this Question
Related Questions
Making a GameObject follow the direction of a RayCast 1 Answer
2D platformer AI 0 Answers
2d object moves only a little then stops 0 Answers
How to Offset collision on player Sprite 1 Answer
Checking for Raycast distances not working as expected. 0 Answers