- Home /
Object Avoidance for my enemies
I'm trying to understand some of this "Object Avoidance" I've been reading and searching up on. Seems there is ALWAYS something new and complicated to try and figure out. I followed along on a video tutorial for a simple method of "Object Avoidance" but again I fear I'm missing a big part of the picture. In my script I already have a "LineCast call" and the tutorial uses "Raycast" so I'm a little confused about what the diffence is and allso on how to implement it into my current AI script.
right now my "Alien Zombies" are doing a pretty goo job of attacking me on sight and inflicting damage much thanks to "Statement". But they are kinda stoooopid when it comes to getting stuck on trees and not going around them.
Here is my script:
I commented out the object avoidance part for now because it was giving me an error although I typed it EXACTLY the way the video instructed, checked, double and even tripple checked it so I don't know why it's not working.
var speed = 3.0; var rotationSpeed = 5.0; var attackRange = 30.0; var dontComeCloserRange = 5.0; var pickNextWaypointDistance = 2.0; var target : Transform; var modelAnimation : Animation; var attackSound : AudioClip; // Attack Player Sounds var tearingFlesh : AudioClip; // Attack Player Sounds
private var hitTimmer = 1.0;
// Make sure there is always a character controller @script RequireComponent (CharacterController) /////////////////////////////////////////////////////////// function Update(){ //The direction vector to our target var dir = (target.position - transform.position).normalized; var hit : RaycastHit; // Check for forward raycast if(Physics.Raycast(transform.position, transform.forward, hit, 20)){ if(hit.transform ! = transform){ Debug.Drawline(transform.position, hit.point, Color.red); dir += hit.normal 50; }
}
var leftR = transform.position; var rightR = transform.position;
leftR.x -= 2; rightR.x += 2;
if(Physics.Raycast(leftR, transform.forward, hit, 20)){ if(hit.transform != transform){ Debug.Drawline(leftR, hit.point, Color.red); dir += hit.normal 50; } } if(Physics.Raycast(RightR, transform.forward, hit, 20)){ if(hit.transform != transform){ Debug.Drawline(RightR, hit.point, Color.red); dir += hit.normal 50; } }
var rot = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Slerp(transform.rotation, rot, transform.position += transform.forward 5 Time.deltaTime;
}
*////////////////////////////////
function Start () { // Auto setup player as target through tags if (target == null && GameObject.FindWithTag("Player")) target = GameObject.FindWithTag("Player").transform;
Patrol();
}
function Patrol () { var curWayPoint = AutoWayPoint.FindClosest(transform.position); while (true) { var waypointPosition = curWayPoint.transform.position; // Are we close to a waypoint? -> pick the next one! if (Vector3.Distance(waypointPosition, transform.position) < pickNextWaypointDistance) curWayPoint = PickNextWaypoint (curWayPoint);
// Attack the player and wait until
// - player is killed
// - player is out of sight
if (CanSeeTarget ())
yield StartCoroutine("AttackPlayer");
// Move towards our target
MoveTowards(waypointPosition);
yield;
}
}
function CanSeeTarget () : boolean { if (Vector3.Distance(transform.position, target.position) > attackRange) return false;
var hit : RaycastHit;
Debug.DrawRay(transform.position, transform.forward * 30, Color.red);
if (Physics.Linecast (transform.position, target.position, hit))
return hit.transform == target;
return false;
}
function AttackPlayer () { var lastVisiblePlayerPosition = target.position; while (true) { //if (CanSeeTarget ()) { // Target is dead - stop hunting if (target == null) return;
// Target is too far away - give up
var distance = Vector3.Distance(transform.position, target.position);
if (distance > attackRange * 3)
return;
lastVisiblePlayerPosition = target.position;
if (distance > dontComeCloserRange)
MoveTowards (lastVisiblePlayerPosition);
else
RotateTowards(lastVisiblePlayerPosition);
//Attack player with "Attack" animation which is basically a clawing and biting animation
//this "Attack" is supposed to inflict damage to the FPS player
var forward = transform.TransformDirection(Vector3.forward);
var targetDirection = lastVisiblePlayerPosition - transform.position;
targetDirection.y = 0;
var angle = Vector3.Angle(targetDirection, forward);
if (distance < 3){
var damage = 10;
target.SendMessage("ApplyDamage", damage);
// you probably have some other script managing there
// animations but you'd typically at this point call
modelAnimation.Play("Attack");
// and you could have the attack animation on a higher
// layer than other animations to override them.
audio.PlayOneShot (attackSound);
yield WaitForSeconds(2.3);
// Play Attack Sounds when clwaing but don't play so often
if (Time.time > hitTimmer && attackSound && tearingFlesh){
audio.PlayOneShot(attackSound, 1.0 / audio.volume);
hitTimmer = Time.time + Random.Range(attackSound.length * 2, attackSound.length * 3);
}
else
{
// Play a tearing flesh sound
audio.PlayOneShot(tearingFlesh, 1.0 / audio.volume);
hitTimmer = Time.time + Random.Range(tearingFlesh.length * 2, tearingFlesh.length * 3);
}
}
yield StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
//Player not visible anymore - stop attacking
if (!CanSeeTarget())
return;
}
yield;
}
//}
function SearchPlayer (position : Vector3) { // Run towards the player but after 3 seconds timeout and go back to Patroling var timeout = 3.0;
while (timeout > 0.0)
{
MoveTowards(position);
// We found the player
if (CanSeeTarget ())
return;
timeout -= Time.deltaTime;
yield;
}
}
function RotateTowards (position : Vector3) { SendMessage("SetSpeed", 0.0);
var direction = position - transform.position;
direction.y = 0;
if (direction.magnitude < 0.1)
return;
// Rotate towards the target
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
}
function MoveTowards (position : Vector3) { var direction = position - transform.position; direction.y = 0; if (direction.magnitude < 0.5) { SendMessage("SetSpeed", 0.0); return;
}
// Rotate towards the target
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
// Modify speed so we slow down when we are not facing the target
var forward = transform.TransformDirection(Vector3.forward);
var speedModifier = Vector3.Dot(forward, direction.normalized);
speedModifier = Mathf.Clamp01(speedModifier);
// Move the character
direction = forward * speed * speedModifier;
GetComponent (CharacterController).SimpleMove(direction);
SendMessage("SetSpeed", speed * speedModifier, SendMessageOptions.DontRequireReceiver);
}
function PickNextWaypoint (currentWaypoint : AutoWayPoint) { // We want to find the waypoint where the character has to turn the least // The direction in which we are walking var forward = transform.TransformDirection(Vector3.forward);
// The closer two vectors, the larger the dot product will be.
var best = currentWaypoint;
var bestDot = -10.0;
for (var cur : AutoWayPoint in currentWaypoint.connected) {
var direction = Vector3.Normalize(cur.transform.position - transform.position);
var dot = Vector3.Dot(direction, forward);
if (dot > bestDot && cur != currentWaypoint) {
bestDot = dot;
best = cur;
}
}
return best;
}
Answer by Flash · Apr 19, 2012 at 04:27 PM
I don't know if you've figured this out yet but I did notice something strange in your code.
transform.rotation = Quaternion.Slerp(transform.rotation, rot,
transform.position += transform.forward * 5 * Time.deltaTime;
I'm not entirely sure if you just forgot to copy/paste parts of the code or if it looks like this in your code.
If we look at the first line:
transform.rotation = Quaternion.Slerp(transform.rotation, rot,
You are using the Slerp function which takes 3 parameters. 1: The "from" angle as a quaternion. 2: The "to" angle as a quaternion. 3: The speed at which to turn towards the "to" angle.
Now if you look at the two lines in your code again you will notice that you're actually passing "transform.position += transform.forward 5 Time.deltaTime;" in as the 3th parameter of the Slerp function which is not correct since "transform.position += transform.forward 5 Time.deltaTime;" is used for moving you're zombie enemy forward.
If you've not fixed this already try doing this:
transform.rotation = Quaternion.Slerp(transform.rotation, rot, 10 * Time.deltaTime);
transform.position += transform.forward * 5 * Time.deltaTime;
You can change 10 to adjust the speed at which the enemy turns. Try this and if it doesn't work then please throw a comment my way.