- Home /
Programming an enemy to shoot upwards
I am trying to program a RayCast enemy that shoots a laser. The problem with this code is that I can't get it to shoot upwards. I know it involves getting the y position of the player, but I just don't know how.
using UnityEngine; using System.Collections; using UnityEngine.AI;
public class EnemyAiTutorial : MonoBehaviour { [SerializeField] Transform enemy;
[SerializeField] NavMeshAgent agent;
[SerializeField] Transform player;
[SerializeField] LayerMask whatIsGround, whatIsPlayer;
[Space]
//Patroling
[SerializeField] Vector3 walkPoint;
bool walkPointSet;
[SerializeField] float walkPointRange;
//Attacking
[SerializeField] float timeBetweenAttacks;
[SerializeField] bool isShooting;
bool alreadyAttacked;
[Space]
//States
[SerializeField] float sightRange, attackRange;
[SerializeField] bool playerInSightRange, playerInAttackRange;
[Space]
[SerializeField] float delaySeconds = 1.5f;
[SerializeField] bool fire;
[SerializeField] float range = 100f;
[SerializeField] float damage = 20f;
[SerializeField] Vector3 characterOffSet = new Vector3(0f, 0.3f, 0);
[SerializeField] Vector3 aimOffSet = new Vector3(0, 1, 0);
private LineRenderer laser;
bool fireLaser;
#region Awake & Update functions
private void Awake()
{
player = GameObject.Find("Player").transform;
}
public void Start()
{
laser = GetComponent<LineRenderer>();
}
private void Update()
{
//Check for sight and attack range
playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);
if (!playerInSightRange && !playerInAttackRange) Patroling();
if (playerInSightRange && !playerInAttackRange) ChasePlayer();
if (playerInAttackRange && playerInSightRange) AttackPlayer();
laser.SetPosition(0, enemy.transform.position + characterOffSet);
if (!fireLaser)
{
laser.SetPosition(1, enemy.transform.position + characterOffSet);
}
}
#endregion
#region States
private void Patroling()
{
if (!walkPointSet) SearchWalkPoint();
if (walkPointSet)
agent.SetDestination(walkPoint);
Vector3 distanceToWalkPoint = transform.position - walkPoint;
//Walkpoint reached
if (distanceToWalkPoint.magnitude < 1f)
walkPointSet = false;
}
private void SearchWalkPoint()
{
//Calculate random point in range
float randomZ = Random.Range(-walkPointRange, walkPointRange);
float randomX = Random.Range(-walkPointRange, walkPointRange);
walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);
if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
{
walkPointSet = true;
}
}
private void ChasePlayer()
{
agent.SetDestination(player.transform.position);
}
private void AttackPlayer()
{
//Make sure enemy doesn't move
agent.SetDestination(transform.position);
if (!isShooting)
{
Vector3 aimPlayer = player.transform.position + aimOffSet;
transform.LookAt(aimPlayer);
}
if (!alreadyAttacked)
{
StartCoroutine(Shoot());
}
}
private void ResetAttack()
{
alreadyAttacked = false;
}
#endregion
IEnumerator Shoot()
{
float totalTime = delaySeconds + timeBetweenAttacks;
isShooting = true;
yield return new WaitForSeconds(delaySeconds);
fireLaser = true;
RaycastHit Hit;
while (!alreadyAttacked)
{
Vector3 onward = transform.TransformDirection(Vector3.forward) * (range);
Debug.DrawRay(enemy.transform.position, onward, Color.red, 1f);
if (Physics.Raycast(enemy.transform.position, enemy.transform.forward, out Hit, range))
{
laser.SetPosition(1, Hit.point);
Debug.Log(Hit.collider.name);
if (Hit.collider.GetComponent<Damagable>() != null)
{
Hit.collider.GetComponent<Damagable>().TakeDamage(damage, Hit.point, Hit.normal);
}
else
{
Hit.collider.GetComponent<mapCollision>().TakeDamage(damage, Hit.point, Hit.normal);
}
} else
{
laser.SetPosition(1, onward);
}
alreadyAttacked = true;
}
isShooting = false;
yield return new WaitForSeconds(totalTime);
fireLaser = false;
alreadyAttacked = false;
}
}
Answer by MegaBomb_Unity · Nov 07, 2021 at 02:18 AM
Took me a while but figured out the answer all by myself. Apparently, my code was inefficient and the AI would not look at the exact point where the player would be. What I did was I created a Vector3 for the player's position
[SerializeField] Vector3 characterOffSet = new Vector3(0f, 0.3f, 0);
[SerializeField] Vector3 aimOffSet = new Vector3(0, 1, 0);
private LineRenderer laser;
bool fireLaser;
Vector3 target;
and after that, I made the vector 3 look for the player's position whenever it's not shooting and used transform.LookAt on the Vector3
if (!isShooting)
{
Vector3 aimPlayer = player.transform.position + aimOffSet;
transform.LookAt(aimPlayer);
target = aimPlayer;
} else
{
transform.LookAt(target);
}
if (!alreadyAttacked)
{
StartCoroutine(Shoot());
}
Your answer
Follow this Question
Related Questions
Enemy raycast detection 0 Answers
Enemy AI Script Acting Abnormal 0 Answers
AI script works, when we add a blocked function it stops working HELP 0 Answers
Enemy AI Running Through Wall With Raycast 1 Answer
[SOLVED] using var from another method? 2 Answers