- Home /
Kill character on impact
Hey guys, got some great code that has a field of view and pathfinding built in. It also has a shooting mechanic but I would like my enemies to kill when they touch the player rather than when shot. The main issue I'm having is that the enemy detects and follows but always stay a foot or so away from the character (shooting range) I already have a death script typed up, super simple but it works. I just need the enemy to run into the player. I'm sure this is simple but I'm new to this and the code is overwhelming for a n00b!
Here it is anyways, thanks for all the help!
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : Actor
{
public const bool DEBUG_ENEMY = false;
// ----------------------------------------------
// CONSTANTS
// ----------------------------------------------
public const int STATE_NULL = -1;
public const int STATE_IDLE = 0;
public const int STATE_WAYPOINTS = 1;
public const int STATE_WAYPOINTS_PATHFINDING = 2;
public const int STATE_FOLLOW_PLAYER = 3;
public const int STATE_FOLLOW_PLAYER_PATHFINDING= 4;
public const int STATE_SHOOT_PLAYER = 5;
public const int STATE_DIE = 6;
public const int STATE_END = 7;
public const float SHOOT_TIMEOUT = 0.5f;
public const float SHOOT_SPEED = 20.0f;
public const int LIFE_ENEMY = 100;
public const int DAMAGE_ENEMY = 5;
// ----------------------------------------------
// VARIABLE MEMBERS
// ----------------------------------------------
private GameObject m_world;
// WAYPOINTS
private int m_currentWaypoint;
private List<Vector3> m_waypoints = new List<Vector3>();
private bool m_directionWaypoints;
private GameObject m_goal;
private Vector2 m_lastCell;
// VIEW LINE RENDER
private int lengthOfLineRenderer = 4;
private Color c1 = Color.yellow;
private Color c2 = Color.red;
private LineRenderer m_lineRenderer;
// ----------------------------------------------
// CONSTRUCTOR
// ----------------------------------------------
// -------------------------------------------
/*
* Constructor
*/
public Enemy()
{
// INIT WAYPOINT STRUCT
m_currentWaypoint = 0;
m_directionWaypoints = true;
m_waypoints = new List<Vector3>();
m_lastCell = new Vector2();
}
// ----------------------------------------------
// INIT/DESTROY
// ----------------------------------------------
// -------------------------------------------
/*
* Start
*/
void Start ()
{
ChangeState(STATE_WAYPOINTS);
// INIT GAME OBJECT
Character = this.gameObject.gameObject;
Type = Global.TYPE_ENEMY;
YawAdditional = 90;
// GET REFERENCE TO WORLD SCRIPT
m_world = GameObject.FindGameObjectWithTag(Global.CAMERA_TAG);
if (m_world.GetComponent<World>()==null)
{
m_world = null;
}
// SET THE PROTAGONIST GOAL
GameObject protagonistModel = GameObject.FindGameObjectWithTag(Global.PLAYER_TAG);
if (protagonistModel!=null)
{
Goal = protagonistModel;
}
// READ WAYPOINTS
if (m_waypointsWorld!=null)
{
for (int i=0;i<m_waypointsWorld.Length;i++)
{
GameObject sWay = m_waypointsWorld[i];
m_waypoints.Add(new Vector3(sWay.transform.position.x, 0, sWay.transform.position.z) );
Destroy(sWay);
}
}
// WAYPOINTS
// AddWaypoint(new Vector3(2*2f, 0, 2*2f));
// AddWaypoint(new Vector3(2*2f, 0, 4*2f));
// AddWaypoint(new Vector3(9*2f, 0, 4*2f));
// AddWaypoint(new Vector3(2*2f, 0, 4*2f));
// ADD A LINE
m_lineRenderer = gameObject.AddComponent<LineRenderer>();
m_lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
m_lineRenderer.SetColors(c1, c2);
m_lineRenderer.SetWidth(0.0F, 0.0F);
m_lineRenderer.SetVertexCount(lengthOfLineRenderer);
}
// -------------------------------------------
/*
* Init
*/
public void Init()
{
}
// -------------------------------------------
/*
* Destroy
*/
void Destroy ()
{
base.Destroy();
if (m_world!=null) m_world.BroadcastMessage("EnemyDeath");
if (DEBUG_ENEMY) Debug.Log("Enemy::Destroy");
}
// ----------------------------------------------
// GETTERS/SETTERS
// ----------------------------------------------
public GameObject Goal
{
get { return m_goal; }
set { m_goal = value; }
}
// ----------------------------------------------
// LISTENERS
// ----------------------------------------------
// ----------------------------------------------
// PRIVATE/PROTECTED FUNCTIONS
// ----------------------------------------------
// ----------------------------------------------
// PUBLIC FUNCTIONS
// ----------------------------------------------
// -------------------------------------------
/*
* Apply damage
*/
public override void ApplyDamage(float damage)
{
base.ApplyDamage(damage);
if (Life<=0)
{
ChangeState(STATE_DIE);
}
else
{
ChangeState(STATE_FOLLOW_PLAYER);
}
}
// -------------------------------------------
/*
* Test if the element has finished
*/
public bool HasFinished()
{
return (m_state == STATE_END);
}
// -------------------------------------------
/*
* Read waypoints
*/
public void AddWaypoint(Vector3 pos)
{
m_waypoints.Add(new Vector3(pos.x, 0, pos.z) );
}
// -------------------------------------------
/*
* Will draw the vision of the enemy
*/
public RaycastHit UpdateVision(Vector3 goalPosition, float viewDistance, float angleView, bool render)
{
Vector3 originLine = new Vector3(Position.x,
Position.y,
Position.z);
if (render)
{
// DRAW LINE 1
m_lineRenderer.SetPosition(0, originLine);
Vector3 destinationLine1 = new Vector3(Position.x+(viewDistance*Mathf.Cos((Yaw+angleView) * Mathf.Deg2Rad)),
Position.y+1,
Position.z+(viewDistance*Mathf.Sin((Yaw+angleView) * Mathf.Deg2Rad)));
m_lineRenderer.SetPosition(1, destinationLine1);
// DRAW LINE 2
// m_lineRenderer.SetPosition(2, originLine);
Vector3 destinationLine2 = new Vector3(Position.x+(viewDistance*Mathf.Cos((Yaw-angleView) * Mathf.Deg2Rad)),
Position.y+1,
Position.z+(viewDistance*Mathf.Sin((Yaw-angleView) * Mathf.Deg2Rad)));
m_lineRenderer.SetPosition(2, destinationLine2);
m_lineRenderer.SetPosition(3, originLine);
}
// LOGIC OF DETECTION OF PLAYER
if ((goalPosition.x!=-1)&&(goalPosition.y!=-1)&&(goalPosition.z!=-1))
{
if (Global.IsInsideCone(this, goalPosition, (float)viewDistance, (float)angleView))
{
Ray ray = new Ray();
ray.origin = Position;
Vector3 fwd = new Vector3( goalPosition.x - Position.x, 0, goalPosition.z - Position.z);
fwd.Normalize();
ray.direction = fwd;
// ray.origin = Position - (1*fwd);
Debug.DrawRay(ray.origin, ray.direction * 100, Color.green);
RaycastHit hitCollision = new RaycastHit();
if (Physics.Raycast(ray, out hitCollision, Mathf.Infinity))
{
return (hitCollision);
}
else
{
return (new RaycastHit());
}
}
}
return (new RaycastHit());
}
// -------------------------------------------
/*
* Will update the waypoint to go
*/
public void UpdateWaypoints()
{
if (m_waypoints.Count>0)
{
if (m_directionWaypoints)
{
m_currentWaypoint++;
}
else
{
m_currentWaypoint--;
}
if (m_currentWaypoint<0) m_currentWaypoint = m_waypoints.Count - 1;
m_currentWaypoint=m_currentWaypoint%m_waypoints.Count;
}
}
// ----------------------------------------------
// UPDATE
// ----------------------------------------------
// -------------------------------------------
/*
* Update
*/
public override void Update ()
{
Collider sCollision;
Vector3 sWay;
String tagCollided;
RaycastHit hitCollision;
base.Update();
// EVAL STATE
switch (m_state)
{
////////////////////////////////
case STATE_IDLE:
if (m_iterator == 1)
{
UpdateWaypoints();
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_IDLE::m_currentWaypoint="+m_currentWaypoint);
}
// ROTATE TO THE NEXT WAYPOINT
if (m_waypoints.Count>0)
{
sWay = m_waypoints[m_currentWaypoint];
Global.LogicAlineation(this, new Vector2(sWay.x,sWay.z), 0, m_speedRotation);
if (Global.IsInsideCone(this, new Vector3(sWay.x, Position.y, sWay.z), 100f, 5))
{
ChangeState(STATE_WAYPOINTS);
}
}
// PLAYER DETECTED
if (Goal != null)
{
hitCollision= UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
if (hitCollision.collider!=null)
{
if ( hitCollision.collider.tag == Global.PLAYER_TAG)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_IDLE::FOLLOW THE PLAYER!");
ChangeState(STATE_FOLLOW_PLAYER);
}
}
}
else
{
hitCollision = UpdateVision(new Vector3(-1,-1,-1), m_viewDistance, m_angleView, true);
}
break;
////////////////////////////////
case STATE_WAYPOINTS:
if (m_iterator==1)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_WAYPOINTS::m_waypoints="+m_waypoints.Count);
}
if (m_waypoints.Count>0)
{
sWay = m_waypoints[m_currentWaypoint];
Global.LogicAlineation(this, new Vector2(sWay.x,sWay.z), m_speedMovement, m_speedRotation);
if (Vector3.Distance(new Vector3(Position.x, 0, Position.z), new Vector3(sWay.x, 0, sWay.z))<(m_speedMovement/2))
{
// UpdateWaypoints();
ChangeState(STATE_IDLE);
}
// CHECK WAYPOINT FOR COLLISION WALL
hitCollision = UpdateVision(sWay, Mathf.Infinity, m_angleView, false);
if (hitCollision.collider != null)
{
if (hitCollision.collider.tag == Global.WALL_TAG)
{
if (Vector3.Distance(Position, hitCollision.point)<(Vector3.Distance(Position, new Vector3(sWay.x, Position.y, sWay.z))))
{
ChangeState(STATE_WAYPOINTS_PATHFINDING);
}
}
}
}
// PLAYER DETECTED
if (Goal != null)
{
hitCollision = UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
if (hitCollision.collider!=null)
{
if ( hitCollision.collider.tag ==Global.PLAYER_TAG)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_WAYPOINTS::FOLLOW THE PLAYER!");
ChangeState(STATE_FOLLOW_PLAYER);
}
}
}
else
{
UpdateVision(new Vector3(-1,-1,-1), m_viewDistance, m_angleView, true);
}
break;
////////////////////////////////
case STATE_WAYPOINTS_PATHFINDING:
if (m_iterator==1)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_WAYPOINTS::m_waypoints="+m_waypoints.Count);
}
if (m_waypoints.Count>0)
{
sWay = m_waypoints[m_currentWaypoint];
int oriX = (int)(((Position.x-PathFinding.xIni)/PathFinding.CellWidth));
int oriY = (int)(((Position.z-PathFinding.zIni)/PathFinding.CellHeight));
int desX = (int)(((sWay.x-PathFinding.xIni)/PathFinding.CellWidth));
int desY = (int)(((sWay.z-PathFinding.zIni)/PathFinding.CellHeight));
if ((PathFinding.GetCellContent(oriX,oriY)==PathFinding.CELL_COLLISION)
||
(PathFinding.GetCellContent(desX,desY)==PathFinding.CELL_COLLISION))
{
ChangeState(STATE_WAYPOINTS);
return;
}
else
{
Vector2 output=PathFinding.SearchAStar( oriX, oriY, desX, desY);
output.x = (output.x * PathFinding.CellWidth) + (PathFinding.CellWidth/2) + PathFinding.xIni;
output.y = (output.y * PathFinding.CellHeight) + (PathFinding.CellHeight/2) + PathFinding.zIni;
Debug.DrawRay(sWay, Vector3.up, Color.yellow);
Debug.DrawLine(Position, new Vector3(output.x, Position.y, output.y), Color.white);
while (!Global.IsInsideCone(this, new Vector3(output.x, Position.y, output.y), 100f, 5))
{
Global.LogicAlineation(this, new Vector2(output.x,output.y), 0, m_speedRotation);
}
Global.LogicAlineation(this, new Vector2(output.x,output.y), m_speedMovement, m_speedRotation);
if (Vector3.Distance(new Vector3(Position.x, 0, Position.z), new Vector3(sWay.x, 0, sWay.z))<(m_speedMovement/2))
{
// UpdateWaypoints();
ChangeState(STATE_IDLE);
}
}
}
// PLAYER DETECTED
if (Goal != null)
{
hitCollision = UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
if (hitCollision.collider!=null)
{
if ( hitCollision.collider.tag ==Global.PLAYER_TAG)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_WAYPOINTS::FOLLOW THE PLAYER!");
ChangeState(STATE_FOLLOW_PLAYER);
}
}
}
else
{
UpdateVision(new Vector3(-1,-1,-1), m_viewDistance, m_angleView, true);
}
break;
////////////////////////////////
case STATE_FOLLOW_PLAYER:
if (m_iterator==1)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_FOLLOW_PLAYER!!!!!!!!!!!!!");
}
// TIMEOUT TO SHOOT
if (m_world!=null)
{
m_timeAcum += Time.deltaTime;
if (m_timeAcum>SHOOT_TIMEOUT)
{
m_timeAcum = 0;
m_world.BroadcastMessage("AskNewShoot", new ShootParameters(Character, Position, Global.TYPE_ENEMY, SHOOT_SPEED, DAMAGE_ENEMY));
}
}
// ALIGN WITH THE PLAYER
if (Goal != null)
{
Global.LogicAlineation(this, new Vector2(Goal.transform.position.x, Goal.transform.position.z), m_speedMovement, m_speedRotation);
if (Vector3.Distance(Goal.transform.position, Position)> (5*m_viewDistance)/4)
{
ChangeState(STATE_WAYPOINTS);
}
// PLAYER LOST DETECTION
hitCollision = UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
if (hitCollision.collider!=null)
{
if ( hitCollision.collider.tag == Global.WALL_TAG)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_FOLLOW_PLAYER::PLAYER LOST, GO BACK WAYPOINTS!");
ChangeState(STATE_FOLLOW_PLAYER_PATHFINDING);
}
}
// PLAYER IN RANGE OF SHOOT
if (Vector3.Distance(Position, Goal.transform.position) < (2*m_viewDistance)/4)
{
ChangeState(STATE_SHOOT_PLAYER);
}
}
else
{
UpdateVision(new Vector3(-1,-1,-1), m_viewDistance, m_angleView, true);
ChangeState(STATE_WAYPOINTS);
}
break;
////////////////////////////////
case STATE_FOLLOW_PLAYER_PATHFINDING:
if (m_iterator==1)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_FOLLOW_PLAYER_PATHFINDING!!!!!!!!!!!!!");
}
// ALIGN WITH THE PLAYER
if (Goal != null)
{
int oriX=(int)(((Position.x-PathFinding.xIni)/PathFinding.CellWidth));
int oriY=(int)(((Position.z-PathFinding.zIni)/PathFinding.CellHeight));
if (PathFinding.GetCellContent(oriX,oriY)==PathFinding.CELL_COLLISION)
{
ChangeState(STATE_WAYPOINTS);
return;
}
else
{
int desX=(int)(((Goal.transform.position.x-PathFinding.xIni)/PathFinding.CellWidth));
int desY=(int)(((Goal.transform.position.z-PathFinding.zIni)/PathFinding.CellHeight));
Vector2 output=PathFinding.SearchAStar(oriX, oriY, desX, desY);
if ((output.x == -1f)&&(output.y == -1f))
{
if (PathFinding.GetCellContent(desX+1,desY)==PathFinding.CELL_EMPTY)
{
desX = desX+1;
desY = desY;
}
else
if (PathFinding.GetCellContent(desX-1,desY)==PathFinding.CELL_EMPTY)
{
desX = desX-1;
desY = desY;
}
else
if (PathFinding.GetCellContent(desX,desY+1)==PathFinding.CELL_EMPTY)
{
desX = desX;
desY = desY+1;
}
else
if (PathFinding.GetCellContent(desX,desY-1)==PathFinding.CELL_EMPTY)
{
desX = desX;
desY = desY-1;
}
else
{
desX = (int)m_lastCell.x;
desY = (int)m_lastCell.y;
}
output = PathFinding.SearchAStar(oriX, oriY, desX, desY);
}
else
{
m_lastCell.x = desX;
m_lastCell.y = desY;
}
output.x = (output.x * PathFinding.CellWidth) + (PathFinding.CellWidth/2) + PathFinding.xIni;
output.y = (output.y * PathFinding.CellHeight) + (PathFinding.CellHeight/2) + PathFinding.zIni;
Global.LogicAlineation(this, new Vector2(output.x, output.y), m_speedMovement, m_speedRotation);
if (Vector3.Distance(Goal.transform.position, Position)>(5*m_viewDistance)/4)
{
ChangeState(STATE_WAYPOINTS);
return;
}
}
}
// LINE CLEAR TO PLAYER
hitCollision = UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
if (hitCollision.collider!=null)
{
if (hitCollision.collider.tag == Global.PLAYER_TAG)
{
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_FOLLOW_PLAYER::PLAYER LOST, GO BACK WAYPOINTS!");
ChangeState(STATE_FOLLOW_PLAYER);
}
}
break;
////////////////////////////////
case STATE_SHOOT_PLAYER:
// TIMEOUT TO SHOOT
if (m_world!=null)
{
m_timeAcum += Time.deltaTime;
if (m_timeAcum>SHOOT_TIMEOUT)
{
m_timeAcum = 0;
if (DEBUG_ENEMY) Debug.Log("Enemy::Update::STATE_SHOOT_PLAYER::NEW SHOOT! Position_A="+Character.transform.position.ToString());
m_world.BroadcastMessage("AskNewShoot", new ShootParameters(Character, Position, Global.TYPE_ENEMY, SHOOT_SPEED, DAMAGE_ENEMY));
}
}
// GO IDLE
if (Goal != null)
{
Global.LogicAlineation(this, new Vector2(Goal.transform.position.x, Goal.transform.position.z), 0f, m_speedRotation);
hitCollision = UpdateVision(Goal.transform.position, m_viewDistance, m_angleView, true);
float distPlayer = Vector3.Distance(Position, Goal.transform.position);
if (distPlayer> (5*m_viewDistance)/4)
{
ChangeState(STATE_WAYPOINTS);
}
else
{
if (distPlayer> (3*m_viewDistance)/4)
{
ChangeState(STATE_FOLLOW_PLAYER);
}
}
}
break;
//////////////////////////////
case STATE_DIE:
ChangeState(STATE_END);
break;
//////////////////////////////
case STATE_END:
if (m_iterator==1)
{
Destroy();
}
break;
}
}
}
Answer by badguy0325 · Jun 14, 2013 at 06:39 AM
Hello there, I actually found this code earlier today, and had the exact same thing in mind! What you are looking for is on line 480. if (Vector3.Distance(Position, Goal.transform.position) < (2*m_viewDistance)/4) Just change the part to the right of the < sign to 0 or 1. That is what I did in my version of the code, and it works great! It even works when you increase the view distance of the AI, instead of stopping further and further away. Hope this helps, and good luck.
Btw if this does help you, would you have a look at my post found ((here))? Or if you can't figure it out, maybe you know somebody who can? I am so close, yet really stuck, and nobody seems to have an answer for me. Anyways best of luck to you.
Your answer
Follow this Question
Related Questions
free roaming enemy ai 1 Answer
Enemy walking off platform in 2D mode 1 Answer
Simple AI Error 8025 Parrsing error. 2 Answers
Enemy raycast detection 0 Answers
Different enemy types script design 1 Answer