- Home /
How can i hide from enemy behind a wall?
Hi, I am trying to make 2d top-down shooter game. I have an enemy ai script. Enemy can make patrol and if my player inside enemy distance can follow my player. My question is how can i hide behind a wall? I tryin to make enemy can't see to me behind the wall. I did a lot of search in google but i can't find it and can't fix my script.
Here is my script. Thanks and sorry for my bad english.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float speed;
private float waitTime;
public float startWaitTime;
public Transform[] moveSpot;
private int randomSpot;
private Transform myTransform;
public Transform target;
public int moveSpeed;
void Awake()
{
myTransform = transform;
}
void Start()
{
waitTime = startWaitTime;
randomSpot = Random.Range(0, moveSpot.Length);
target = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update()
{
if (Vector2.Distance(transform.position, target.position) < 5f)
{
transform.position = Vector2.MoveTowards(transform.position, target.position, moveSpeed * Time.fixedDeltaTime);
Vector3 dir = target.position - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + 90f;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
Debug.DrawLine(target.position, myTransform.position, Color.red);
Patrol();
}
public void Patrol()
{
transform.position = Vector2.MoveTowards(transform.position, moveSpot[randomSpot].position, speed * Time.deltaTime);
Vector3 dir = moveSpot[randomSpot].position - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + 90f;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
if (Vector2.Distance(transform.position, moveSpot[randomSpot].position) < 0.2f)
{
if (waitTime <= 0)
{
randomSpot = Random.Range(0, moveSpot.Length);
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
}
}
Answer by ADiSiN · May 08, 2020 at 05:22 PM
Hi!
Basically, what you want to do is to detect if there is any Collider between your Player and Enemy.
To do that you can either use Physics.Linecast ot Physics2D.Linecast (since I am not sure is you are using 3D but top-down 2D-ish or simple 2D, so here is both documentation for any of them: https://docs.unity3d.com/ScriptReference/Physics.Linecast.html https://docs.unity3d.com/ScriptReference/Physics2D.Linecast.html ).
What it does - it casts line between 2 given points and detects if there is any Collider on the path. Therefore keep in mind that your obstacle MUST have Collider attached.
If you want to specify certain objects behind which player can hide you can use tag and when receive any collider from Linecast use CompareTag (https://docs.unity3d.com/ScriptReference/Component.CompareTag.html) to check if Collider has correct Tag.
It would look something like this, for example:
void Update()
{
RaycastHit hit;
if (Physics.Linecast(player.position, enemy.position, out hit))
{
if (hit.collider.CompareTag("hide"))
{
// Stop chasing
}
}
}
Hope that will help you :)
First of all thank you for respond. I have tried to Raycast2D as you say and it work. But i have another problem. This time when enemy can see my player it can't turn ai chasing. I have tried a bool for this but it's not work. Here is my script.
public Layer$$anonymous$$ask layerWall;
bool chase;
void Update()
{
Patrol();
Chasing();
RaycastHit2D hit;
if (hit = Physics2D.Linecast(transform.position, target.position, layerWall))
{
if (hit.collider.CompareTag("wall"))
{
chase= false;
Debug.Log("i can't see.");
}else
{
chase= true;
Debug.Log("i am chasing.");
}
// or i have tried this code
if (hit.collider.CompareTag("Player"))
{
chase= true;
Debug.Log("chasing.");
}
//
}
}
public void Chasing()
{
if (Vector2.Distance(transform.position, target.position) < 5f && chase == true)
{
transform.position = Vector2.$$anonymous$$oveTowards(transform.position, target.position, moveSpeed * Time.fixedDeltaTime);
Vector3 dir = target.position - transform.position;
float angle = $$anonymous$$athf.Atan2(dir.y, dir.x) * $$anonymous$$athf.Rad2Deg + 90f;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
Debug.DrawLine(target.position, myTransform.position, Color.red);
}
public void Patrol()
{
transform.position = Vector2.$$anonymous$$oveTowards(transform.position, moveSpot[randomSpot].position, speed * Time.deltaTime);
Vector3 dir = moveSpot[randomSpot].position - transform.position;
float angle = $$anonymous$$athf.Atan2(dir.y, dir.x) * $$anonymous$$athf.Rad2Deg + 90f;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
if (Vector2.Distance(transform.position, moveSpot[randomSpot].position) < 0.2f)
{
if (waitTime <= 0)
{
randomSpot = Random.Range(0, moveSpot.Length);
waitTime = startWaitTime;
}
else
{
waitTime -= Time.deltaTime;
}
}
}
How can i turn enemy back to chasing when see my player. Thanks for respond again.
Hi, glad that it worked, so to yor second issue.
I didn't try to test exactly your script, but only Update logic inside it, but with 3D raycasting since I was testing it in 3D project and the script below is working as you can see on attached picture (can't attach so left link).
public Layer$$anonymous$$ask collisionLayer;
bool is_Chasing;
void Update()
{
// To store linecast info
RaycastHit2D hit;
/* Transform.position - first point position;
* Target.position - second point position;
* collisionlayer - what specific layer our linecast will detect (in other words it will ignore any other layers) */
hit = Physics2D.Linecast(transform.position, target.position, collisionLayer);
if (hit.collider != null) // If we indeed hit something
{
if (hit.collider.CompareTag("Wall")) // And something has tag wall
{
if (is_Chasing) // And previously we did chase
{
// Stop chasing and resetting boolean to false
Debug.Log("Stop chase");
is_Chasing = false;
}
}
else
{
// If somethin that we hit isn't wall then we want to continue chasing
Debug.Log("Chase with collider on path but not wall");
is_Chasing = true;
}
}
else
{
// If we don't hit anything, but don't have chasing enabled then we want to continue to chase
Debug.Log("Chase without any collider on path");
// In case if boolean set to false from previous calculations
if (!is_Chasing)
is_Chasing = true;
}
// Only patrol when we don't chase
if (!is_Chasing)
Debug.Log("Patrol");
Debug.DrawLine(target.position, myTransform.position, Color.red, 2f);
}
Try to implement it in your code first with simple Debug to make sure each part called correctly and then replace Debug with functions. Let me know if it works.
NOTE: For some reason it won't let me attach the picture, so here is the link: https://imgur.com/yNx53PK
Hi, I have tried your code and it works. First i use debug.log in my script if it works then replace my functions. I had one more problem for enemy scale but i did fix it. It was face away from player. İ added float enemyScale; and edit it in my script. After all codes are work correctly. Thank you so much again.That's very helpful.
Your answer
Follow this Question
Related Questions
[BUG?] Game freezes or I get error. C# 3 Answers
A* Pathfinding Project Point Graphs in 2D 0 Answers
Multiple enemy AI using the same animations/animation controller 1 Answer
AI scripted by player 0 Answers
Unlimited Road car AI 0 Answers