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

How would I get an AI to say something when you press a button near him?

Discussion in 'Scripting' started by luhjgh, Jul 13, 2011.

  1. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    I am wondering how you can make it so that if you are close to an AI, you can press T, and the AI will say something (what he says is an audio file)

    I am guessing it would go something along the lines of:

    function GetButtonDown
    {
    if : PlayerProximity from GameObject Wormy the worm = 5
    {
    if : GetButtonDown = T
    {'PlayAudioClip: 'Hint'
    }
    }


    But I am not sure if that will work...

    Does anyone know how to make the AI say something when you press T?
     
  2. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    yes that will work, once you turn it from the pseudocode.to unity script.

    It probably does not need to be in its own function, but perhaps in the Update function or in some other dialogue function, etc.

    This is untested code, just did it looking at your pseudocode:
    Code (csharp):
    1. var player : Transform;
    2. var wormyWorm : Transform;
    3. var proximity : float = 5.0
    4. var hint : AudioClip;
    5.  
    6. if (Input.GetKeyDown("t")  Vector3.Distance( player.position, wormyWorm.position) <= proximity )
    7. {
    8.    audio.clip = hint ;
    9.     audio.Play();
    10. }
    of course if this script is on the Wormy the Worm object, then you don't need that variable - just replace wormyWorm.position with transform.position.
     
    Last edited: Jul 13, 2011
  3. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    I get one error:
    Assets/Scripts/Enemies/SaySomething.js(6,46): BCE0017: The best overload for the method 'UnityEngine.Vector3.Distance(UnityEngine.Vector3, UnityEngine.Vector3)' is not compatible with the argument list '(UnityEngine.Vector3, UnityEngine.Transform)'.


    Would I just change UnityEngine.Vector3 to UnityEngine.Transform?
     
  4. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    I edited my previous post just a moment ago when I noticed I forgot to add ".position" after wormyWorm - the code should be corrected now.
     
  5. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    Oh, it works.


    Thanks for your help!

    Here is an imaginary taco:
    [taco][/taco]
     
  6. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    Gah, I can't get it to play the sound file...
     
  7. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    do you have an audio source component on the same object that the script is on? or - is it giving an error message?
     
  8. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    Gah, unity forums lagged and posted my message 3 times.
     
    Last edited: Jul 13, 2011
  9. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    I get this error:
    UnityException: Input Key named: T is unknown
    UnityEngine.Input.GetKeyDown (System.String name) (at C:/BuildAgent/work/6bc5f79e0a4296d6/Runtime/ExportGenerated/Editor/BaseClass.cs:1186)
    SaySomething.Main () (at Assets/Scripts/Enemies/SaySomething.js:6)

    I assume I have to change the button?
     
  10. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    I get this error:
    UnityException: Input Key named: T is unknown
    UnityEngine.Input.GetKeyDown (System.String name) (at C:/BuildAgent/work/6bc5f79e0a4296d6/Runtime/ExportGenerated/Editor/BaseClass.cs:1186)
    SaySomething.Main () (at Assets/Scripts/Enemies/SaySomething.js:6)

    I assume I have to change the button?
     
  11. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    Just use "t" as lower case. If you really want "T" you need to check for both the shift key and the t key.
     
  12. luhjgh

    luhjgh

    Joined:
    Jan 1, 2011
    Posts:
    128
    Alright. I attached it to Wormy, and at the moment he has: An audio Source (no audio selected), A character Controller, SaySomething (the script you gave me) and my TurretControl script.


    When I press t it still gives me no sound.


    I also changed wormyWorm.position into transform.position

    Just so you know

    Any ideas?

    (also sorry if I am bothering you)
     
  13. pixellegolas

    pixellegolas

    Joined:
    Apr 10, 2011
    Posts:
    223
    well you have to drag an audio source to the script so it can call the audio. The script if you look at it only loads a AudioClip but you have to manually drag it on to the audioclip slot. Unity will not know what to play else
     
  14. priceap

    priceap

    Joined:
    Apr 18, 2009
    Posts:
    274
    As pixellegolas said, you need to set the audio clip.

    I added that part because of thinking you may want to add more dialog possibilities as it expands. This would allow you to add more audioclip variables and have a selection of dialog clips that could be called up. However, if the worm is only going to say one thing, then you could simply attach the audio source component with the one sound, and then only use audio.Play() in the script.

    I would stay with the first version, but this example illustrates what I mean, but what I am showing this example for is a way you can check if things are working without having dependency on something else working (e.g. audio set correctly). You can easily find if things are working by using Debug.Log and watching your console window.

    Code (csharp):
    1. var player : Transform;
    2. var proximity : float = 5.0
    3.  
    4. if (Input.GetKeyDown("t")  Vector3.Distance( player.position, transform.position) <= proximity )
    5. {
    6.     Debug.Log("the audio should play");
    7.     audio.Play();
    8. }
    9.  
     
  15. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    If you have multiple characters with which you can interact, spread out over a distance, you should consider creating a more general system for handling interaction.

    For example (untested):
    Code (csharp):
    1. void Update ()
    2. {
    3.     if (Input.GetKeyDown ("t"))
    4.     {
    5.         Interact ();
    6.     }
    7. }
    8.  
    9.  
    10. void Interact ()
    11. {
    12.     Collider[] colliders = Physics.OverlapSphere (transform.position, interactionRadius);
    13.         // Might want to apply a layer mask here, to reduce the cost of the query
    14.    
    15.     if (colliders.Length == 0)
    16.     {
    17.         return;
    18.     }
    19.    
    20.     float shortestDistance = Mathf.infinite;
    21.     GameObject closestInteractive = null;
    22.    
    23.     foreach (Collider collider in colliders)
    24.     {
    25.         GameObject root = collider.transform.root;
    26.         Vector3 direction = root.transform.position - transform.position;
    27.        
    28.         if (root.tag == "Interactive"  // Or whatever means you use for marking objects as interactive
    29.             Vector3.Angle (direction, transform.forward) < interactionViewCone
    30.                 // Don't interact with stuff behind us
    31.         )
    32.         {
    33.             if (shortestDistance > direction.sqrMagnitude)
    34.             // Find the closest interactive object
    35.             {
    36.                 shortestDistance = direction.sqrMagnitude;
    37.                 closestInteractive = root;
    38.             }
    39.         }
    40.     }
    41.    
    42.     if (closestInteractive != null)
    43.     // Interact if we found a good candidate
    44.     {
    45.         closestInteractive.SendMessage ("OnInteract");
    46.     }
    47. }