- Home /
Help with citizen conversation script.
Well, I have been doing fine writing scripts, but conversation ones always get me. The audio isn't playing, and the GUI doesn't show up. If anyone can tell me or show me what is wrong here it would be a lot of help. (NOTE: I can sometimes get clumsy with my scripts, so forgive me if it's something obvious.)
//The area in which you can be able to talk to the person.
var ConversationArea : GameObject;
//The different audio clips.
var PlayerHello : AudioClip;
var CitizenHello : AudioClip;
var PlayerBeMean : AudioClip;
var CitizenBeMeanResponse : AudioClip;
var PlayerCompliment : AudioClip;
var CitizenComplimentResponse : AudioClip;
var PlayerBeNice : AudioClip;
var CitizenBeNiceResponse : AudioClip;
var PlayerRob : AudioClip;
var CitizenRobResponse : AudioClip;
var PlayerMakeSmallTalk : AudioClip;
var CitizenMakeSmallTalkResponse : AudioClip;
//The lengths of the audio clips.
var PlayerHelloLength : Number;
var PlayerBeMeanLength : Number;
var PlayerComplimentLength : Number;
var PlayerBeNiceLength : Number;
var PlayerRobLength : Number;
var PlayerMakeSmallTalkLength : Number;
var CitizenHelloLength : Number;
//The direction the person is facing while in conversation.
var targetPosition : Transform;
var damp: int = 5;
//The style of the buttons.
var btnTexture : GUISkin;
var CanTalk : boolean;
var Player : GameObject;
var rotationAngle : Number;
//On start.
function Start () {
CanTalk = false;
}
//When player enters the trigger.
function OnTriggerEnter (ConversationArea : Collider) {
if(Player.tag == "Player") {
CanTalk = true;
}
}
//When player exits the trigger.
function OnTriggerExit (ConversationArea : Collider) {
if(Player.tag == "Player") {
CanTalk = false;
}
}
function OnGUI () {
GUI.skin = btnTexture;
}
if(CanTalk) {
//If N is pressed, conversation will start.
if (Input.GetKeyDown("N") && CanTalk) {
//The starting "hello"s.
audio.PlayOneShot(PlayerHello);
yield WaitForSeconds(PlayerHelloLength);
audio.PlayOneShot(CitizenHello);
yield WaitForSeconds (CitizenHelloLength);
//The different buttons.
if (GUI.Button(Rect(250,150,50,30),"Be Mean")) {
audio.PlayOneShot(PlayerBeMean);
yield WaitForSeconds (PlayerBeMeanLength);
audio.PlayOneShot(CitizenBeMeanResponse);
}
if (GUI.Button(Rect(250,190,50,30),"Compliment")) {
audio.PlayOneShot(PlayerCompliment);
yield WaitForSeconds (PlayerComplimentLength);
audio.PlayOneShot(CitizenComplimentResponse);
}
if (GUI.Button(Rect(250,230,50,30),"Be Nice")) {
audio.PlayOneShot(PlayerBeNice);
yield WaitForSeconds (PlayerBeNiceLength);
audio.PlayOneShot(CitizenBeNiceResponse);
}
if (GUI.Button(Rect(250,270,50,30),"Rob")) {
audio.PlayOneShot(PlayerRob);
yield WaitForSeconds (PlayerRobLength);
audio.PlayOneShot(CitizenRobResponse);
}
if (GUI.Button(Rect(250,310,50,30),"Make Small Talk")) {
audio.PlayOneShot(PlayerMakeSmallTalk);
yield WaitForSeconds (PlayerMakeSmallTalkLength);
audio.PlayOneShot(CitizenMakeSmallTalkResponse);
}
}
}
//Rotation, not done, work on it later.
if (rotationAngle) {
Quaternion.LookRotation(targetPosition.position - transform.position);
}
The booleans work correctly, and yield WaitForSeconds has given me trouble in the past, so I'm not exactly sure what could have gone wrong. Thanks in advance! (P.S. I know that the rotation isn't done yet, I just want to get the actual conversation done first.)
Answer by whydoidoit · Mar 25, 2013 at 09:05 PM
Your OnGUI has an extra } on line 51 in the listing above, the code that follows is not in OnGUI (this is one reason I don't like Unity Script - because that invalid code is apparently valid, just it doesn't run when you want it to!) Furthermore you can't yield in an OnGUI function... nor can you use Input (you have to use the Event.current properties).
Also, you'd be better off making a class of those conversations and responses and then your code would be about 30% of the current size and would be far more extendable!
Additionally PlayerMakeSmallTalk.length is the length in time of PlayerMakeSmallTalk etc.
@Serializable
class ConversationElement
{
var name : String;
var description : String;
var audio : AudioClip;
var showSpeechButton = true;
}
var playerSpeech : ConversationElement[];
var citizenSpeech : ConversationElement[];
function SaySomething(var options : ConversationElement[], var phrase : String)
{
for(var i = 0; i < options.Length; i++)
{
if(options[i].name == phrase)
{
audio.PlayOneShot(options[i].audio);
yield WaitForSeconds(options[i].audio.length);
break;
}
}
}
function SpeakAndRespond(var phrase : String)
{
CanTalk = false;
yield SaySomething(playerSpeech, phrase);
yield SaySomething(citizenSpeech, phrase);
CanTalk = true;
}
var Talking = false;
var CanTalk = true;
function OnGUI()
{
if( Talking && CanTalk)
{
var y = 150;
for(var thingToSay in playerSpeech)
{
if(thingsToSay.showSpeechButton)
{
if(GUI.Button(Rect(250,y,100,30), thingToSay.description)
{
StartCoroutine(SpeakAndRespond(thingToSay.name));
}
y+= 40;
}
}
}
}
function Update()
{
if(Input.GetKeyDown("n") && !Talking)
{
Talking = true;
StartCoroutine(SpeakAndRespond("Hello"));
}
}
With that you would do is use the inspector to fill out those arrays - dropping in your audio clips etc and naming them the same name for citizen and player. So e.g. name = "SmallTalk", description = "Make Small Talk", audio = some clip
Or it might be nicer to have one or more responses in the ConversationElement for the citizen and player:
@Serializable
class ConversationElement
{
var name : String;
var description : String;
var player : AudioClip[];
var citizen : AudioClip[];
var showSpeechButton = true;
}
var speech : ConversationElement[];
function SaySomething(var phrase : String) : ConversationElement
{
for(var i = 0; i < speech.Length; i++)
{
if(speech[i].name == phrase)
{
return speech[i];
}
}
return null;
}
function SpeakAndRespond(var phrase : String)
{
CanTalk = false;
var conversation = SaySomething(phrase);
if(conversation != null)
{
var playerSpeech =conversation.player[Random.Range(0, conversation.player.length)];
audio.PlayOneShot(playerSpeech);
yield WaitForSeconds(playerSpeech.length);
var citizenSpeech =conversation.citizen[Random.Range(0, conversation.citizen.length)];
audio.PlayOneShot(citizenSpeech);
yield WaitForSeconds(citizenSpeech.length);
}
CanTalk = true;
}
var Talking = false;
var CanTalk = true;
function OnGUI()
{
if( Talking && CanTalk)
{
var y = 150;
for(var thingToSay in speech)
{
if(thingsToSay.showSpeechButton)
{
if(GUI.Button(Rect(250,y,100,30), thingToSay.description)
{
StartCoroutine(SpeakAndRespond(thingToSay.name));
}
y+= 40;
}
}
}
}
function Update()
{
if(Input.Get$$anonymous$$eyDown("n") && !Talking)
{
Talking = true;
StartCoroutine(SpeakAndRespond("Hello"));
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613095103im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Help with a simple conversation script? 0 Answers
help whit WaitForSecond use. 1 Answer
Gui Playing Audio Trouble 1 Answer
Play Audio on Collision or Trigger Enter 4 Answers
someone is there? 1 Answer