Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Decellerating Ai based on Player proximity

Discussion in 'Scripting' started by AaronC, May 4, 2007.

  1. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Heres my submarineAi script, and 2 questions:
    Im trying to get the sub to come within a set distance of the Player, and the shoot. I am trying to fiwrite a "HoldPosition" function, because I want to slow the sub's motion down which is based on force... I guess thats quite dependent on how Im calling Both the Move Towards and HoldPosition functions also, because I dont want to be calling MoveTowards and Hold position at the same time I dont think...either one or the other...I guess even opinions there would be helpful right now..

    I figure ForceMode.VelocityChange is best to slow the objects speed down, but I dont know to get it into code. So the Ai subs' existence is to spawn, Find enemy and move towards, get to a set distance from the player, and start shooting...

    Thanks for any help!

    Code (csharp):
    1. var Speed = 3.0;
    2. var rotationSpeed = 5.0;
    3. var shootRange = 15.0;
    4. var attackRange = 30.0;
    5. var difference = 4.0;
    6. var shootAngle = 4.0;
    7. var dontComeCloserRange = 5.0;
    8. var delayShootTime = 0.35;
    9. var target : Transform;
    10.  
    11.  
    12. private var lastShot = -10.0;
    13.  
    14.  
    15.  
    16.  
    17.  
    18. function Update(){
    19.    
    20.   if (target == null  GameObject.FindWithTag("Player")) {
    21.                target = GameObject.FindWithTag("Player").transform;
    22.   }
    23.  
    24.  
    25.       var targetDirection = target.transform.position - transform.position;
    26.       var forward = transform.TransformDirection(Vector3.forward);
    27.       var angle = Vector3.Angle(targetDirection, forward);
    28.       var distance = Vector3.Distance(transform.position, target.position);
    29.        var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    30. var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);
    31. transform.rotation = Quaternion.Lerp (transform.rotation, targetRotation, str);
    32.  
    33. if (distance < shootRange  angle < shootAngle)
    34.          StartCoroutine("Shoot");
    35.          if (distance > shootRange  angle < shootAngle)
    36.         MoveTowards();
    37. }
    38.  
    39.  
    40. function Shoot ()
    41. {
    42.    
    43.    
    44.    // Fire gun
    45.    BroadcastMessage("Fire");
    46.    
    47.    // Wait for the rest of the animation to finish
    48.    yield WaitForSeconds(delayShootTime);
    49. }
    50.  
    51. function RotateTowards (position : Vector3)
    52. {
    53.    
    54.    
    55.    var direction = position - transform.position;
    56.    direction.y = 0;
    57.    if (direction.magnitude < 0.1)
    58.       return;
    59.    
    60.    // Rotate towards the target
    61.    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    62.    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    63. }
    64.  
    65. function MoveTowards ()
    66. {
    67.    
    68.   rigidbody.AddForce (0, 0, (Speed*10));
    69.    if (distance < shootRange  angle < shootAngle)
    70.       HoldPosition();
    71.    
    72.    
    73.    }
    74. function HoldPosition(){
    75.         rigidbody.AddForce
    76. //In here I am not sure how to apply thr force to slow down the object...
    77. //?ForceMode.VelocityChange?//
    78. );
    79.         }  
    80.  
    Thanks
    AC
     
  2. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    At a quick glance...

    function MoveTowards ()
    {

    rigidbody.AddForce (0, 0, (Speed*10));
    if (distance < shootRange angle < shootAngle)
    HoldPosition();


    }

    Doesn't work, because you are adding the force even though you might be telling the sub to holdposition.... something more like this simple logic.

    function WhatShouldTheSubDo ()
    {
    if (distance < shootRange)
    HoldPosition();
    else
    MoveSub();

    if(angle < shootAngle)
    {
    if (distance < shootRange)
    {
    Shoot();
    }
    }
    else
    {
    RotateSub();
    }

    }

    The sub should be able to rotate independently of the move/hold, and should only shoot if position and rotation are right.
     
  3. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Okay, go that. So heres how it looks now-Hopefully its an improvement, But I still need to fix the "Hold Position" function so It an compile and I can test it
    Code (csharp):
    1. var Speed = 3.0;
    2. var rotationSpeed = 5.0;
    3. var shootRange = 15.0;
    4. var attackRange = 30.0;
    5. var difference = 4.0;
    6. var shootAngle = 4.0;
    7. var dontComeCloserRange = 5.0;
    8. var delayShootTime = 0.35;
    9. var target : Transform;
    10.  
    11.  
    12. private var lastShot = -10.0;
    13.  
    14.  
    15.  
    16.  
    17.  
    18. function Update(){
    19.    
    20.   if (target == null  GameObject.FindWithTag("Player")) {
    21.                target = GameObject.FindWithTag("Player").transform;
    22.   }
    23.  
    24.  
    25.       var targetDirection = target.transform.position - transform.position;
    26.       var forward = transform.TransformDirection(Vector3.forward);
    27.       var angle = Vector3.Angle(targetDirection, forward);
    28.       var distance = Vector3.Distance(transform.position, target.position);
    29.        var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    30. var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);
    31. transform.rotation = Quaternion.Lerp (transform.rotation, targetRotation, str);
    32.  
    33. if (distance < shootRange  angle < shootAngle)
    34.          StartCoroutine("Shoot");
    35.          if (distance > shootRange  angle < shootAngle)
    36.     WhatShouldTheSubDo();
    37. }
    38. function WhatShouldTheSubDo ()
    39. {
    40. if (distance < shootRange)
    41. HoldPosition();
    42. else
    43. MoveSub();
    44.  
    45. if(angle < shootAngle)
    46. {
    47. if (distance < shootRange)
    48. {
    49. Shoot();
    50. }
    51. }
    52. else
    53. {
    54. RotateSub();
    55. }
    56.  
    57. }
    58.  
    59. function Shoot ()
    60. {
    61.    
    62.    
    63.    // Fire gun
    64.    BroadcastMessage("Fire");
    65.    
    66.    // Wait for the rest of the animation to finish
    67.    yield WaitForSeconds(delayShootTime);
    68. }
    69.  
    70. function RotateSub (position : Vector3)
    71. {
    72.    
    73.    
    74.    var direction = position - transform.position;
    75.    direction.y = 0;
    76.    if (direction.magnitude < 0.1)
    77.       return;
    78.    
    79.    // Rotate towards the target
    80.    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    81.    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    82. }
    83.  
    84. function MoveTowards ()
    85. {          var targetDirection = target.transform.position - transform.position;
    86.       var forward = transform.TransformDirection(Vector3.forward);
    87.       var angle = Vector3.Angle(targetDirection, forward);
    88.       var distance = Vector3.Distance(transform.position, target.position);
    89.        var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    90. var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);  
    91.   rigidbody.AddForce (0, 0, (Speed*10));
    92.    if (distance < shootRange  angle < shootAngle)
    93.       HoldPosition();
    94.    
    95.    
    96.    }
    97. function HoldPosition(){
    98. ///Yeehaa now to fix this bit
    99. ForceMode.VelocityChange(  Vector3 (0, 0.3, 0));
    100.       Shoot();
    101.         }  
    102.  
    Thanks Seon-What you said made it a bit clearer, for sure...
    AC
     
  4. podperson

    podperson

    Joined:
    Jun 6, 2006
    Posts:
    1,371
    A general observation of writing AI code:

    Probably a good general approach is to think of your AI as a finite state machine. Give it a bunch of states (e.g. "unaware" "trying to close" "shadowing" "fleeing" "shooting" "hiding"), a decision-making process, and some kind of mechanism for determining how often the AI changes state.

    (From the Finite State Machine point of view, what you're coding isn't "AI" but "actions". Tracking a target and moving towards it are actions an enemy may or may not take depending on their internal "state".)

    The key point here is that "AI" in some respects is too easy to do. What you want is "AS" (artifical stupidity) and/or "IB" (interesting behavior). An AI that singlemindedly charges towards you and fires with deadly accuracy is more like a missile than an opponent, and generally the fun in computer games is recognising enemy behavior patterns and exploiting them.

    Once you start coding this way, you'll discover all kinds of benefits:

    1) You can easily vary the deadliness of an opponent's behavior.

    2) You can make behaviors that are amusing or stupid.

    3) You can give enemies "personalities".
     
  5. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Hmm I agree Podperson. Its not intelligence, its decision making based on Parameters-which should be easy to do...

    I have tried to make this easier to read, and I apologise if the previous posts had too much clutter, and are therefore confusing/annoying...

    Perhaps snippets are easier to trouble shoot? The thing is I couldnt really say what to leave in and what to leave out...

    the error is: error BCE0017: The best overload for the method 'AI 2.Shoot(UnityEngine.Vector3)' is not compatible with the argument list '()'

    Wheres a good place to start finding the language errors here?-Sorry, Im looking at my third day of trying to get this to compile..
    Thanks
    Code (csharp):
    1. var Speed = 3.0;
    2. var rotationSpeed = 5.0;
    3. var shootRange = 15.0;
    4. var attackRange = 30.0;
    5. var difference = 4.0;
    6. var shootAngle = 4.0;
    7. var dontComeCloserRange = 5.0;
    8. var delayShootTime = 0.35;
    9. var target : Transform;
    10.  
    11.  
    12. private var lastShot = -10.0;
    13.  
    14.  
    15.  
    16.  
    17.  
    18. function Update(){
    19.    
    20.   if (target == null  GameObject.FindWithTag("Player")) {
    21.                target = GameObject.FindWithTag("Player").transform;
    22.   }
    23.  
    24.  
    25.       var targetDirection = target.transform.position - transform.position;
    26.      
    27.       var forward = transform.TransformDirection(Vector3.forward);
    28.      
    29.       var angle = Vector3.Angle(targetDirection, forward);
    30.      
    31.       var distance = Vector3.Distance(transform.position, target.position);
    32.      
    33.        var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    34.        
    35.        var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);
    36.        
    37. transform.rotation = Quaternion.Lerp (transform.rotation, targetRotation, str);
    38.  
    39.     WhatShouldTheSubDo();
    40.    
    41. }
    42.  
    43. function WhatShouldTheSubDo () {
    44.    
    45.       var targetDirection = target.transform.position - transform.position;
    46.      
    47.       var forward = transform.TransformDirection(Vector3.forward);
    48.      
    49.       var angle = Vector3.Angle(targetDirection, forward);
    50.      
    51.       var distance = Vector3.Distance(transform.position, target.position);
    52.      
    53.        var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    54.        
    55.        var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);
    56.        
    57. transform.rotation = Quaternion.Lerp (transform.rotation, targetRotation, str);
    58.    
    59. if (distance > shootRange)
    60.  
    61.      MoveTowards();
    62.      yield;
    63.  
    64. if(distance < shootRange  angle < shootAngle)
    65.      
    66.      Shoot();
    67.      yield;
    68.  
    69. if(distance < shootRange  angle > shootAngle)
    70.  
    71.       RotateSub();
    72.        yield;
    73. }
    74.  
    75. function Shoot (position : Vector3)
    76. {
    77.    
    78.    
    79.    // Fire gun
    80.    BroadcastMessage("Fire");
    81.    
    82.    // Wait for the rest of the animation to finish
    83.    yield WaitForSeconds(delayShootTime);
    84. }
    85.  
    86. function RotateSub (position : Vector3)
    87. {
    88.    var direction = position - transform.position;
    89.    
    90.     direction.y = 0;
    91.  
    92. if (direction.magnitude < 0.1)
    93.    
    94.     return;
    95.    
    96.    // Rotate towards the target
    97.    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    98.    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    99.  
    100. }
    101.  
    102. function MoveTowards ()
    103. {    
    104.      var targetDirection = target.transform.position - transform.position;
    105.      
    106.      var forward = transform.TransformDirection(Vector3.forward);
    107.      
    108.      var angle = Vector3.Angle(targetDirection, forward);
    109.      
    110.      var distance = Vector3.Distance(transform.position, target.position);
    111.      
    112.      var targetRotation = Quaternion.LookRotation(targetDirection.normalized);
    113.      
    114.      var str = Mathf.Min(rotationSpeed * Time.deltaTime, 1);  
    115.      
    116.   rigidbody.AddForce (0, 0, (Speed*10));
    117.  
    118.    }
    119.    
    120. function HoldPosition(){
    121.    
    122.   rigidbody.velocity= Vector3 (0,0,.05);
    123.  
    124.      Shoot();
    125. }
    PS, if you just want to advise me on how to make it more readable, thats cool too. Cheers
    AC
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You've defined Shoot as "Shoot (position : Vector3)", but you're just calling it with Shoot(), and not passing it a vector3. Although you're not doing anything with "position" in Shoot anyway.

    --Eric
     
  7. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Eric Said
    Yes-Thats where I understand the problem is. If I have the (position : Vector3) part in both, it doesnt compile. If I have it in neither, it also does not compile. Is this something to do with properties vs varibles or similar?

    Thanks for seeing the problem-as I saw it too...(But I just dont get it)

    EDIT Whoops that one fixes ok its the rotate sub function I mean
    AC :oops:
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    When you define a function like "function Shoot (position : Vector3)", that means you have to pass an actual vector3 when you call the function. Like "Shoot(vector3(4, 7, 82) )". Or

    Code (csharp):
    1.  
    2. var myVector = Vector3(30, 20, 10);
    3. Shoot(myVector);
    4.  
    However, your function should actually do something with the variable that you're passing...otherwise there's no need for it.

    --Eric
     
  9. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Yeah i goofed that up for some reason...That function actually worked( Should've removed that before posting.)

    The bit that never worked, was the rotate Sub function:
    Code (csharp):
    1. function RotateSub (position : Vector3)
    2. {
    3.    var direction = position - transform.position;
    4.    
    5.     direction.y = 0;
    6.  
    7. if (direction.magnitude < 0.1)
    8.    
    9.     return;
    10.    
    11.    // Rotate towards the target
    12.    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    13.    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
    14.  
    15. }
    16.  
    Thats the one that doesnt let me call RotateSub(); or RotateSub(position:Vector3); I cant pull "position:Vector 3 out because that doesnt work either...
    Damn this is hard to explain . All I need is a stupid mistake (directing you to the wrong function)and I make it even worse...
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's the same problem though. When you define RotateSub as you have, it's saying "Hey, give me a Vector3 when you call me." But "RotateSub()" passes nothing, so it fails. "RotateSub(position:Vector3)" is defining "position" as a vector3 and not passing anything, so that fails. You need to call RotateSub with an actual vector3 from somewhere.

    Code (csharp):
    1.  
    2. var someplace = Vector3(22, 35, 66);
    3. RotateSub (someplace);
    4.  
    That's just an example; I haven't read through all your code to see what it does. But that's how you call functions using variables.

    --Eric
     
  11. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Ok cool. Thanks Eric. Thats got to help

    I appreciate your skill and helpfulness a lot...thank you...

    AC