I am trying to have a game, in which everyone can buy cars (and I save that data to playerprefs). So I have 9 trails for the cars in my game and I am trying to write some code so that when you press a button the car & the trail for that car will show up.
When the button next to it is clicked, it saves that data so when people restart the game, they will still have the car & trail open and won't need to press the button again.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Button[] TrailLevel;
public GameObject[] Cars, Trails;
public Text text;
public int CurrentCarToSpawn = 0;
private void Start()
{ }
private void FixedUpdate()
{
UpdateCar();
}
public void InstantiateCar()
{
TrailLevel[CurrentCarToSpawn].gameObject.active = false;
MineLevel[CurrentCarToSpawn+1].interactable = true;
PlayerPrefs.SetInt("TrailCountA", PlayerPrefs.GetInt("TrailCountA") + 1);
PlayerPrefs.Save();
CurrentCarToSpawn++;
UpdateCar();
}
void UpdateCar()
{
int TrailCountA= PlayerPrefs.GetInt("TrailCountA", 1);
for (int i = 0; i < TrailLevel.Length; i++)
{
if (i + 1 > TrailCountA)
{
TrailLevel.interactable = false;
}
if (TrailLevel.interactable)
{
Trains[CurrentCarToSpawn].gameObject.active = true;
Mines[CurrentCarToSpawn].gameObject.active = true;
}
}
text.text = PlayerPrefs.GetInt("TrailCountA").ToString();
}
}
From what I can see with your code, this is how I would approach it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Button[] TrailLevel;
public GameObject[] Cars, Trails;
public Text text;
public int CurrentCarToSpawn = 0;
private void Start()
{
// Load the current car. ADDED
CurrentCarToSpawn = PlayerPrefs.getInt("savedSelection", 0);
// Since we are loading the last selection, we need to call our
// instantiation method so it can activate the appropriate
// GameObjects.
InstantiateCar();
}
private void FixedUpdate()
{
UpdateCar();
}
public void InstantiateCar()
{
TrailLevel[CurrentCarToSpawn].gameObject.active = false;
MineLevel[CurrentCarToSpawn+1].interactable = true;
PlayerPrefs.SetInt("TrailCountA", PlayerPrefs.GetInt("TrailCountA") + 1);
// Save that this is our current selection.
PlayerPrefs.SetInt("savedSelection", CurrentCarToSpawn);
PlayerPrefs.Save();
CurrentCarToSpawn++;
UpdateCar();
}
void UpdateCar()
{
int TrailCountA= PlayerPrefs.GetInt("TrailCountA", 1);
for (int i = 0; i < TrailLevel.Length; i++)
{
if (i + 1 > TrailCountA)
{
TrailLevel.interactable = false;
}
if (TrailLevel.interactable)
{
Trains[CurrentCarToSpawn].gameObject.active = true;
Mines[CurrentCarToSpawn].gameObject.active = true;
}
}
text.text = PlayerPrefs.GetInt("TrailCountA").ToString();
}
}
Related
I need help with creating a code for a typewriter effect that only displays one character per click(ui button), I'm really new to Unity and coding as a whole, and I used a tutorial to use the typewriter effect, then i tried to make it so it only works as one character per click on the button, but it didn't work.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class TypeWriterEffect : MonoBehaviour {
public float delay = 0.1f;
public string fullText;
private string currentText = "";
public Button toggleButton;
bool toggle = false;
void Start () {
toggleButton.onClick.AddListener(Toggle);
}
void Toggle()
{
StartCoroutine(ShowText());
toggle = true;
}
IEnumerator ShowText(){
if (toggle == true)
{
for (int i = 0; i < fullText.Length; i++)
{
this.GetComponent<Text>().text = currentText;
currentText = fullText.Substring(0, i);
yield return new WaitForSeconds(delay);
}
toggle = false;
}
}
}
If you really want it to only display one character per click on a UI button, you can cut it down to something like this:
using UnityEngine;
using UnityEngine.UI;
public class TypeWriterEffect : MonoBehaviour
{
public string fullText;
public Button toggleButton;
public int carriage=0;
void Start () {
toggleButton.onClick.AddListener(Clicked);
GetComponent<Text>().text = fullText.Substring(0, carriage);
}
void Clicked()
{
carriage++;
GetComponent<Text>().text = fullText.Substring(0, carriage);
}
}
I have a button for showing rewarded advertisement. If the advertisement is loaded, I want to enable this button, also if the advertisement is not loaded, I want to disabled this button. But, the code is not working, When i have no internet connection, the button is always enabled. How can i do this issue?
Here is my code :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RewardedShop : MonoBehaviour
{
public static RewardedShop Instance { get; set; }
private void Awake()
{
Instance = this;
}
public string appkey;
public GameObject afterRewardedScreen, mainScreen;
public Button btnWatchSHOP;
public GameObject btnActive;
RewardedGameObject[] go;
// Start is called before the first frame update
void Start()
{
IronSource.Agent.shouldTrackNetworkState(true);
IronSourceEvents.onRewardedVideoAvailabilityChangedEvent += RewardedVideoAvaibilityChangedEvent;
IronSourceEvents.onRewardedVideoAdClosedEvent += RewardedVideoAdClosedEvent;
IronSourceEvents.onRewardedVideoAdRewardedEvent += RewardedVideoAdRewardedEvent;
//IronSourceEvents.onRewardedVideoAdReadyEvent += OnRewardedVideoAdReady;
btnWatchSHOP.interactable = false;
}
public void showRewarded()
{
if (IronSource.Agent.isRewardedVideoAvailable())
{
counter = 0;
IronSource.Agent.showRewardedVideo("ShopRewarded");
}
}
void RewardedVideoAdClosedEvent()
{
IronSource.Agent.init(appkey, IronSourceAdUnits.REWARDED_VIDEO);
IronSource.Agent.shouldTrackNetworkState(true);
}
void RewardedVideoAvaibilityChangedEvent(bool available)
{
bool rewardedVideoAvailability = available;
BtnActive();
}
int counter = 0;
void RewardedVideoAdRewardedEvent(IronSourcePlacement ssp)
{
if (counter < 1)
{
RewardHandlerSHOP.Instance.Reward();
counter++;
}
}
public void Reward()
{
PlayerPrefs.SetInt("totalCoin", PlayerPrefs.GetInt("totalCoin") + 150);
GameObject.Find("TxtTotalSHOPCoin").GetComponent<Text>().text = PlayerPrefs.GetInt("totalCoin").ToString();
SoundManager.Instance.PlayEarnGoldSound();
}
public void BtnActive()
{
bool available = IronSource.Agent.isRewardedVideoAvailable();
if (available)
{
btnWatchSHOP.interactable = true;
}
else
{
btnWatchSHOP.interactable = false;
}
}
}
So basically I have a Score/Highscore system and I also have an array which contains some of the buttons which change the color of the player's character. So my question is that if I have highscoreCount >= 20, I want a certain button to become interactable.
ScoreManager Script
using UnityEngine;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour
{
public Transform player;
public Text scoreText;
public Text highScoreText;
public float scoreCount;
public float highscoreCount;
public float pointsPerSecond;
public bool scoreIncreasing;
public Button[] CustomizeButtons;
void Start()
{
if (PlayerPrefs.HasKey("Highscore"))
{
highscoreCount = PlayerPrefs.GetFloat("Highscore");
}
int CustomizationButtonReached = PlayerPrefs.GetInt("CustomizationButtonReached", 1);
{
for (int i = 0; i < CustomizeButtons.Length; i++)
{
if (i + 1 > CustomizationButtonReached)
CustomizeButtons[i].interactable = false;
}
}
}
void Update()
{
if (scoreIncreasing)
{
scoreCount += pointsPerSecond * Time.deltaTime;
}
if(scoreCount > highscoreCount)
{
highscoreCount = scoreCount;
PlayerPrefs.SetFloat("Highscore", highscoreCount);
}
scoreText.text = "Score: " + Mathf.Round(scoreCount);
highScoreText.text = "Highscore: " + Mathf.Round(highscoreCount);
}
}
CustomizeColors Script
using UnityEngine;
public class CustomizeColors : MonoBehaviour
{
public Color[] Colors;
public Material Mat;
public void Start()
{
if (PlayerPrefs.HasKey("HeadColor"))
{
Mat.color = Colors[PlayerPrefs.GetInt("HeadColor")];
}
}
public void ChangeColor(int colorIndex)
{
Mat.color = Colors[colorIndex];
PlayerPrefs.SetInt("HeadColor", colorIndex);
PlayerPrefs.Save();
}
}
Essentially this is the code that I have made (in the ScoreManager) to make an array and to disable all of the buttons. I just want to get a specific element to be interactable when highscoreCount >= "number"
public Button[] CustomizeButtons;
void Start()
{
int CustomizationButtonReached = PlayerPrefs.GetInt("CustomizationButtonReached", 1);
{
for (int i = 0; i < CustomizeButtons.Length; i++)
{
if (i + 1 > CustomizationButtonReached)
CustomizeButtons[i].interactable = false;
}
}
}
You could go multiple ways about this, for example storing a reference for that specific button and when the condition you mentioned is true just set that one button to be interactable
[SerializeField] Button button; //Set this in the inspector
public void AddToScore(int score)
{
//Do your score adding stuff
if (highscoreCount >= number)
{
button.interactable = true
}
}
At the dialogue trigger script top I added a new List type string:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour
{
public List<string> conversation = new List<string>();
public List<Dialogue> dialogue = new List<Dialogue>();
[HideInInspector]
public int dialogueNum = 0;
private bool triggered = false;
private List<Dialogue> oldDialogue;
private void Start()
{
//oldDialogue = dialogue.ToList();
}
public void TriggerDialogue()
{
if (triggered == false)
{
if (FindObjectOfType<DialogueManager>() != null)
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
dialogueNum += 1;
}
triggered = true;
}
}
private void Update()
{
if (DialogueManager.dialogueEnded == true)
{
if (dialogueNum == dialogue.Count)
{
return;
}
else
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
DialogueManager.dialogueEnded = false;
dialogueNum += 1;
}
}
}
}
Then in the editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
// do this only once here
_dialogues = serializedObject.FindProperty("dialogue");
_conversations = serializedObject.FindProperty("conversation");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversation Size", _conversations.arraySize);
// Ofcourse you also want to change the list size here
_dialogues.arraySize = EditorGUILayout.IntField("Dialogue Size", _dialogues.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
for (int i = 0; i < _dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
}
}
// Note: You also forgot to add this
serializedObject.ApplyModifiedProperties();
}
}
I'm doing a loop of the _conversations on the loop of the _dialogues.
But this is not what I wanted.
I want that in the Inspector on the top level there will be only "Conversations Size".
If the Conversations Size is 0 there is nothing.
But if the Conversations Size for example is 5.
Then it will create 5 Conversations(Conversation 1, Conversation 2....Conversation5). And under each Conversation there will be a Dialouge Size and then I can make many dialogues per conversation.
That way it will be easier to identify later the conversations and dialogues.
Instead as before that there was one long dialogues.
I added the conversation List before that it was just without the conversation/s and working fine but now I want to add the conversations. So each conversation will have it's own dialogues.
This is the scripts according to the solution:
Created the class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Conversation
{
public string Id;
public List<Dialogue> Dialogues = new List<Dialogue>();
}
Then the trigger script:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour
{
public List<Conversation> conversations = new List<Conversation>();
public List<Dialogue> dialogue = new List<Dialogue>();
[HideInInspector]
public int dialogueNum = 0;
private bool triggered = false;
private List<Dialogue> oldDialogue;
private void Start()
{
//oldDialogue = dialogue.ToList();
}
public void TriggerDialogue()
{
if (triggered == false)
{
if (FindObjectOfType<DialogueManager>() != null)
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
dialogueNum += 1;
}
triggered = true;
}
}
private void Update()
{
if (DialogueManager.dialogueEnded == true)
{
if (dialogueNum == dialogue.Count)
{
return;
}
else
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
DialogueManager.dialogueEnded = false;
dialogueNum += 1;
}
}
}
}
And last the trigger editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
_conversations = serializedObject.FindProperty("conversations");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversations Size", _conversations.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
var conversation = _conversations.GetArrayElementAtIndex(x);
var Id = conversation.FindPropertyRelative("Id");
EditorGUILayout.PropertyField(Id);
_dialogues = conversation.FindPropertyRelative("Dialogues");
_dialogues.arraySize = EditorGUILayout.IntField("Dialogues size", _dialogues.arraySize);
for (int i = 0; i < _dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
}
}
serializedObject.ApplyModifiedProperties();
}
}
And a screenshot result:
I think that all the Id's in the Inspector should be children of the Conversations Size and all the Dialogues Size should be child of the Id and then the Dialogues should be childs of the Dialogues Size.
Conversation Size
Id 1
Dialogues Size
Dialogue 1
Name
Sentences
Dialogue 2
Something like that.
You should instead have a proper class
[Serializable]
public class Conversation
{
public string Id;
public List<Dialogue> Dialogues = new List<Dialogue>();
}
and than instead have a list of that in
public DialogueTrigget : MonoBehaviour
{
public List<Conversation> Conversations = new List<Conversation> ();
...
}
Than you can use exactly the same script I gave you last time but with
_conversations = serializedObject.FindProperty("Conversations");
and accordingly one for loop more similar to what you tried already .. something like
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
_conversations = serializedObject.FindProperty("conversation");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversation Size", _conversations.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
var conversation = _conversations.GetArrayElementAtIndex(x);
var id = conversation.FindPropertyRelative("I'd");
EditorGUI.indentLevel ++;
EditorGUILayout.PropertyField(Id);
var dialogues = conversation.FindPropertyRelative("Dialogues");
dialogues.arraySize = EditorGUILayout.IntField("Dialogues size", dialogues.arraySize);
for (int i = 0; i < dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
}
}
or alternatively simply
EditorGUILayout.PropertyField(_conversations, new GUIContent ("Conversations"), true);
but this would not print "Dialogue 1, Dialogue 2" etc
Again I strongly recommend you have a look at the nested ReorderableList you will see it is awesome once you got it working.
Typed on my smartphone so no warranty
I am making a quiz game in the unity from the unity live session quiz game tutorials everything is working fine except somehow the score isn't working when i Click the button it should add 10 score to the Score. Here are the tutorials : https://unity3d.com/learn/tutorials/topics/scripting/intro-and-setup?playlist=17117 and the code for my Game Controller :
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
public class GameController : MonoBehaviour {
public Text questionDisplayText;
public Text scoreDisplayText;
public Text timeRemainingDisplayText;
public SimpleObjectPool answerButtonObjectPool;
public Transform answerButtonParent;
public GameObject questionDisplay;
public GameObject roundEndDisplay;
private DataController dataController;
private RoundData currentRoundData;
private QuestionData[] questionPool;
private bool isRoundActive;
private float timeRemaining;
private int questionIndex;
private int playerScore;
private List<GameObject> answerButtonGameObjects = new List<GameObject>();
// Use this for initialization
void Start ()
{
dataController = FindObjectOfType<DataController> ();
currentRoundData = dataController.GetCurrentRoundData ();
questionPool = currentRoundData.questions;
timeRemaining = currentRoundData.timeLimitInSeconds;
UpdateTimeRemainingDisplay();
playerScore = 0;
questionIndex = 0;
ShowQuestion ();
isRoundActive = true;
}
private void ShowQuestion()
{
RemoveAnswerButtons ();
QuestionData questionData = questionPool [questionIndex];
questionDisplayText.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);
}
}
public void AnswerButtonClicked(bool isCorrect)
{
if (isCorrect)
{
playerScore += currentRoundData.pointsAddedForCorrectAnswer;
scoreDisplayText.text = "Score: " + playerScore.ToString();
}
if (questionPool.Length > questionIndex + 1) {
questionIndex++;
ShowQuestion ();
} else
{
EndRound();
}
}
public void EndRound()
{
isRoundActive = false;
questionDisplay.SetActive (false);
roundEndDisplay.SetActive (true);
}
public void ReturnToMenu()
{
SceneManager.LoadScene ("MenuScreen");
}
private void UpdateTimeRemainingDisplay()
{
timeRemainingDisplayText.text = "Time: " + Mathf.Round (timeRemaining).ToString ();
}
// Update is called once per frame
void Update ()
{
if (isRoundActive)
{
timeRemaining -= Time.deltaTime;
UpdateTimeRemainingDisplay();
if (timeRemaining <= 0f)
{
EndRound();
}
}
}
}
and my answer Button Code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class AnswerButton : MonoBehaviour {
public Text answerText;
private AnswerData answerData;
private GameController GameController;
// Use this for initialization
void Start ()
{
GameController = FindObjectOfType<GameController> ();
}
public void Setup(AnswerData data)
{
answerData = data;
answerText.text = answerData.answerText;
}
public void HandleClick()
{
GameController.AnswerButtonClicked (answerData.isCorrect);
}
}
and Answer Data :
using UnityEngine;
using System.Collections;
[System.Serializable]
public class AnswerData
{
public string answerText;
public bool isCorrect;
}
If everything is working fine (the whole code gets executed correctly, which I presume at this point), you probably did not set the data correctly. In your Game Controller, you have the line
playerScore += currentRoundData.pointsAddedForCorrectAnswer;
in your AnswerButtonClicked method which should add an amount you defined to the score if the answer is correct. Since I presume that your whole code is running fine (I can't see your in-engine setup, only the code here, which looks like the one in the tutorial), this is probably the first location where to look at the error. This value is probably set in the Unity Inspector or via another script, so you may want to go check in other files or the Editor.
The next thing to check is, if the buttons are correctly linked via their event handler. This can be checked by looking at the inspector. In the tutorial series this step is done in part Click to answer at the end of the video.