unity Add selected card in a canvas panel to a dictionary - c#

I have got displayed cards in a scene, they are gameobjects with this script:
public class CardClick : MonoBehaviour
{
DeckBuildManager deckManager;
// Start is called before the first frame update
void Start()
{
deckManager = FindObjectOfType<DeckBuildManager>();
}
// Update is called once per frame
public void AddToDeck()
{
if (deckManager.DeckCards.Count <= 9)
{
if (!deckManager.DeckCards.ContainsValue(this.gameObject.GetComponent<CardValues>().dataCard.cardName))
{
deckManager.DeckCards.Add(this.gameObject.GetComponent<CardValues>().dataCard, this.gameObject.GetComponent<CardValues>().dataCard.cardName);
}
}
}
}
Cards got a button component which use the AddToDeck function when clicked but there are impossible to click.
What can i do to click them?
I use panel to display those cards so its impossible to delete the panel in case it was the error.

resolv
public void ClickOnCard()
{
if (deckManager.DeckCards.Count <= 9)
{
if (!deckManager.DeckCards.ContainsValue(this.gameObject.GetComponent<CardValues>().dataCard.cardName))
{
deckManager.DeckCards.Add(this.gameObject.GetComponent<CardValues>().dataCard, this.gameObject.GetComponent<CardValues>().dataCard.cardName);
}
}
}

Related

How to pass the current clicked button from a list of buttons in Unity? [duplicate]

This question already has answers here:
Impossible value in lambda expression
(2 answers)
Closed 19 days ago.
I have a list of Buttons that get activated after certain conditions are met. I then add a listener to each button to call a function when clicked. That function then needs to be able to get the text off the button that was clicked. This is what I've tried but it returns an out of range error, I think because it calls the function once clicked, and at that point the variable i is maxed out.
public List<GameObject> ButtonList = new List<GameObject>();
void Start() {
for (int i = 0; i < ButtonList.Count; i++) {
ButtonList[i].SetActive(true);
ButtonList[i].GetComponent<Button>().onClick.AddListener(() => {GetButtonText(ButtonList[i]); });
}
}
public void GetButtonText(GameObject SelectedButton) {
Debug.Log(SelectedButton.GetComponentInChildren<TMP_Text>().text)
}
I thought about creating game objects for each button and assigning them in the inspector, but the number of buttons in the list is likely to fluctuate, so it needs to remain dynamic. Additionally, because the game object this script is attached to is a prefab, I can't set up the listeners in the inspector either.
First of all I would suggest to make it list of Button and not a GameObjects you still will be able to access GameObject without call GetComponent each time.
This think happened because it use the last value of i:
you need to redo it like that:
public List<GameObject> ButtonList = new List<GameObject>();
void Start() {
for (int i = 0; i < ButtonList.Count; i++) {
var button = ButtonList[i];
button.SetActive(true);
button.GetComponent<Button>().onClick.AddListener(() => {GetButtonText(button); });
}
}
public void GetButtonText(GameObject SelectedButton) {
Debug.Log(SelectedButton.GetComponentInChildren<TMP_Text>().text)
}
Base And I rater suggest to create a class to wrap the buttons
public class MyButton : MonoBehaviour
{
public event Action<int> OnClick;
[SerializeField] private Button button;
[SerializeField] private Text text;
private int id = -1;
private void Awake()
{
button.onClick.AddListener(Click);
}
private void Click()
{
OnClick?.Invoke(id);
}
public void Init(int index)
{
id = index;
}
public void SetText(string message)
{
text.text = message;
}
}

First click of Unity UI Button does not respond

I'm trying to use Unity's UI system .
What I want is that I have a button #1 as a card image and I have button 2 as a spade image. First I will click spade image and it's indicator will turn on. After that I will click the card image to make the Spade Icon image disappear. I managed to get variables from script to another script but whatever I do the first click of the Spade Button, the indicator lights up and spadeselected bool changes in the inspector. While spadeselected is true, the first click of the Card image doesn't do a thing. After clicking twice and so on everything works fine. What could cause this problem?
My main script for card button:
public class main : MonoBehaviour
{
private bool ace = false;
spadestatement _spadestatement;
public GameObject spadebutton;
public GameObject spade_icon;
private void Awake()
{
_spadestatement = spadebutton.GetComponent<spadestatement>();
}
private void Start()
{
gameObject.GetComponent<Button>().onClick.AddListener(turnoff);
}
private void turnoff()
{
ace ^= true;
if (_spadestatement.spadeselected == true)
{
spade_icon.SetActive(ace);
}
}
}
My spadestatement script for spade button:
public class spadestatement : MonoBehaviour
{
public bool spadeselected;
public GameObject indicator;
void Start()
{
gameObject.GetComponent<Button>().onClick.AddListener(select);
}
public void select()
{
spadeselected ^= true;
indicator.SetActive(spadeselected);
}
}
And here is a picture to make it more understandable:
When spadeselected is true, the first time you call turnoff() :
private void turnoff()
{
ace ^= true; //first time : after the assignment, ace is true
if (_spadestatement.spadeselected == true)
{
spade_icon.SetActive(ace); // since ace is true, set spade_icon active
}
}
The second time you call turnoff(), ace become false, thus spade_icon is deactive.
If you want to turn on/off the spade_icon, maybe try this one:
private void turnoff()
{
ace ^= true; //first time : after the assignment, ace is true
if (_spadestatement.spadeselected == true)
{
spade_icon.SetActive(!ace); // since ace is true, set spade_icon deactive
}
}
Or, if you don't want to bind the active/deactive behaviour of spade_icon with ace, you can:
private void turnoff()
{
if (_spadestatement.spadeselected == true)
{
spade_icon.SetActive(!spade_icon.activeSelf);
}
}

Simple 2d program working with colors, buttons, and if statements

There are 3 buttons present. Clicking a button will change its color. The task here is to match every color of the buttons to a shade of green. Now, I have the buttons programmed to cycle through 4 colors, the same palette. It works, of course.
What I want to implement now is, to make a text appear once all the buttons match colors. I'm working on Unity and the c# script is on Visual Studio.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ChangeColor : MonoBehaviour
{
[SerializeField] int count = 0;
[SerializeField] Color[] colorArray;
public void button ()
{
if(count < colorArray.Length)
{
gameObject.GetComponent<Image>().color = new Color(colorArray[count].r, colorArray[count].g, colorArray[count].b);
if(count == colorArray.Length - 1)
{
count = -1;
}
count += 1;
}
}
}
First of all your button method can be simplified a lot.
And then I would use a callback that checks your colors everytime one of the buttons was pressed:
public class ChangeColor : MonoBehaviour
{
[SerializeField] int count = 0;
[SerializeField] Color[] colorArray;
[SerializeField] private Image _image;
public Color CurrentColor => _image.color;
public event Action OnChangedColor;
private void Awake ()
{
if(!_image) _image = GetComponent<Image>();
}
public void button ()
{
var count = (count + 1) % colorArray.Length;
var nextColor = colorArray[Count];
_image.color = nextColor;
OnChangedColor?.Invoke();
}
}
And now in a central controller script you have references to all your buttons ChangeColor components and their according target Color like e.g.
[Serializable]
public class ButtonColorPair
{
public ChangeColor changeColor;
public Color targetColor;
// Returns true if a ChangeColor is referenced and the colors are matching
public bool IsMatching => changeColor && changeColor.CurrentColor == tatgetColor;
}
public class ColorChecker : MonoBehaviour
{
public ButtonColorPair[] buttonColorPairs;
private void Awake ()
{
// Register a callback which is called every time one of the buttons
// has changed the color
foreach(var pair in buttonColorPairs)
{
// It is save to remove a callback even if it wasn't added before
// but it makes sure there is only one single callback
pair.changeColor.OnChangedColor -= HandleChangedColor;
pair.changeColor.OnChangedColor += HandleChangedColor;
// Here you would also set the targetColor if you want to do it via code e.g. like
pair.targetColor = Color.green;
// or to be save e.g. pick a random value from the color array etc
// Maybe this class would even be responsible for telling the buttons which colors are
// available at all
}
}
private void OnDestroy()
{
// As a good practice always remove callbacks as soon as you don't need them anymore
foreach(var pair in buttonColorPairs)
{
pair.changeColor.OnChangedColor -= HandleChangedColor;
}
}
// Finally check if the color matches for all buttons everytime one of them was changed
private void HandleChangedColor ()
{
// This is Linq and require "using System.Linq;" on top of your file
if(buttonColorPairs.All(p => p.IsMatching)
{
Debug.Log("All buttons are matching their target color");
}
else
{
Debug.Log("Nope not all matching yet");
}
// it basically equals doing something like
//bool allMatch = true;
//foreach(var p in buttonColorPairs)
//{
// if(!p.IsMatching)
// {
// allMatch = false;
// break;
// }
//}
//if(allMatch)
//{
// Debug.Log("All buttons are matching their target color");
//}
//else
//{
// Debug.Log("Nope not all matching yet");
//}
}
}

how to use Inventory UI buttons by enums

Ill try to explain my issue. I need to do for my school project simple 2D escape room. I've got most of the scripts ready, when I click an item he add to the inventory list, and then I can see it on my inventory bar. The problem is , I want that the buttons of the UI Bar inventory, to know after I click the item , to know what item I've been clicking on. the way I did worked half way because he always give the key item. Ive got State Machine Interface. that inheritance to 2 more scripts (that open or close the other interactive stuff (door drawer). got KeyItems script and Interactable Script and UImanager - Singleton.
is there to it in a generic way?
this is the PlayerCast Script that I add the items I click on to the inventory, thought the button need to be here
public enum item {none , paperclip , key }
public class PlayerCast : MonoBehaviour
{
public Camera cam;
public List<item> inventory;
public item activeItem;
private void Start()
{
inventory = new List<item>();
}
// Update is called once per frame
void Update()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetMouseButtonDown(0))
{
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.CompareTag("Interact"))
{
Interactable interactable = hit.collider.gameObject.GetComponent<Interactable>();
interactable.CLickMe(activeItem);
}
else if(hit.collider.CompareTag("Key"))
{
KeyItems hitItem = hit.collider.gameObject.GetComponent<KeyItems>();
hitItem.PickMeUp();
}
}
}
}
public void ButtonSelect() //this is the generic button im trying to do
{
this.activeItem = item.key;
Debug.Log("Clicked");
}
You need event.
public enum ItemTypes { None , Paperclip , Key }
[DisallowMultipleComponent]
public class Foo : MonoBehaviour {
// Action its void delegate
public event System.Action<ItemTypes> Selected;
public ItemTypes ActiveItem { get; private set; }; // property
public void ButtonSelect () {
ActiveItem = ItemTypes.Key;
Selected?.Invoke(ActiveItem); // invoke event
}
}
[DisallowMultipleComponent]
public class YourUIBar : MonoBehaviour {
[SerializeField] private Foo _foo; // link on inspector
private void OnEnable () {
ItemChange(Foo.ActiveItem); // setup current
Foo.Selected += ItemChange; // subscribe to event
}
private void OnDisable () {
Foo.Selected -= ItemChange;
}
private void ItemChange (ItemTypes item) {
// your code
}
}

How to use Unity Toggle Check Function (checked and unchecked)

I'm trying to toggle. When I click on the toggle (if it is on I mean checked), it closes some gameobject, if I click on the toggle (if it is off I mean unchecked) it opens some gameobject but I don't know which function unity
toggle.onselect?
toggle.onValuesChanged? or others which one
public GameObject controlledObject;
public NamesGet nameController;
public Text text;
public Button button;
public Toggle toggle;
private bool deneme;
public void FixedUpdate()
{
text.text = controlledObject.name;
if(?????????)
{
controlledObject.SetActive(!controlledObject.activeSelf);
}
}
I would use something like this :
toggle.onValueChanged.AddListener((value) =>
{
MyListener(value);
});//Do this in Start() for example
public void MyListener(bool value)
{
if(value)
{
//do the stuff when the toggle is on
}else {
//do the stuff when the toggle is off
}
}
New
instead using OnValueChanged why not use EventTrigger - Pointer Click so it will only be called Once.
same as adding Listener via script but its more quick and handy.

Categories

Resources