Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Rondom AI Movement whitout Waypoint.

Discussion in 'Scripting' started by pauloaguiar, Jul 14, 2011.

  1. pauloaguiar

    pauloaguiar

    Joined:
    May 13, 2009
    Posts:
    700
    How do put the A.I enemy moving rondom movement whitout using Waypoints. if A.I collide whit Wall colliders change direction etc....

    By using Raycast to change direction if collide whit an wall. !?

    function Update()
    {
    var hit : RaycastHit;
    if (Physics.Linecast (transform.position, transform.position, hit))
    ??????????????????????????????????


    }

    I'm afraid of messing up, so I ask here in the forum.

    By Using the A.I FPS tutorial.

    Code (csharp):
    1. var speed = 3.0;
    2. var rotationSpeed = 5.0;
    3. var shootRange = 15.0;
    4. var attackRange = 30.0;
    5. var shootAngle = 4.0;
    6. var dontComeCloserRange = 5.0;
    7. var delayShootTime = 0.35;
    8. var pickNextWaypointDistance = 2.0;
    9. var target : Transform;
    10. private var lastShot = -10.0;
    11. // Make sure there is always a character controller
    12. @script RequireComponent (CharacterController)
    13. function Start () {
    14.  // Auto setup player as target through tags
    15.  if (target == null  GameObject.FindWithTag("Player"))
    16.   target = GameObject.FindWithTag("Player").transform;
    17.  Patrol();
    18. }
    19. function Patrol ()
    20. {    
    21.  var curWayPoint = AutoWayPoint.FindClosest(transform.position);
    22.  while (true)
    23.  {
    24.   var waypointPosition = curWayPoint.transform.position;
    25.   // Are we close to a waypoint? -> pick the next one!
    26.   if (Vector3.Distance(waypointPosition, transform.position) < pickNextWaypointDistance)
    27.    curWayPoint = PickNextWaypoint (curWayPoint);
    28.   // Attack the player and wait until
    29.   // - player is killed
    30.   // - player is out of sight  
    31.   if (CanSeeTarget ())
    32.    yield StartCoroutine("AttackPlayer");
    33.  
    34.   // Move towards our target
    35.   MoveTowards(waypointPosition);
    36.  
    37.   yield;
    38.  }
    39. }
    40. function CanSeeTarget () : boolean {
    41.  if (Vector3.Distance(transform.position, target.position) > attackRange)
    42.   return false;
    43.  
    44.  var hit : RaycastHit;
    45.  if (Physics.Linecast (transform.position, target.position, hit))
    46.   return hit.transform == target;
    47.  return false;
    48. }
    49. function Shoot () {
    50.  // Start shoot animation
    51.  animation.CrossFade("shoot", 0.3);
    52.  // Wait until half the animation has played
    53.  yield WaitForSeconds(delayShootTime);
    54.  // Fire gun
    55.  BroadcastMessage("Fire");
    56.  // Wait for the rest of the animation to finish
    57.  yield WaitForSeconds(animation["shoot"].length - delayShootTime);
    58. }
    59. function AttackPlayer ()
    60. {
    61.  var lastVisiblePlayerPosition = target.position;
    62.  while (true) {
    63.   if (CanSeeTarget ())
    64.   {
    65.    // Target is dead - stop hunting
    66.    if (target == null)      
    67.     return;
    68.    // Target is too far away - give up
    69.    var distance = Vector3.Distance(transform.position, target.position);
    70.    if (distance > shootRange * 3)
    71.     return;
    72.  
    73.    lastVisiblePlayerPosition = target.position;  
    74.    if (distance > dontComeCloserRange)      
    75.     MoveTowards (lastVisiblePlayerPosition);    
    76.    else
    77.     RotateTowards(lastVisiblePlayerPosition);
    78.    var forward = transform.TransformDirection(Vector3.forward);
    79.    var targetDirection = lastVisiblePlayerPosition - transform.position;
    80.    targetDirection.y = 0;
    81.    var angle = Vector3.Angle(targetDirection, forward);
    82.    // Start shooting if close and play is in sight
    83.    if (distance < shootRange  angle < shootAngle)
    84.     yield StartCoroutine("Shoot");
    85.   }
    86.   else
    87.   {
    88.    yield StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
    89.    // Player not visible anymore - stop attacking
    90.    if (!CanSeeTarget ())
    91.     return;
    92.   }
    93.   yield;
    94.  }
    95. }
    96. function SearchPlayer (position : Vector3)
    97. {
    98.  // Run towards the player but after 3 seconds timeout and go back to Patroling
    99.  var timeout = 3.0;
    100.  while (timeout > 0.0)
    101.  {
    102.   MoveTowards(position);
    103.   // We found the player
    104.   if (CanSeeTarget ())
    105.    return;
    106.   timeout -= Time.deltaTime;
    107.   yield;
    108.  }
    109. }
    110. function RotateTowards (position : Vector3)
    111. {
    112.  SendMessage("SetSpeed", 0.0);
    113.  
    114.  var direction = position - transform.position;
    115.  direction.y = 0;
    116.  if (direction.magnitude < 0.1)
    117.   return;
    118.  
    119.  // Rotate towards the target
    120.  transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    121.  transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    122. }
    123. function MoveTowards (position : Vector3)
    124. {
    125.  var direction = position - transform.position;
    126.  direction.y = 0;
    127.  if (direction.magnitude < 0.5)
    128.  {
    129.   SendMessage("SetSpeed", 0.0);
    130.   return;
    131.  }
    132.  // Rotate towards the target
    133.  transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    134.  transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    135.  // Modify speed so we slow down when we are not facing the target
    136.  var forward = transform.TransformDirection(Vector3.forward);
    137.  var speedModifier = Vector3.Dot(forward, direction.normalized);
    138.  speedModifier = Mathf.Clamp01(speedModifier);
    139.  // Move the character
    140.  direction = forward * speed * speedModifier;
    141.  GetComponent (CharacterController).SimpleMove(direction);
    142.  
    143.  SendMessage("SetSpeed", speed * speedModifier, SendMessageOptions.DontRequireReceiver);
    144. }
    145. function PickNextWaypoint (currentWaypoint : AutoWayPoint)
    146. {
    147.  // We want to find the waypoint where the character has to turn the least
    148.  // The direction in which we are walking
    149.  var forward = transform.TransformDirection(Vector3.forward);
    150.  // The closer two vectors, the larger the dot product will be.
    151.  var best = currentWaypoint;
    152.  var bestDot = -10.0;
    153.  for (var cur : AutoWayPoint in currentWaypoint.connected)
    154.  {
    155.   var direction = Vector3.Normalize(cur.transform.position - transform.position);
    156.   var dot = Vector3.Dot(direction, forward);
    157.   if (dot > bestDot  cur != currentWaypoint)
    158.   {
    159.    bestDot = dot;
    160.    best = cur;
    161.   }
    162.  }
    163.  return best;
    164. }
     
  2. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    There have been a lot of AI interests posted lately!

    I had success with a wandering AI crowd system by having two raycasts, each at a 45 degree angle in front of the AI. This controlled the collision avoidance by steering the AI away from the obstacle and had the nice effect of centering them up between obstacles. If the two raycasts do not succeed in steering the AI out of something like a corner, each was given a random bias for turning direction to escape so that they do not all look like they are doing similar things.

    However, I found that doing this without waypoints ultimately looked too aimless. In this case the AI were people and they wound up looking like they were all not very smart. I then introduced a simple wayfinding node system into it and now they seem to be more like pedestrians. So consider what your AI are supposed to be in regard to the option not to use waypoints.

    the second part of the video shows the raycasting debug lines
    http://youtu.be/uUjPSqsvvnA
     
  3. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    Hm, I asked this same question...
     
  4. pauloaguiar

    pauloaguiar

    Joined:
    May 13, 2009
    Posts:
    700

    Yep, the same i´m trying to do. The most import of the game is the A.I.
    I´m going try play around whit the A.I FPS script to see what i can get.
    Some tips, and help is wellcome.

    Some pic of my game;)
     

    Attached Files:

  5. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Without any pre-baked navigation information, such as waypoints, aimless trotting around in a larger area is going to look really silly.

    What you could do is aim for just walking around in the immediate vicinity of your starting location. You could do that by using ray- and spherecasts to find out an unobstructed area with a radius as large as possible, containing the starting location. Once you have that, you can do some actual planning of your aimless wandering.

    I guess the very good question is why would you want to avoid pre-baking navigation information? Even if you procedurally generate your level, you should be able to build a navigation tree.
     
  6. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    You do want to use waypoints, not the otherway.
    Its a game afterall, you dont want to invent some robot or somethin do you?

    Here is my attempt for some wandering neutral entities and an aggressive entity.

    It uses waypoints and astar for pathfinding,
    entities choose to visit random position inside a convex or concave polygon(you can call it a navmesh though), pre-set point of interests(pre-set path ways) and according to situation, pre-set hiding points if necessary.
    and the whole thing uses raycast only in the awake function, while walking or pathfinding, the heaviest calculation is a distance check and its done on 2D plane.
     
  7. pauloaguiar

    pauloaguiar

    Joined:
    May 13, 2009
    Posts:
    700

    "Its a game afterall, you dont want to invent some robot or somethin do you?"
    In this Q , using robot for testing porpose. I have soldier whit 5500 frames of animation as you can see in the 2 picture.

    Sence the unity 3d v3.5 comes whit pathfinder, is the easy solution for this, that depends how is working on unity 3d.
    i work in other engines pathfinder in the past. great tool for my point of view and used.

    I have a few headaches to resolve it.

    Using spherecasts, good idea. The problem is put it to work properly.

    I'm currently trying to make respectful way.
    Using extensions, for me is not the solution. For several reasons. Compatibility among other scripts. Errors after errors is not recommended for anyone:)

    I´m playing around whit the raycasts.
     
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    whatever suits you:)
     
  9. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    I would use Random.insideUnitCircle().
     
  10. pauloaguiar

    pauloaguiar

    Joined:
    May 13, 2009
    Posts:
    700
    Sorry mates I can´t do it:( pain in the ass to do this:(
    Sorry, it was a waste of time.:(
    tks for tips.
     
    Last edited: Jul 14, 2011
  11. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,090
    Not tested, but something along these lines should work:

    Code (csharp):
    1.  
    2. var wanderRadius : float = 10.0;
    3. var moveSpeed : float = 5.0;
    4. var pauseTime : float = 3.0;
    5.  
    6. private var nextPoint : Vector3;
    7.  
    8. function Start(){
    9.     ChooseNextPoint();
    10.     yield Wander();
    11. }
    12.  
    13. function Wander(){
    14.     while(true){  
    15.             transform.LookAt(nextPoint);
    16.             transform.Translate(transform.forward*moveSpeed*Time.deltaTime);    
    17.             if(Vector3.Distance(transform.position, nextPoint) < stopDistance){
    18.                     yield WaitForSeconds(pauseTime);
    19.                     ChooseNextPoint();
    20.             }    
    21.             yield;      
    22.     }
    23. }
    24.  
    25. function ChooseNextPoint(){
    26.     nextPoint = Random.insideUnitSphere*wanderRadius;
    27.     nextPoint.y = transform.position.y;
    28. }
    29.  
    30.  
     
  12. pauloaguiar

    pauloaguiar

    Joined:
    May 13, 2009
    Posts:
    700

    So far i start to made an basic A.I , just have an problem lookAt currenct waypoint don´t work !?

    Someting i mess up!??

    Code (csharp):
    1. var shoot : Rigidbody;
    2. var target : Transform;
    3. var lastshoot = 0;
    4. var bulletSpeed : float = 3000;
    5. var explo : Transform;
    6. var FireZone : Transform;
    7. var waypoints : Transform[];
    8. var curWaypoint : Transform;
    9. var WayNumber = 0;
    10. var Player : Transform;
    11. function Awake()
    12. {
    13.  Player = gameObject.FindWithTag("Player").transform;
    14.  curWaypoint = waypoints [null];
    15. }
    16.  
    17. function FixedUpdate()
    18. {
    19.  if (Vector3.Distance(Player.position, transform.position) > 30)
    20.  {  
    21.   if (Vector3.Distance(transform.position, curWaypoint.position)< 5)
    22.   {
    23.       if(WayNumber < 1)
    24.    {
    25.        WayNumber++;
    26.    }
    27.    else
    28.    {
    29.     WayNumber = 0;      
    30.    }    
    31.   }  
    32.   curWaypoint = waypoints [WayNumber];  
    33.   transform.LookAt(curWaypoint);
    34.   transform.Translate(Vector3.forward * 0.1);  
    35.  }
    36.  
    37. }
    38. function Update ()
    39. {
    40.  
    41.     if(target == null)
    42.     {
    43.      target = transform;
    44.   //transform.LookAt(curWaypoint); //if not see me return to currenct waypoint.
    45.  }
    46.  if (Vector3.Distance(transform.position, Player.position) < 30)
    47.  {
    48.      target = Player;
    49.   //transform.LookAt(Player); //View range look at player
    50.   transform.Translate(Vector3.forward * 0.1); // start follow the player
    51.   shooting();
    52.  
    53.  }
    54.  transform.LookAt(target.position);    
    55. }
    56. function shooting()
    57. {
    58.     if(Time.time >= lastshoot +1)
    59.  {
    60.      Instantiate(explo, FireZone.position, Quaternion.identity);
    61.      var bullet = Instantiate(shoot, FireZone.position, transform.rotation);
    62.         bullet.rigidbody.AddForce(transform.forward * bulletSpeed);  
    63.      lastshoot = Time.time;
    64.  }
    65.  
    66. }