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;
}