I have four buttons using the same prefab and holding 4 text elements from an array out of which only one is assigned bool value to true. I am trying to access that true element when any of false element is clicked. i want to highlight true element when the false element is clicked. can anyone please help me to achieve this functionality?
using simpleobjectpool
taking reference from unity quiz game tutorial
Thanks
Answer Button Script
public class AnswerButton : MonoBehaviour
{
public Text answerText;
private AnswerData answerData;
private GameController gameController;
private bool isCorrect;
void Start()
{
gameController = FindObjectOfType<GameController>();
}
public void Setup(AnswerData data)
{
answerData = data;
answerText.text = answerData.answerText;
}
public void HandleClick()
{
gameController.AnswerButtonClicked(answerData.isCorrect);
{
if (answerData.isCorrect)
{
}
if (!answerData.isCorrect)
{
}
}
Answer Data Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class AnswerData
{
public string answerText;
public bool isCorrect;
}
QuestionData Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class QuestionData
{
public string questionText;
public AnswerData[] answers;
}
Game Controller Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System;
public class GameController : MonoBehaviour
{
public Text questionText;
public Text scoreDisplayText;
public SimpleObjectPool answerButtonObjectPool;
public Transform answerButtonParent;
public GameObject questionPanel;
public GameObject roundOverPanel;
public GameObject levelsPanel;
private DataController dataController;
private RoundData currentRoundData;
private bool isRoundActive;
private float timeBeetweenQuestions = 3.0f;
private List<GameObject> answerButtonGameObjects = new List<GameObject>();
private QuestionData[] questionPool;
private int questionIndex;
private int qNumber = 0;
private List<int> questionIndexesChosen = new List<int>();
public int playerScore = 0;
public int totalQuestions;
private static int pointAddedForCorrectAnswer;
public AudioSource answerButtonClicked;
public AudioSource wrongAnswerClicked;
void Start ()
{
dataController = FindObjectOfType<DataController>();
currentRoundData = dataController.GetCurrentRoundData();
questionPool = currentRoundData.questions;
playerScore = 0;
questionIndex = 0;
scoreDisplayText.text = "Score: " + playerScore.ToString();
isRoundActive = true;
ShowQuestion();
}
private void ShowQuestion()
{
RemoveAnswerButtons();
QuestionData questionData = questionPool[questionIndex];
questionText.text = questionData.questionText;
for (int i = 0; i < questionData.answers.Length; i++)
{
GameObject answerButtonGameObject =
answerButtonObjectPool.GetObject();
answerButtonGameObjects.Add(answerButtonGameObject);
answerButtonGameObject.transform.SetParent(answerButtonParent);
AnswerButton answerButton =
answerButtonGameObject.GetComponent<AnswerButton>();
AnswerButton.Setup(questionData.answers[i]);
}
}
private void RemoveAnswerButtons()
{
while (answerButtonGameObjects.Count > 0)
{
answerButtonObjectPool.ReturnObject(answerButtonGameObjects[0]);
answerButtonGameObjects.RemoveAt(0);
}
}
IEnumerator TransitionToNextQuestion()
{
yield return new WaitForSeconds(timeBeetweenQuestions);
ShowQuestion();
}
IEnumerator WaitForFewSeconds()
{
yield return new WaitForSeconds(timeBeetweenQuestions);
EndRound();
}
IEnumerator ReturnCorrectButtonColor()
{
Debug.Log("im correct");
GetComponent<Button>().image.color = Color.green;
yield return new WaitForSeconds(seconds: 2.9f);
GetComponent<Button>().image.color = Color.white;
}
IEnumerator ReturnWrongButtonColor()
{
Debug.Log("im wrong");
GetComponent<Button>().image.color = Color.red;
yield return new WaitForSeconds(seconds: 2.9f);
GetComponent<Button>().image.color = Color.white;
}
public void AnswerButtonClicked (bool isCorrect)
{
if (isCorrect)
{
playerScore += currentRoundData.pointAddedForCorrectAnswer;
scoreDisplayText.text = "Score: " + playerScore.ToString();
//play coorect answer sound
answerButtonClicked.Play();
StartCoroutine(ReturnCorrectButtonColor());
}
if (!isCorrect)
{
//play wrong answer sound
answerButtonClicked = wrongAnswerClicked;
answerButtonClicked.Play();
StartCoroutine(ReturnWrongButtonColor());
// buttons = GameObject.FindGameObjectsWithTag("Answer");
// {
// foreach (GameObject button in buttons)
// {
// if (button.GetComponent<AnswerButton>
//().answerData.isCorrect)
// {
// button.GetComponent<AnswerButton>
// ().StartCoroutine(ReturnCorrectButtonColor());
// }
// }
//}
}
if (qNumber < questionPool.Length - 1) /
{
qNumber++;
StartCoroutine(TransitionToNextQuestion());
}
else
{
StartCoroutine(WaitForFewSeconds());
}
}
public void EndRound()
{
isRoundActive = false;
questionPanel.SetActive(false);
roundOverPanel.SetActive(true);
}
//on button click return to main menu
public void ReturnToMenu ()
{
SceneManager.LoadScene("MenuScreen");
}
}
In order to highlight both Wrong (the clicked one) and the Right buttons you need to have access to both buttons. This means that you can't do highlighting from HandleClick method of your Answer Button Script, as it only has access to itself, e.g. to the Wrong button.
The good thing is that this method notifies GameController that the button has been clicked. GameController knows about all the buttons, so it can easily highlight both buttons.
So, instead of launching your highlight subroutines from Answer Button's HandleClick, you should do this from GameController's AnswerButtonClicked: identify both the Right button and the clicked button there and launch appropriate subroutines for them.
Update:
For instance, your ReturnCorrectButtonColor would look like:
IEnumerator ReturnCorrectButtonColor( GameObject button )
{
Debug.Log("im correct");
button.GetComponent<Button>().image.color = Color.green;
yield return new WaitForSeconds(seconds: 2.9f);
button.GetComponent<Button>().image.color = Color.white;
}
so in AnswerButtonClicked you identify which button to highlight as a correct answer button and pass it as a paramter to this method:
StartCoroutine(ReturnCorrectButtonColor(correctButton));
Related
I had a script that controlled my main menu that was on a GameObject and moved it to another gameobject and reconnected all the loose ends. now for some reason none of my buttons work, even with highlighting.
just had two gameobjects and moved the script between them using the editor
the script itself doesnt do much, just this:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class MainMenu : MonoBehaviour
{
public GameObject mainMenu;
public GameObject optionsMenu;
public GameObject modeMenu;
public Dropdown resolutionDropdown;
private Resolution[] resolutions;
public Toggle fullscreenToggle;
public void StartGameLocal()
{
SceneManager.LoadScene("Local2P");
}
public void StartGameAI()
{
SceneManager.LoadScene("AI2P");
}
public void MenuToOptions()
{
mainMenu.SetActive(false);
optionsMenu.SetActive(true);
}
public void OptionsToMenu()
{
mainMenu.SetActive(true);
optionsMenu.SetActive(false);
}
public void MenuToMode()
{
mainMenu.SetActive(false);
modeMenu.SetActive(true);
}
public void ModeToMenu()
{
mainMenu.SetActive(true);
modeMenu.SetActive(false);
}
public void ExitGame()
{
Application.Quit();
}
void Start()
{
resolutions = Screen.resolutions;
resolutionDropdown.ClearOptions();
List<string> options = new List<string>();
int currentResolutionIndex = 0;
for (int i = 0; i < resolutions.Length; i++)
{
string option = resolutions[i].width + " x " + resolutions[i].height;
options.Add(option);
if (resolutions[i].width == Screen.width && resolutions[i].height == Screen.height)
currentResolutionIndex = i;
}
resolutionDropdown.AddOptions(options);
resolutionDropdown.value = currentResolutionIndex;
resolutionDropdown.RefreshShownValue();
if (Screen.fullScreen == true)
{
fullscreenToggle.isOn = true;
}
}
public void SetResolution(int resolutionIndex)
{
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width,
resolution.height, Screen.fullScreen);
PlayerPrefs.SetInt("ResolutionPreference", resolutionDropdown.value);
}
public void SetFullscreen(bool isFullscreen)
{
Screen.fullScreen = isFullscreen;
if (isFullscreen)
{
PlayerPrefs.SetInt("FullscreenPreference", 1);
}
else
{
PlayerPrefs.SetInt("FullscreenPreference", 0);
}
}
void Update()
{
if (Input.GetKey(KeyCode.Escape))
{
if (optionsMenu.activeSelf)
{
OptionsToMenu();
}
else if (optionsMenu.activeSelf)
{
ModeToMenu();
}
else
{
Application.Quit();
}
}
}
}
i dont know how to fix this and why my buttons just stopped working, even after reconnecting everything, but please help!
p.s. havent checked the update code to see if it worked, if yall have suggestions let me know
Your buttons likely pointed to the functions in this script in their OnClick handlers. If you moved the location of the script, you need to go to each of the buttons and hook those handlers back up.
quick introduction to my project. I am trying to make a game in unity game engine and I am working on its shop system. Everything about the shop system is complete but one problem is still there. I need to save the State of button that is (MyButton) in my game scene and change it with (BuyButton) or (EquipButton) the saving part works but setting the button doesn't, I am using enum and switch statements for that part. These are the scripts of those two things.
script with the enum:
using UnityEngine;
using System.IO;
public class SaveEverything : MonoBehaviour
{
// What script to save
public LoadEveryThing MyButton;
public void Save()
{
// What data to save
string saveData = MyButton.state.ToString();
// Where the data is stored
string path = Application.persistentDataPath + "\\buttonstate.save";
// Writes data to file
if (File.Exists(path))
{
File.WriteAllText(path, saveData/*, saveData1, saveData2, saveData3, 5*/);
}
else
{
File.Create(path).Close();
File.WriteAllText(path, saveData/*, saveData1, saveData2, saveData3, 5*/);
}
}
}
public enum ButtonState
{
Buy,
Equip
}
At the last part of script the enum is declared, with Buy and Equip inside it and rest of the script is about saving MyButton in a string.
Script with the switch statement:
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System;
using TMPro;
public class LoadEveryThing : MonoBehaviour
{
// Types of buttons
public GameObject BuyButton;
/* public GameObject BuyButton1;
public GameObject BuyButton2;
public GameObject BuyButton3;*/
public GameObject EquipButton;
/*public GameObject EquipButton1;
public GameObject EquipButton2;
public GameObject EquipButton3;*/
public ButtonState state;
void Start()
{
// What file to read save data from
string path = Application.persistentDataPath + "\\buttonstate.save";
// Get data and set state to that data
if (File.Exists(path))
{
string data = File.ReadAllText(path);
if (Enum.TryParse(data, out ButtonState State))
state = State;
}
// Copy button properties onto this button
// depending on the state
switch (state)
{
case ButtonState.Buy:
SetButton(BuyButton);
break;
case ButtonState.Equip:
SetButton(EquipButton);
break;
}
if(shop.isSold == true)
{
state = ButtonState.Equip;
Debug.Log("working");
}
else if(shop.isSold == false)
{
state = ButtonState.Buy;
Debug.Log(" buy working");
}
}
void Update()
{
}
void SetButton(GameObject button)
{
// Set on-click method of button
Button myButton = GetComponent<Button>();
Button targetButton = button.GetComponent<Button>();
myButton.onClick = targetButton.onClick;
// Set text of button
TMPro.TextMeshProUGUI myText = GetComponentInChildren<TMPro.TextMeshProUGUI>();
TMPro.TextMeshProUGUI targetText = button.GetComponentInChildren<TMPro.TextMeshProUGUI>();
myText.text = targetText.text;
}
/*public static void SetEquipButton()
{
}
public static void SetBuyButton()
{
}*/
}
In the script the switch statement works like this if the enum ButtonState is ButtonState.Buy then it actives buy button else it active and sets Equip button. But the problem is I don't know how to change the ButtonScript State through script. So the switch statement doesn't have anything to change and save BuyButton to EquipButton. I had already tried this /*I made this variable of type ButtonState*/ public ButtonState state and then I did this to change the enum State state = ButtonState.Equip; but it is not changing the State of the enum. I can see that in the inspector and there are not errors as well. So what should I do?
This is the script where I am calling to change the enum state:
the script is too long so this is the method where I am calling it and I also as told I already made a variable of type public ButtonState state;
public class shop : MonoBehaviour
{
public TMPro.TextMeshProUGUI scoreText;
public GameObject Item1;
public GameObject Item2;
public GameObject Item3;
public GameObject Item4;
public TMPro.TextMeshProUGUI notenough;
public TMPro.TextMeshProUGUI notenough1;
public TMPro.TextMeshProUGUI notenough2;
public TMPro.TextMeshProUGUI notenough3;
public GameObject buyButton;
public GameObject buyButton1;
public GameObject buyButton2;
public GameObject buyButton3;
public GameObject equipButton;
public GameObject equipButton1;
public GameObject equipButton2;
public GameObject equipButton3;
public float sec = 14f;
public static bool isSold = false;
public static bool isSold1 = false;
public static bool isSold2 = false;
public static bool isSold3 = false;
public ButtonState state;
public ButtonState1 state1;
public ButtonState2 state2;
public ButtonState3 state3;
private Dictionary<GameObject, float> ItemPrices;
void Start ()
{
scoreText.text = "Score : " + ((int)PlayerPrefs.GetFloat ("Highscore")).ToString();
ItemPrices = new Dictionary<GameObject, float>()
{
{ Item1, 50f },
{ Item2, 80f },
{Item3, 3500f},
{ Item4, 5000f },
};
notenough.enabled = false;
notenough1.enabled = false;
notenough2.enabled = false;
notenough3.enabled = false;
}
public void PurchaseItem(GameObject Item)
{
foreach(KeyValuePair<GameObject, float> item in ItemPrices)
{
if (item.Key == Item)
{
float price = item.Value;
float val = PlayerPrefs.GetFloat ("Highscore");
if(val >= price)
{
val -= item.Value;
PlayerPrefs.SetFloat("Highscore", val);
scoreText.text = "Score : " + ((int)PlayerPrefs.GetFloat ("Highscore")).ToString();
buyButton.SetActive(false);
equipButton.SetActive(true);
isSold = true;
state = ButtonState.Equip;
// Take away the cost of the item from the player's currency
//PlayerPrefs.GetFloat ("Highscore") -= item.Value;
}
else
{
Debug.Log("not enough money");
notenough.enabled = true;
notenough1.enabled = true;
notenough2.enabled = true;
notenough3.enabled = true;
Invoke("noen", 2);
state = ButtonState.Buy;
}
}
}
}
public void noen()
{
notenough.enabled = false;
notenough1.enabled = false;
notenough2.enabled = false;
notenough3.enabled = false;
}
}
If any thing is unclear let me know.
Thanks,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemAction : MonoBehaviour
{
public camMouseLook mouselook;
public GameObject lockedRoomCamera;
public Camera playerCamera;
public GameObject navi;
public ConversationTrigger trigger;
public GameObject player;
private Vector3 playerposition;
private Quaternion playerrotation;
private bool torotate = false;
public void Init()
{
navi.transform.parent = null;
navi.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
navi.transform.LookAt(lockedRoomCamera.transform);
PlayerController.disablePlayerController = true;
mouselook.enabled = false;
playerCamera.enabled = false;
lockedRoomCamera.SetActive(true);
torotate = true;
playerposition = player.transform.position;
playerrotation = player.transform.rotation;
}
private void Update()
{
if(torotate == true)
{
RotateRandom.RandomRotation(navi.transform);
PlayConversations.ConversationToPlay(3);
}
}
}
The problem is that it's calling this line many times :
PlayConversations.ConversationToPlay(3);
I don't mind it will be called many times but I want it to play for exmaple index 3 only once. If it started playing the index remember it started playing and played the index in this case 3 and don't play it again even if it will call this line in the Update over again.
This is the PlayConversations script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayConversations : MonoBehaviour
{
private static ConversationTrigger conversationTrigger;
private static PlayConversations instance;
private void Awake()
{
conversationTrigger = GetComponent<ConversationTrigger>();
instance = this;
}
public static void ConversationToPlay(int index)
{
ConversationTrigger.conversationsToPlay.Add(index);
instance.StartCoroutine(conversationTrigger.PlayConversations());
}
}
And the ConversationTrigger script :
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEditorInternal;
public class ConversationTrigger : MonoBehaviour
{
public List<Conversation> conversations = new List<Conversation>();
public static List<int> conversationsToPlay = new List<int>();
[HideInInspector]
public GameObject canvas;
[HideInInspector]
public bool conversationEnd;
[HideInInspector]
public static int conversationIndex;
private DialogueManager dialoguemanager;
private void Start()
{
conversationIndex = 0;
dialoguemanager = FindObjectOfType<DialogueManager>();
}
public IEnumerator PlayConversations()
{
conversationEnd = false;
var conversations = conversationsToPlay.ToArray(); // Copy the list
conversationsToPlay.Clear(); // Immediately clear the original list
for (int i = 0; i < conversations.Length; i++) // iterate over the array
{
// Now you also don't need to remove items anymore,
// since you already cleared the list
yield return StartCoroutine(PlayConversation(conversations[i]));
}
}
public IEnumerator PlayConversation(int index)
{
if (conversations.Count > 0 &&
conversations[index].Dialogues.Count > 0)
{
for (int i = 0; i < conversations[index].Dialogues.Count; i++)
{
if (dialoguemanager != null)
{
dialoguemanager.StartDialogue(conversations[index].Dialogues[i]);
}
while (DialogueManager.dialogueEnded == false)
{
yield return null;
}
}
conversationIndex = index;
conversationEnd = true;
canvas.SetActive(false);
Debug.Log("Conversation Ended");
}
}
public void SaveConversations()
{
string jsonTransform = JsonHelper.ToJson(conversations.ToArray(), true);
File.WriteAllText(#"d:\json.txt", jsonTransform);
}
public void LoadConversations()
{
string jsonTransform = File.ReadAllText(#"d:\json.txt");
conversations.Clear();
conversations.AddRange(JsonHelper.FromJson<Conversation>(jsonTransform));
}
}
Either to make inside the PlayConversations script or inside the ConversationTrigger that when it started playing a conversation don't play this conversation over again.
The problem is that each place in the game I'm playing a conversation like in this case I need to use flags to make it stop after start playing but inthis case for example while the conversation is playing I'm also rotating an object and that should be in the Update and be called many times :
RotateRandom.RandomRotation(navi.transform);
But the conversation should start only once.
Since I don't see a reason why to play the same conversation twice in the game then I want it to be playing only once without the need to use flags each place.
Inside the manager script I have a method that start a dialogue name : StartDialogue:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogueManager : MonoBehaviour
{
public Text dialogueText;
public Text nameText;
public float sentencesSwitchDuration;
public bool animateSentenceChars = false;
public GameObject canvas;
public static bool dialogueEnded = false;
public DialogueTrigger trigger;
private Queue<string> sentence;
// Use this for initialization
void Start()
{
sentence = new Queue<string>();
}
public void StartDialogue(Dialogue dialogue)
{
canvas.SetActive(true);
nameText.text = dialogue.name;
sentence.Clear();
foreach (string sentence in dialogue.sentences)
{
this.sentence.Enqueue(sentence);
}
DisplayNextSentence();
}
public void DisplayNextSentence()
{
if (this.sentence.Count == 0)
{
EndDialogue();
return;
}
string sentence = this.sentence.Dequeue();
dialogueText.text = sentence;
StopAllCoroutines();
StartCoroutine(DisplayNextSentenceWithDelay(sentence));
}
public IEnumerator DisplayNextSentenceWithDelay(string sentence)
{
if (animateSentenceChars)
{
dialogueText.text = "";
foreach (char letter in sentence.ToCharArray())
{
dialogueText.text += letter;
yield return null;
}
}
yield return new WaitForSeconds(sentencesSwitchDuration);
DisplayNextSentence();
}
private void EndDialogue()
{
dialogueEnded = true;
if (trigger.dialogueNum == trigger.conversations[trigger.dialogueIndex].Dialogues.Count)
canvas.SetActive(false);
Debug.Log("End of conversation.");
}
}
Then in the trigger script I have a method name TriggerDialogue that get index number. For example index 0 it will start the dialoue/s of the first conversation. But in fact it's just starting the first dialogue from the dialogues List.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
[ExecuteInEditMode]
public class DialogueTrigger : MonoBehaviour
{
public List<Conversation> conversations = new List<Conversation>();
//public List<Dialogue> dialogue = new List<Dialogue>();
[HideInInspector]
public int dialogueNum = 0;
[HideInInspector]
public int dialogueIndex = 0;
private bool triggered = false;
private List<Dialogue> oldDialogue;
private bool activateButton = false;
public void TriggerDialogue(int dialogueIndex)
{
this.dialogueIndex = dialogueIndex;
if (conversations.Count > 0 &&
conversations[dialogueIndex].Dialogues.Count > 0)
{
if (triggered == false)
{
if (FindObjectOfType<DialogueManager>() != null)
{
FindObjectOfType<DialogueManager>().StartDialogue(conversations[dialogueIndex].Dialogues[dialogueNum]);
dialogueNum += 1;
}
triggered = true;
}
}
}
private void Update()
{
ButtonActivation();
if (DialogueManager.dialogueEnded == true)
{
if (dialogueNum == conversations[dialogueIndex].Dialogues.Count)
{
return;
}
else
{
FindObjectOfType<DialogueManager>().StartDialogue(conversations[dialogueIndex].Dialogues[dialogueNum]);
DialogueManager.dialogueEnded = false;
dialogueNum += 1;
}
}
}
public bool ActivateButton()
{
return activateButton;
}
private void ButtonActivation()
{
if (ConversationsChecks() == true)
{
foreach (string sentence in conversations[dialogueIndex].Dialogues[dialogueNum].sentences)
{
if (sentence != "")
{
activateButton = true;
}
else
{
activateButton = false;
}
}
}
else
{
activateButton = false;
}
}
public void SaveConversations()
{
string jsonTransform = JsonHelper.ToJson(conversations.ToArray(), true);
File.WriteAllText(#"d:\json.txt", jsonTransform);
}
public void LoadConversations()
{
string jsonTransform = File.ReadAllText(#"d:\json.txt");
conversations.Clear();
conversations.AddRange(JsonHelper.FromJson<Conversation>(jsonTransform));
}
private bool ConversationsChecks()
{
bool IsConversationsReady = false;
if (conversations.Count > 0 &&
conversations[dialogueIndex].Dialogues.Count > 0 &&
conversations[dialogueIndex].Dialogues[dialogueNum].sentences.Count > 0 &&
conversations[dialogueIndex].Dialogues[dialogueNum].name != "" &&
conversations[dialogueIndex].name != "")
{
IsConversationsReady = true;
}
else
{
IsConversationsReady = false;
}
return IsConversationsReady;
}
}
Then I have more two small classes :
Dialogue:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Dialogue
{
[Tooltip("Dialogue Name")]
public string name;
[TextArea(1, 10)]
public List<string> sentences = new List<string>();
}
And Conversation :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Conversation
{
[Tooltip("Conversation Name")]
public string name;
public List<Dialogue> Dialogues = new List<Dialogue>();
}
So now when I want to start a dialogue I'm calling the TriggerDialogue method like this example :
dialogueTrigger.TriggerDialogue(0);
Instead I want to do something like that :
dialogueTrigger.StartConversation("Opening Scene");
Or
dialogueTrigger.StartConversation("The last conversation");
And this is example screenshot of how the Inspector of the conversations and dialogues looks like :
Conversations
So if for example I want to start the first conversation somewhere in my game I will do :
dialogueTrigger.StartConversation("The Opening");
And it will start the dialogue/s inside the "The Opening" conversation.
Using the index is working fine but I want to use to start a conversation by the conversation name it will be easier.
Given that you are using a List<T>, if you move away from using the index to get the item you want, you will need to enumerate the collection each time to find that same item. The best you can do here, is change the data structure to a Dictionary, so you can search for it by the Key and avoid the performance hit. In order to also avoid having to remember what names you put to the conversations, perhaps it would be best to use an Enum.
So, create the enum:
public enum SceneConversations
{
OpeningScene = 1,
// ...
}
and start using
public class DialogueTrigger : MonoBehaviour
{
public Dictionary<SceneConversations, Conversation> conversations = new Dictionary<SceneConversations, Conversation>();
you can then use
public void StartConversation(SceneConversations conversationWanted) {}
and call it with
dialogueTrigger.StartConversation(SceneConversations.OpeningScene);
If I remember correctly, this has the added advantage that Unity will show you a drop-down for the possible values of SceneConversations, so that's also easier to handle.
I have three characters and each of them has a camera attached to them.By default they are disabled but one.I made a character selector which is supposed to change them.I have a problem where I can move the selected one but the camera stays at the last one.
Here is the script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityStandardAssets.Utility;
public class GameManageer : MonoBehaviour {
public Camera[] cams = new Camera[3];
public Character CurrentCharacter;
public List<Character> Characters = new List<Character>();
public List<Item> AllItems;
bool ShowCharWheel;
public int SelectedCharacter;
public int lastCharacter;
public static GameManageer Instance;
void Awake(){
Instance = this;
foreach (Character c in Characters){
c.Instance = Instantiate(c.PlayerPrefab, c.HomeSpawn.position, c.HomeSpawn.rotation) as GameObject;
c.Instance.GetComponent<PlayerController>().LocalCharacter = c;
}
ChangeCharacter(Characters[PlayerPrefs.GetInt("SelectedChar")]);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKey (KeyCode.C)) {
ShowCharWheel = true;
} else {
ShowCharWheel = false;
}
}
void ChangeCharacter(Character c){
lastCharacter = SelectedCharacter;
SelectedCharacter = Characters.IndexOf (c);
cams [SelectedCharacter].gameObject.SetActive (true);
cams [lastCharacter].gameObject.SetActive (false);
CurrentCharacter = c;
Characters [lastCharacter].Instance.GetComponent<PlayerController> ().CanPlay = false;
Characters [SelectedCharacter].Instance.GetComponent<PlayerController> ().CanPlay = true;
PlayerPrefs.SetInt ("SelectedChar", SelectedCharacter);
}
void OnGUI(){
if (ShowCharWheel) {
GUILayout.BeginArea(new Rect(Screen.width - 64, Screen.height - 192,64,192));
foreach (Character c in Characters){
if (GUILayout.Button(c.Icon,GUILayout.Width(64),GUILayout.Height(64))){
ChangeCharacter(c);
}
}
GUILayout.EndArea();
}
}
}
[System.Serializable]
public class Character {
public string Name;
public Texture2D Icon;
public GameObject PlayerPrefab;
public GameObject Instance;
public Transform HomeSpawn;
}
[System.Serializable]
public class Item{
public string Name;
public Texture2D Icon;
public ItemInstance InstancePrefab;
}
This should do the job:
cams[SelectedCharacter].enabled = true;
cams[lastCharacter].enabled = false;
Use Depth:
foreach (Camera cam in cams)
{
cam.depth = cam == cams[SelectedCharacter] ? 10 : 0;
}
I think the real problem here though, is that you have more cameras in the scene which you have to manage as well, other then only the last and current selected character... in which case:
foreach (Camera cam in cams)
{
cam.SetActive(cam == cams[SelectedCharacter]);
}