So I downloaded the assets file of the final version of the Sloan Kelly Card Game Project from YouTube Link to the video where you can download it in the description and I was playing around with the game it was all working fine.
I then re-opened the game the project the next day and the 'Stick Button' is no longer working. It appears on screen and appears intractable but it will not press.
I made a couple of changes to the code to make it easier to read but didn't think i had changed anything to do with this button. The rest of the code runs fine just this one button.
I'm unsure how to link my project assets package on this sight, but I can show you the code for the button and was just wondering if anyone can see the problem straight away / could you tell me how to link the whole file so you can get a better look at what is happening.
Thanks in advance
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
int dealersFirstCard = -1;
public CardStack player;
public CardStack dealer;
public CardStack deck;
public Button hitButton;
public Button stickButton;
public Button playAgainButton;
public Text winnerText;
/*
* Cards dealt to each player
* First player hits/sticks/bust
* Dealer's turn unyil minimum of 17 value in hand
* Dealers cards: first card is hidden, other cards are facing
*/
#region Hit
public void Hit()
{
player.Push(deck.Pop());
if (player.HandValue() > 21)
{
hitButton.interactable = false;
stickButton.interactable = false;
StartCoroutine(DealersTurn());
}
}
#endregion
#region Stick
public void Stick()
{
hitButton.interactable = false;
stickButton.interactable = false;
StartCoroutine(DealersTurn());
}
#endregion
#region Play Again
public void PlayAgain()
{
playAgainButton.interactable = false;
player.GetComponent<CardStackView>().Clear();
dealer.GetComponent<CardStackView>().Clear();
deck.GetComponent<CardStackView>().Clear();
deck.CreateDeck();
winnerText.text = "";
hitButton.interactable = true;
stickButton.interactable = true;
dealersFirstCard = -1;
StartGame();
}
#endregion
void Start()
{
StartGame();
}
void StartGame()
{
for (int i = 0; i < 2; i++)
{
player.Push(deck.Pop());
HitDealer();
}
}
void HitDealer()
{
int card = deck.Pop();
if (dealersFirstCard < 0)
{
dealersFirstCard = card;
}
dealer.Push(card);
if (dealer.CardCount >= 2)
{
CardStackView view = dealer.GetComponent<CardStackView>();
view.Toggle(card, true);
}
}
#region Dealers turn
IEnumerator DealersTurn()
{
hitButton.interactable = false;
stickButton.interactable = false;
CardStackView view = dealer.GetComponent<CardStackView>();
view.Toggle(dealersFirstCard, true);
view.ShowCards();
yield return new WaitForSeconds(1f);
while (dealer.HandValue() < 17)
{
HitDealer();
yield return new WaitForSeconds(1f);
}
if (player.HandValue() > 21 || (dealer.HandValue() >= player.HandValue() && dealer.HandValue() <= 21))
{
winnerText.text = "You Lose!";
}
else if (dealer.HandValue() > 21 || (player.HandValue() <= 21 && player.HandValue() > dealer.HandValue()))
{
winnerText.text = "You Win!";
}
else
{
winnerText.text = "The house wins!";
}
yield return new WaitForSeconds(1f);
playAgainButton.interactable = true;
}
#endregion
}
Related
Hello I am developing an augmented reality app for android. I made animations with the Animation component of the Anchored Position type for Anchored position of my windows that are contained in different panels.When adding a script to the unity Animation component to Select a window depending on whether I'm clicking it or not; I throw the following mistakes:
This is the script that I use for programming (note that it is from the Animation component). I'm not sure if I need to import some libraries, or what's wrong with my code, why doesn't it compile? Understanding that this code is a bit old; from 2019.
This is the code and I'm relying on this youtube video: https://www.youtube.com/watch?v=WBGY5TxmjrA at minute 29.
``
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class SelecionarVentana : MonoBehaviour
{
public GameObject VentanaGuerrero;
public GameObject VentanaGuitarra;
public GameObject VentanaPiano;
public GameObject VentanaTigre;
Animation AVentanaGuerrero;
Animation AVentanaGuitarra;
Animation AVentanaPiano;
Animation AVentanaTigre;
bool VisibleVGuerrero = false;
bool VisibleVGuitarra = false;
bool VisibleVPiano = false;
bool VisibleVTigre = false;
void Start()
{
AVentanaGuerrero = VentanaGuerrero.GetComponent<Animation>();
AVentanaGuitarra = VentanaGuitarra.GetComponent<Animation>();
AVentanaPiano = VentanaPiano.GetComponent<Animation>();
AVentanaTigre = VentanaTigre.GetComponent<Animation>();
}
public void VentanaGuePulsada()
{
if (VisibleVGuerrero == false)
{
AVentanaGuerrero["Guerrero"].speed = 1;
AVentanaGuerrero.Play();
VisibleVGuerrero = true;
}
}
public void VentanaGuiPulsada()
{
if (VisibleVGuitarra == false)
{
AVentanaGuitarra["Guitarra"].speed = 1;
AVentanaGuitarra.Play();
VisibleVGuitarra = true;
}
}
public void VentanaPiaPulsada()
{
if (VisibleVPiano == false)
{
AVentanaPiano["Piano"].speed = 1;
AVentanaPiano.Play();
VisibleVPiano = true;
}
}
public void VentanaTigPulsada()
{
if (VisibleVTigre == false)
{
AVentanaTigre["Tigre"].speed = 1;
AVentanaTigre.Play();
VisibleVTigre = true;
}
}
public void VentanaNoPulsada()
{
string NombreBoton = EventSystem.current.currentSelectedGameObject.name;
if (NombreBoton != "Guerrero" & VisibleVGuerrero == true)
{
AVentanaGuerrero["Guerrero"].speed = -1;
AVentanaGuerrero["Guerrero"].time = AVentanaGuerrero["Guerrero"].length;
AVentanaGuerrero.Play();
VisibleVGuerrero = false;
}
if (NombreBoton != "Guitarra" & VisibleVGuitarra == true)
{
AVentanaGuitarra["Guitarra"].speed = -1;
AVentanaGuitarra["Guitarra"].time = AVentanaGuitarra["Guitarra"].length;
AVentanaGuitarra.Play();
VisibleVGuitarra = false;
}
if (NombreBoton != "Piano" & VisibleVPiano == true)
{
AVentanaPiano["Piano"].speed = -1;
AVentanaPiano["Piano"].time = AVentanaPiano["Piano"].length;
AVentanaPiano.Play();
VisibleVPiano = false;
}
if (NombreBoton != "Tigre" & VisibleVTigre == true)
{
AVentanaTigre["Tigre"].speed = -1;
AVentanaTigre["Tigre"].time = AVentanaTigre["Tigre"].length;
AVentanaTigre.Play();
VisibleVTigre = false;
}
}
}
``
What's wrong with this old code I try to compile it into unity. I'm on unity version 2021.3.10f1.
I am making a badminton simulator in unity, where the opponent is a set of video clips. I am trying to add some delay to my update method so theres some time between two clips of the opponent. However this delay only applies to the video clips and not the shuttle that arrives from behind the video.
My Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
public class Video_Player : MonoBehaviour
{
public VideoPlayer activeCam, otherCam;
public List<VideoClip> playlist = new List<VideoClip>();
public GameObject shuttle;
VideoClip nextClip;
private bool Timer;
void Start()
{
Shuffle(playlist);
// play the first video in the playlist
PrepareNextPlaylistClip();
SwitchCams(activeCam);
Timer=false;
// setup an event to automatically call SwitchCams() when we finish playing
activeCam.loopPointReached += SwitchCams;
otherCam.loopPointReached += SwitchCams;
shuttle.SetActive(false);
}
void Update()
{
if (playlist.Count == 0)
return;
if(!Timer)
{
StartCoroutine(CountDown(5));
if (nextClip == null && activeCam.time >= activeCam.clip.length - 0.1)
{
PrepareNextPlaylistClip();
shuttle.SetActive(false);
}
if(activeCam.time >= 1.0f && activeCam.time <= 2.95f)
{
Debug.Log("start:"+activeCam.time);
shuttle.SetActive(true);
}
else
//if(activeCam.time >= 2.95f || activeCam.time <= 1.0f)
{
Debug.Log("end:"+activeCam.time);
shuttle.SetActive(false);
}
}
}
void SwitchCams(VideoPlayer thisCam)
{
activeCam = otherCam;
otherCam = thisCam;
activeCam.targetCameraAlpha = 1f;
otherCam.targetCameraAlpha = 0f;
Debug.Log("new clip: " + nextClip.name);
nextClip = null;
}
void PrepareNextPlaylistClip()
{
nextClip = playlist[0];
otherCam.clip = nextClip;
otherCam.Play();
playlist.RemoveAt(0);
}
//delay couroutine
IEnumerator CountDown(float delay)
{
Timer = true;
yield return new WaitForSeconds(delay);
Timer= false;
}
// randomize the video playlist
public static void Shuffle<T>(IList<T> playlist)
{
int n = playlist.Count;
while (n > 1)
{
n--;
int k = Random.Range(0, n);
T value = playlist[k];
playlist[k] = playlist[n];
playlist[n] = value;
}
}
}
Forgive me if I'm misunderstanding your code but rather than having it all in Update() couldn't you just have it in an IEnumerator like this?
void Start()
{
Shuffle(playlist);
// play the first video in the playlist
PrepareNextPlaylistClip();
SwitchCams(activeCam);
activeCam.loopPointReached += SwitchCams;
otherCam.loopPointReached += SwitchCams;
shuttle.SetActive(false);
//Run the function on start
StartCoroutine(Function());
}
IEnumerator Function()
{
while(true)
{
if(playlist.Count == 0)
{
//If you have no clips left exit out of the loop
break;
}
if(nextClip == null)
{
//If you have clips left load the next clip
shuttle.SetActive(false);
PrepareNextPlaylistClip();
}
yield return new WaitForSeconds(1); //This is your delay
//Execute the code you want to run after the delay here
}
}
I am working on small game similar to angry birds since I am new to both unity
and C#. I want to make load and unlock next level if all enemies are dead and check if new level exist
(if not) return back to Level selection scene.
This is what I tried:
LevelScript
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelScript : MonoBehaviour
{
[SerializeField] string _nextLevelName;
Monster[] _monsters;
void OnEnable()
{
_monsters = FindObjectsOfType<Monster>();
}
private void Update()
{
int currentLevel = SceneManager.GetActiveScene().buildIndex ;
if (currentLevel >= PlayerPrefs.GetInt("levelsUnlocked"))
{
PlayerPrefs.SetInt("levelsUnlocked", currentLevel );
}
if (MonsterAreAllDead())
{
GoToNextLevel();
}
Debug.Log("Level" + PlayerPrefs.GetInt("levelsUnlocked") + "UNLOCKED");
}
public void Pass()
{
int currentLevel = SceneManager.GetActiveScene().buildIndex;
if (currentLevel >= PlayerPrefs.GetInt("levelsUnlocked") )
{
PlayerPrefs.SetInt("levelsUnlocked", currentLevel + 1);
};
}
bool MonsterAreAllDead()
{
foreach (var monster in _monsters)
{
if (monster.gameObject.activeSelf)
return false;
}
return true;
}
void GoToNextLevel()
{
Debug.Log("Go to next level" + _nextLevelName);
SceneManager.LoadScene(_nextLevelName);
}
}
and Level Manager
public class LevelManager : MonoBehaviour
{
int levelsUnlocked;
public Button[] buttons;
void Start()
{
levelsUnlocked = PlayerPrefs.GetInt("levelsUnlocked", 1);
for (int i = 0; i < buttons.Length; i++)
{
buttons[i].interactable = false;
}
for (int i = 0; i < levelsUnlocked; i++)
{
buttons[i].interactable = true;
}
}
public void LoadLevel(int levelIndex)
{
SceneManager.LoadScene(levelIndex);
}
I got these 2 scripts and I attached both canvas and my buttons and Level script to my levels.
Problem is that every level gets unlocked at begin and after completeing levels automatically
it want to go to next level whic is not exist yet.
Pls help me. Sorry if my question is stupid and for bad english.
You should make an array of scene in your LevelManager that know all your levels (in order)
and for getting next level you can get the position of your actual scene in the array and check the next one.
somethink like
pseudocode :
[Serialized]
Scene[] AllScenes
void GoToNextLevel()
{
int currentLevelPos = AllScenes.IndexOf(currentScene);
if (AllScenes[currentLevelPos + 1] != null)
Load Next Level
else
Go To Level Menu
}
I have the following coroutine which displays a warning error image when you click on a button and you do not have enough money:
public IEnumerator ShowWarning()
{
if (warningActive)
yield break;
Debug.Log("started...");
warningActive = true;
NotEnoughMoneyImage.SetActive(true);
yield return new WaitForSeconds(1f);
NotEnoughMoneyImage.SetActive(false);
warningActive = false;
Debug.Log("ended...");
yield break;
}
NotEnoughMoneyImage is a public Image GameObject
warningActive is a public bool
It shows the debug line "started" but never shows the debug line "ended". How is that possible? I call it from another script, but I don't think that there is the problem.
Here I've got the first script which is attached to an empty object (the main parent of the shop UI). This script is the main one. At the final of it appears the IEnumerator:
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using UnityEngine;
public class WeaponShop : MonoBehaviour
{
public static WeaponShop shop;
public GameObject itemHolderPrefab;
public Transform grid;
public List<Weapon> weaponList = new List<Weapon>();
private List<GameObject> itemHolderList = new List<GameObject>();
public List<GameObject> buyButtonList = new List<GameObject>();
public GameObject NotEnoughMoneyImage;
public bool warningActive = false;
void Start()
{
NotEnoughMoneyImage.SetActive(false);
shop = this;
FillList();
}
void FillList()
{
for (int i = 0; i < weaponList.Count; ++i)
{
GameObject holder = Instantiate(itemHolderPrefab, grid);
ItemHolder holderScript = holder.GetComponent<ItemHolder>();
holderScript.itemID = weaponList[i].weaponID;
holderScript.itemName.text = weaponList[i].weaponName;
if (weaponList[i].weaponPrice != (int)weaponList[i].weaponPrice)
holderScript.itemPrice.text = weaponList[i].weaponPrice.ToString("N2") + "$";
else
holderScript.itemPrice.text = weaponList[i].weaponPrice.ToString() + "$";
holderScript.itemSprite.sprite = weaponList[i].weaponSprite;
holderScript.buyButton.GetComponent<BuyButton>().weaponID = weaponList[i].weaponID;
itemHolderList.Add(holder);
buyButtonList.Add(holderScript.buyButton);
}
}
public void SoldOutText(int weaponID)
{
for (int i = 0; i < weaponList.Count; ++i)
if (weaponList[i].weaponID == weaponID)
itemHolderList[i].GetComponent<ItemHolder>().itemPrice.text = "SOLD OUT!";
}
public IEnumerator ShowWarning()
{
if (warningActive)
yield break;
Debug.Log("started...");
warningActive = true;
NotEnoughMoneyImage.SetActive(true);
yield return new WaitForSeconds(1f);
NotEnoughMoneyImage.SetActive(false);
warningActive = false;
Debug.Log("ended...");
yield break;
}
}
Now the second script is attached to the "BUY" button of a prefab "Item Holder". The script above (first one) generates a number of prefabs "item holder" and fills them with the info from the inspector (weapon name, price, stats etc). Here it comes the second script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.PlayerLoop;
public class BuyButton : MonoBehaviour
{
public int weaponID;
public TMP_Text buttonText;
public void BuyWeapon()
{
if (weaponID == 0)
{
Debug.Log("Weapon ID is ZERO");
return;
}
for (int i = 0; i < WeaponShop.shop.weaponList.Count; ++i)
{
if (WeaponShop.shop.weaponList[i].weaponID == weaponID && !WeaponShop.shop.weaponList[i].isBought && CurrencyManager.currencyManager.RequestMoney(WeaponShop.shop.weaponList[i].weaponPrice))
{// USING
WeaponShop.shop.weaponList[i].isBought = true;
CurrencyManager.currencyManager.ReduceMoney(WeaponShop.shop.weaponList[i].weaponPrice);
WeaponShop.shop.SoldOutText(weaponID);
UpdateBuyButton();
// change the weapon system and update your weapon, depending on ID / name here
}
else if (WeaponShop.shop.weaponList[i].weaponID == weaponID && !WeaponShop.shop.weaponList[i].isBought && !CurrencyManager.currencyManager.RequestMoney(WeaponShop.shop.weaponList[i].weaponPrice))
{//NOT ENOUGH MONEY. I know that it enters this if statement because of the debug.log
Debug.Log("Corountine...");
StartCoroutine(WeaponShop.shop.ShowWarning());
}
else if (WeaponShop.shop.weaponList[i].weaponID == weaponID && WeaponShop.shop.weaponList[i].isBought)
{
UpdateBuyButton();
// change the weapon system and update your weapon, depending on ID / name here
}
}
}
void UpdateBuyButton()
{
buttonText.text = "USING";
for (int i = 0; i < WeaponShop.shop.buyButtonList.Count; ++i)
{
BuyButton buyButtonScript = WeaponShop.shop.buyButtonList[i].GetComponent<BuyButton>();
for (int j = 0; j < WeaponShop.shop.weaponList.Count; ++j)
{
if (WeaponShop.shop.weaponList[j].weaponID == buyButtonScript.weaponID && WeaponShop.shop.weaponList[j].isBought && WeaponShop.shop.weaponList[j].weaponID != weaponID)
{
buyButtonScript.buttonText.text = "USE";
}
}
}
// change the weapon system and update your weapon, depending on ID / name
}
}
At line 34 is the start coroutine method.
Yes, I figured it out! When I was entering the shop UI, I was pausing the game in another script. So the time scale was 0. All I had to do was to replace in the coroutine this line:
yield return new WaitForSeconds(1f);
to this one:
yield return new WaitForSecondsRealtime(1f);
That was it! Now it works just fine! For everyone which thinks the coroutine does not work well, check your time scale. It's very important (Idk how I missed it!).
thanks for reading.
I'm currently building a small memory card game in Unity using C#. I have the main portion of code finished but when I press the play button on a certain scene Unity freezes.
I believe it is due to an infinite While loop, but I can not find the issue. I would really appreciate any help anyone can offer. I will leave my code below. Thanks in advance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine;
public class Pairs : MonoBehaviour {
public Sprite[] face; //array of card faces
public Sprite back;
public GameObject[] deck; //array of deck
public Text pairsCount;
private bool deckSetUp = false;
private int pairsLeft = 13;
// Update is called once per frame
void Update () {
if (!deckSetUp)
{
SetUpDeck();
}
if (Input.GetMouseButtonUp(0)) //detects left click
{
CheckDeck();
}
}//Update
void SetUpDeck()
{
for (int ix = 0; ix < 2; ix++)
{
for(int i = 1; i < 14; i++)//sets up card value (2-10 JQKA)
{
bool test = false;
int val = 0;
while (!test)
{
val = Random.Range(0, deck.Length);
test = !(deck[val].GetComponent<Card>().SetUp);
}//while
//sets up cards
deck[val].GetComponent<Card>().Number = i;
deck[val].GetComponent<Card>().SetUp = true;
}//nested for
}//for
foreach (GameObject crd in deck)
{
crd.GetComponent<Card>().setUpArt();
}
if (!deckSetUp)
{
deckSetUp = true;
}
}//SetUpDeck
public Sprite getBack()
{
return back;
}//getBack
public Sprite getFace(int i)
{
return face[i - 1];
}//getFace
void CheckDeck()
{
List < int > crd = new List<int>();
for(int i = 0; i < deck.Length; i++)
{
if(deck[i].GetComponent<Card>().State == 1)
{
crd.Add(i);
}
}
if(crd.Count == 2)
{
CompareCards(crd);
}
}//CheckDeck
void CompareCards(List<int> crd)
{
Card.NO_TURN = true; //stops cards turning
int x = 0;
if(deck[crd[0]].GetComponent<Card>().Number ==
deck[crd[1]].GetComponent<Card>().Number)
{
x = 2;
pairsLeft--;
pairsCount.text = "PAIRS REMAINING: " + pairsLeft;
if(pairsLeft == 0) // goes to home screen when game has been won
{
SceneManager.LoadScene("Home");
}
}
for(int j = 0; j < crd.Count; j++)
{
deck[crd[j]].GetComponent<Card>().State = x;
deck[crd[j]].GetComponent<Card>().PairCheck();
}
}//CompareCards
}
I believe the issue lies in the while(!test) but i do not know why test never become true.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class Card : MonoBehaviour {
public static bool NO_TURN = false;
[SerializeField]
private int cardState; //state of card
[SerializeField]
private int cardNumber; //Card value (1-13)
[SerializeField]
private bool _setUp = false;
private Sprite back; //card back (Green square)
private Sprite face; //card face (1-10 JQKA)
private GameObject pairsManager;
void Begin()
{
cardState = 1; //cards face down
pairsManager = GameObject.FindGameObjectWithTag("PairsManager");
}
public void setUpArt()
{
back = pairsManager.GetComponent<Pairs>().getBack();
face = pairsManager.GetComponent<Pairs>().getFace(cardNumber);
turnCard();//turns the card
}
public void turnCard() //handles turning of card
{
if (cardState == 0)
{
cardState = 1;
}
else if(cardState == 1)
{
cardState = 0;
}
if (cardState == 0 && !NO_TURN)
{
GetComponent<Image>().sprite = back; // shows card back
}
else if (cardState == 1 && !NO_TURN)
{
GetComponent<Image>().sprite = face; // shows card front
}
}
//setters and getters
public int Number
{
get {return cardNumber;}
set { cardNumber = value;}
}
public int State
{
get { return cardState; }
set { cardState = value; }
}
public bool SetUp
{
get { return _setUp; }
set { _setUp = value; }
}
public void PairCheck()
{
StartCoroutine(pause ());
}
IEnumerator pause()
{
yield return new WaitForSeconds(1);
if (cardState == 0)
{
GetComponent<Image>().sprite = back;
}
else if (cardState == 1)
{
GetComponent<Image>().sprite = face;
}
}
}
Thank you for reading, I will post a link to the github repository if that helps.
github repository
Your deck array has at least one card in it that has _setUp set to true which would make it go in a infinite loop.
The reason it goes in a infinite loop is because it will have set all available _setUp to true and it would keep looking for _setUp that are set to false and it will never find any.
The reason you need at least 26 object that have _setUp to false is because in the nested for loop you loop 13 times and then you do that twice which gives a total of 26 loops. So you need at least 26 objects.
What you can do to make sure that they're all false is to set them all to false before entering the for loop
for(int i = 0; i < deck.Length; i++)
{
deck[i].GetComponent<Card>().SetUp = false;
}