- Home /
How to make enemy to shoot and dodge projectile?
I want to have the enemy AI to shoot the player as well as dodging the projectile from the player. I can get the enemy to chase the player but I can't get it to shoot and dodge the projectile.
using UnityEngine;
using System.Collections;
public class EnemyControllerBasic : MonoBehaviour {
// The reference to the bullet prefab for Enemies
public Projectile EnemyBullet;
// The game object which spawn us
private ShipPlayerController PlayerShipCtrl;
// The speed to use when in "ramming" mode
[SerializeField] float RamSpeed = 5.0f;
// The different IDs for the AI states
enum AIMode { Normal, Ramming, SteerTowards };
// The variable which holds the current AI state
private AIMode CurrentAIState;
// list of pickup Types to spawn
[SerializeField] GameObject[] PickupTypes;
// Used to control how fast the game object moves
[SerializeField] float MoveSpeed = 5.0f;
// Use this for initialization
void Start () {
Destroy(gameObject, 5.0f);
// find the player ship game object by name
GameObject playerShip = GameObject.Find("PlayerShip");
// Acess the player ship's script component by type
PlayerShipCtrl = playerShip.GetComponent<ShipPlayerController>();
// Always start in the normal state
CurrentAIState = AIMode.Normal;
}
// Update is called once per frame
void Update () {
transform.position +=
transform.up * Time.deltaTime * MoveSpeed;
// Decides which AI state should be currently active
DetermineAIState();
// Depending on the current AI mode, call the update function
switch (CurrentAIState)
{
// Normal State
case AIMode.Normal:
UpdateNormal();
break;
// Ramming State
case AIMode.Ramming:
UpdateNormal();
break;
// Steer sowards the player
case AIMode.SteerTowards:
UpdateSteerTowards();
break;
}
}
// Called by the engine when this object collides
// with another object containing collision
void OnTriggerEnter(Collider other) {
// Hit the player's projectile?
if (other.tag == "PlayerProjectile")
{
// Projectile instant kills us
Destroy(gameObject);
// Drop a pickup
SpawnPickup();
}
// Hit the player ship?
else if (other.tag == "PlayerShip")
{
// Wrecking with the player kills us
Destroy(gameObject);
// Remove the points from the player for hitting this enemy
PlayerShipCtrl.ModScore(-1);
}
}
void SpawnPickup() {
// Randomly choose an index in the pickup array
int randIndex = Random.Range(0, PickupTypes.Length);
// use the random index to select one of the enemy
Instantiate(PickupTypes[randIndex],
transform.position, transform.rotation);
}
// Update the enemy when in "Normal" state
void UpdateNormal() {
// Move the object in the direction it is facing
transform.position +=
transform.up * Time.deltaTime * MoveSpeed;
}
// Applies the AI ramming movement
void UpdateRamming() {
// Move the object in the direction it is facing over a peroid amount of time
transform.position +=
transform.up * Time.deltaTime * RamSpeed;
}
void DetermineAIState() {
// Use our helper function to determine if the player
// ship is in the line of the sight of this enemy ship
bool canSee = CanSeeTarget("PlayerShip");
// Subtract the enemy's current position from the player's location
Vector3 directionToplayer =
PlayerShipCtrl.transform.position - transform.position;
// Store the normalized version of the direction to remove its length
Vector3 DirToPlayerNorm = directionToplayer.normalized;
// Not products of two vectors represent a cosine angle between them
float product = Vector3.Dot(transform.up, DirToPlayerNorm);
// Convert to cosine to a radiant angle
float angle = Mathf.Acos(product);
// Convert the radian angle into a degree angle
angle = angle * Mathf.Rad2Deg;
// Check if the player ship is close enough
// to be considered in front of the player
if (canSee)
{
// if so, change the ramming mode
CurrentAIState = AIMode.Ramming;
// Add a little visual feedback and change it to red
renderer.material.color = Color.red;
}
// Check if the player ship is outside the enemy's vision
else if (product > 0 && angle < 90)
{
// Change the state to steertoward
CurrentAIState = AIMode.SteerTowards;
// Change its color to green to denote
// that it found the player
renderer.material.color = Color.green;
}
else
{
// if not, return to the normal state
CurrentAIState = AIMode.Normal;
// Restore the color back to normal
renderer.material.color = Color.white;
}
}
// Determines if the this AI can "See" the player
bool CanSeeTarget(string _targetTag)
{
// Contains data about collision
RaycastHit hitInfo;
// Performs a ray cast
bool hitAny = Physics.Raycast(transform.position, transform.up, out hitInfo);
if (hitAny)
{
if (hitInfo.collider.gameObject.tag == _targetTag)
{
return true;
}
}
return false;
}
// Handles the movement and rotation towards the player
void UpdateSteerTowards() {
// Subtact the enemy's current position form the player's
Vector3 directionToplayer =
PlayerShipCtrl.transform.position - transform.position;
// Rotate the enemy's movement direction towards the player
transform.up = Vector3.RotateTowards(transform.up,
directionToplayer,
Time.deltaTime * MoveSpeed,
0.0f);
UpdateNormal();
}
}
Answer by drudiverse · Oct 18, 2014 at 08:13 PM
that's a great idea. that's 5 6 pages of code :/
use rotates towards for the AI enemy to totally control his movement. you can add perlin noise and slow lerping functions to fine tune the ai movement. every time a bullet is fired, you have to compare it's vector to the player/enemy position. using on the angle of the 2 vectors, and distance player enemy, you can make the enemy move in any kind of way away from the firing, perlin noise is cool there too, to add side force or transform position if fired upon. the amout of possible variables and methods to fine tune your AI in endless, its same as any other algorithms for changing transform positions of things in unity.