- Home /
Enemy not rotating when inside range
Hello,
I have had this problem for a while but I have not been able to find an answer. When the player gets within a certain distance, the enemy rotates and moves towards the player. When he within a closer distance, he stops so that he won't run into the player. When he is within the second distance, he stops rotating. I have an archer so when he stops rotating he won't be able to hit the player if he moves just inches from the side.
This is what I have got:
// vars
var target : Vector3;
public var dir : Vector3;
private var dirFull : Vector3;
public var mindist:float;
public var maxdist:float;
public var civilian:boolean;
public var Wander:boolean;
public var dist:float;
public var wayPoint : Vector3;
public var speed : float = 1;
public var WanderDistance:float;
public var pickPoint:boolean = true;
public var CantMove:boolean;
public var added:boolean;
public var size:float;
function Update()
{
var curY:float = transform.position.y;
//Find The Player/Distance
target = GameObject.FindGameObjectWithTag("Player").transform.position;
dist = Vector3.Distance(target, transform.position);
//Dont Want to shoot through walls.
var hit : RaycastHit;
//If it is between the maximum distance
if(dist < maxdist){
//the minimum distance
if(dist > mindist){
//direction to rotate
dir = (target - transform.position).normalized;
// check for forward raycast
if (Physics.Raycast(transform.position, transform.forward, hit, 20))
{
if (hit.transform != this.transform)
{
Debug.DrawLine (transform.position, hit.point, Color.white);
dir += hit.normal * 20; // 20 is force to repel by
}
}
// more raycasts
var leftRay = transform.position + Vector3(-0.125, 0, 0);
var rightRay = transform.position + Vector3(0.125, 0, 0);
// check for leftRay raycast
if (Physics.Raycast(leftRay, transform.forward, hit, 20))
{
if (hit.transform != this.transform)
{
Debug.DrawLine (leftRay, hit.point, Color.red);
dir += hit.normal * 20; // 20 is force to repel by
}
}
// check for rightRay raycast
if (Physics.Raycast(rightRay, transform.forward, hit, 20))
{
if (hit.transform != this.transform)
{
Debug.DrawLine (rightRay, hit.point, Color.green);
dir += hit.normal * 20; // 20 is force to repel by
}
}
//Keep going forward
transform.position += transform.forward * speed * Time.deltaTime;
//Stay on the same Y position
transform.position.y = curY;
}//Ends Minimum Distance
//Calculates rotation
var rot;
rot = Quaternion.LookRotation (dir);
//Civilians run away
if(civilian == true){
rot = Quaternion.Inverse(rot);
}
//Performs rotation
transform.rotation = Quaternion.Slerp (transform.rotation, rot, Time.deltaTime);
//Ends Maximum Distance
}else{
//Wandering When out of range
PickPos();
transform.LookAt(wayPoint);
transform.position += transform.forward * speed * Time.deltaTime;
}
}
function PickPos()
{
if((transform.position - wayPoint).magnitude <= 3||pickPoint == true){
wayPoint= Random.insideUnitSphere *WanderDistance;
wayPoint.y = transform.position.y;
transform.LookAt(wayPoint);
pickPoint = false;
}
}
function OnCollisionEnter(hit:Collision){
transform.position += transform.forward * speed * -1 * Time.deltaTime;
pickPoint = true;
CantMove=true;
}
function OnCollisionExit(hit:Collision){
CantMove=false;
}
Answer by SinisterRainbow · Jun 27, 2013 at 09:54 PM
thnx for reformatting. (just less white space and scope alignment is fine for many).. Your 'dir' force fails only when the raycasts fail. I'm a little confused with your raycasts. You set the left and right ray casts to different x-positions in real world space. Regardless of the rotation of the archer, they will always face real world x. I think your intention is to have these sort of be a perception area? You need to use TransformDirection() if so. Also, if a perception area you may want to do this differently, if you want say an x degree perception area just calculate the direction to target (no raycast) and the forward direction of archer and compare angles. if the target lies within, rotate and shoot.. the first forward raycast will never cause rotation by definition, if the target is there it doesn't need to rotate, if the target is not there, it won't rotate. so it's left to the left and right raycasts which are always pointing int the same direction regardless of rotation.
Also once the target lies within a minimum distance, I would not not use raycasts any longer. Say if you are 15m from your target, I would make perception 100%, and always rotate towards the target..As a bonus (used in CryEngine for example and a few others) at even smaller distances (as an archer), have him move away from the target. Say when under 5 feet. A melee character won't want this, but an archer likely would depending on game of course.
This is very helpful. The raycasts make the enemy avoid walls, which I might still end up using, but for targeting I think I use your idea. Also I like the archer idea.
Glad to help. Yah, path finding is a different matter .. you can do raycasts but with many characters it's expensive and it's never full proof unfortunately so they run into stuff and get stuck. usually you'll want to set up good paths ahead of time (in the editor), like tactical way points..because you have height problems, and pathfinding problems that would take many rays (and rarely be full proof without being super expensive). if you want real time, there's some theories out there like randomly populating the ground around the player, make a graph, then use aStar.. but it's expensive on the fly. I just posted an Astar search alg in another post if you want to use it. (C#).
Your answer
Follow this Question
Related Questions
Enemy following Player in range 2 Answers
Help with Enemy AI 1 Answer
Problem with the movement of AI 1 Answer
Waypoint System help 1 Answer
How to make the enemy move back to its waypoint after it's target killed? 2 Answers