Find a GameObject and check if the user has clicked on it - c#

I have recently been making the UI for a game I am creating and have run into a problem.
I have been trying to find a way in the new Unity 4.6 for the user to be able to click on a player card and have it select the player they clicked on.
public void Panel1Click()
{
GameManager.Player1Select ();
}
This is the way I am doing it at the moment, calling this when the player clicks on Panel 1, there are also 3 more for each of them.
I have been researching different methods on how to find the object the player clicks the execute the correct selecting code.
if (GameObject.Find ("Panel 1"))
{
print ("Click Panel 1");
GameManager.Player1Select();
}
This is one of the methods I tried, however nothing gets called. (Because it just checks if the object exists/is true? I think).
All these methods are linked to the EventSystem component on the panels.
Is there a more efficient way of condensing all the functions and just checking which panel the player clicks on?

You can add a collider to the game object (sprite), and then in the OnMouseDown function to test if it is clicked.
Select the card --> Add a box collider to it --> Add a MonoBehaviour script and attach to the card --> In the script, add function:
bool bClicked = false;
void OnMouseDown()
{
Debug.Log(gameObject.name + " is clicked");
bClicked = true;
}

You can actually have one parameter for your click handler. Supported types are: int, float, string and object reference. So you can define your handler like this:
public void SelectCharacter(int character) {
GameManager.PlayerSelect(character)
}
Then just set the parameter in the event trigger.

Create a script and put it on the object(Panel) you want to interact with, then try this code. In this example it finds the parent panel and sets it to inactive
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class CloseInventory : MonoBehaviour, IPointerDownHandler
{
GameObject inventoryPanel;
// Use this for initialization
void Start()
{
inventoryPanel = GameObject.Find("Inventory Panel");
}
public void OnPointerDown(PointerEventData eventData)
{
//SET WHAT TO DO HERE
inventoryPanel.SetActive(false);
}
}

Related

How to Make a Clickable Sprite in Unity 2D, detect if the cursor is hovering over a sprite, and how to change scene with code

I am making a 2D game in unity, and I want a start screen, but I cant find out how to make the start button clickable, and to then change the scene to level 1
The game will be a cursor labyrinth, so any help with detecting if a mouse is hovering over something would be appreciated
I looked up a bunch of tutorials but none of them worked in c#
STEP 1:
You will have to add a Button Component to the sprite.
Alternatively, you can right click in the Scene Hierarchy and go to Create -> UI -> Button. This automatically creates a simple Button for you. Then it sprites can be changed accordingly.
STEP 2:
Then assign callback to the Button in the OnClick() Field to make it interactable. To load the scene,
Create a new C# script. Make a new method in it. Use the LoadScene method in SceneManagement class. Then the script becomes:
using UnityEngine;
using UnityEngine.SceneManagement;
public class ExampleScript: MonoBehaviour
{
public void Loadscene(int sceneIndex)
{
SceneManager.LoadScene(sceneIndex);
}
}
Here you go bro.
public bool IsOverUi()
{
var eventDataCurrentPosition = new PointerEventData(EventSystem.current)
{
position = Input.mousePosition
};
var results = new List();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
return results.Count > 0;
}
Following the Answer here: https://answers.unity.com/questions/1199251/onmouseover-ui-button-c.html
You can add a script:
public class MyClass: MonoBehaviour, IPointerEnterHandler{
public void OnPointerEnter(PointerEventData eventData)
{
//do stuff
}
}

How do I assign a method that is inside a prefab to the On Click() event on a button?

I have a button that is supposed to switch beetween light and dark mode in my game by running the method "ToggleTheme" inside the ObjectTheme script, which all the objects that I want to be affected by light/dark mode have. ToggleTheme just changes the boolean "DarkMode", since all the objects' transitions use this DarkMode boolean. It all works fine if I just assign the objects and select ObjectTheme.ToggleTheme, but if I assign the objects' prefabs and select ObjectTheme.ToggleTheme I get the warning "Animation is not playing an AnimatorController" on button press. Is there any way around this, because assigning every object in every scene would just be to impractical and one of the objects has up to 30 copies in every level of the game?
P.S. I know It probably would have been easier if I just used a toggle instead of a button, but I'm new to Unity and I just couldn't get the toggle to work how I wanted it, so I'm using a button instead.
Here is the ObjectTheme script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectTheme : MonoBehaviour
{
public Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
public void ToggleTheme()
{
if(animator.GetBool("DarkMode") == true)
{
animator.SetBool("DarkMode", false);
}
else
{
animator.SetBool("DarkMode", true);
}
}
}
**Edited after Jonatan's comments below.
I understand the desire to just assign the prefab as the button's event target. But the prefab itself is in some sense also just an instance that is just not living in the scene. While in edit mode, all changes in the prefab itself will reflect in the scene instances. But when you are in play mode (runtime) the prefab instances in the scene will no longer automatically update themselves with changes in the prefab file.
In this case, we are trying to set a bool value on an Animator component, but the Animator on the prefab is not really playing - only the Animators on the scene instances are playing. That is why you get the 'not playing' warning.
One option to solve the issue could be something like the following.
First add a script to the button that has a function that can be hooked up with your button's OnClick() UnityEvent. The script will look for instances of another script, which is present on all the objects that should react to dark mode state. This other script could be your ObjectTheme script but here I call it DarkModeReceiver. When the button triggers the function, the script will simply call a function on all the script instances stored in its array.
//Put this script on the Button,
//and hook up the Button's OnClick event with the OnButtonClicked() function
using UnityEngine;
public class DarkModeHandler : MonoBehaviour
{
static bool isDarkMode;
public static bool IsDarkMode => isDarkmode;//Public get property
//Make your Button call this function in its OnClick() event
public void OnButtonClicked()
{
isDarkMode = !isDarkMode;//Toggle bool
SendIsDarkMode();
}
//Alternatively, if you choose to use a Toggle instead
//you could hook this function up with the Toggle's OnValueChanged(Boolean) event
//with the dynamic bool of that event.
public void OnToggleValueChanged(bool isToggledOn)
{
isDarkMode = isToggledOn;
SendIsDarkMode();
}
void SendIsDarkMode()
{
var darkModeReceivers = FindObjectsOfType<DarkModeReceiver>(true);
foreach (var receiver in darkModeReceivers)
{
receiver.SetIsDarkMode(isDarkMode);
}
}
}
And then the receiving script (attached on all the game objects / prefabs that should react to dark mode state) could be something like this (or a modified version of your ObjectTheme script).
using UnityEngine;
public class DarkModeReceiver : MonoBehaviour
{
Animator myAnimator;
void Awake()
{
myAnimator = GetComponent<Animator>();
}
void Start()
{
//Ensure that our state is in sync with the DarkModeHandler
SetIsDarkMode(DarkModeHandler.IsDarkMode);
}
public void SetIsDarkMode(bool isDarkMode)
{
myAnimator.SetBool("DarkMode", isDarkMode);
}
}
Alternatively, you could do something where the DarkModeReceivers/ObjectThemes register themselves on the DarkModeHandler on their Start() and unregister themselves again on their OnDestroy() - for example by subscribing to an event. Then the DarkModeHandler wouldn't have to look for receivers every time the button is clicked.

How do i disable a button GameObject after clicking it. In other words, have a button that is only clickable ONCE

I'm making an upgrade button for a game I'm creating, obviously I want the upgrade to only be available once, how do I code that?
I looked around the internet and each person suggested trying the following:
Bouton.SetActive (false);
or something like that. However, this makes the button inactive during startup. I want it to be inactive or destroyed after just one click. the button in question must be a GameObject
Anyone know how to fix this?
Thank you in advance!
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class One_One_Click_to_Save_the_GameObject_Deactivate_If_scene_replay : MonoBehaviour
{
public GameObject Bouton;
void Start()
{
if (PlayerPrefs.HasKey("buttonState")) // if the button was saved in memory
{
if (PlayerPrefs.GetInt("buttonState") == 0) //if the value is 0
Bouton.SetActive (false); // make button disabled
}
else
{
PlayerPrefs.SetInt("buttonState", 1); // saving in memory that button is on
}
}
public void buttonCliked()
{
Bouton.SetActive(false); // making the button disabled
PlayerPrefs.SetInt("buttonState", 0); //saving in memory that button is off
}
}
First of all you do not have any code piece to reset the state of your button on PlayerPrefs.
You should go to Edit -> Clear All PlayerPrefs on Unity Editor to get rid of the previous saved states.
Then you will check if the player is already used the upgrade button which you did on start but you dont need the else statement because in default it will be already active on the scene so this should be enough
void Start()
{
if (PlayerPrefs.HasKey("buttonState")) // if the button was saved in memory
{
if (PlayerPrefs.GetInt("buttonState") == 0) //if the value is 0
Bouton.SetActive (false); // make button disabled
}
}
Alternatively you can use the PlayerPrefs.GetInt() method with a default parameter so you don't need to check if it has a key, like this
void Start()
{
if (PlayerPrefs.GetInt("buttonState",1) == 0) // This will return 1 if there is no key with the name "buttonState"
Bouton.SetActive (false);
}
And after you clicked the upgrade which you should be doing on your buttonCliked() method. You can set the buttonstate to zero and it will always disable it on start. If you want to reset the state you need to clear the player prefs again like we did it on first step
public void buttonCliked()
{
Bouton.SetActive(false); // making the button disabled
PlayerPrefs.SetInt("buttonState", 0); //saving in memory that button is off
}
But again alternatively you can disable the clicking function on the button rather than just disabling it on the menu. What you should do is create a Button reference rather than a gameobject (or get the button component on the gameobject) and set it's interactable field to false. Which makes the button not clickable but still be seen on the screen.
You can use public Button Bouton; rather than public GameObject Bouton;and instead of using Bouton.SetActive (false); you can now call Bouton.interactable = false;

Unity - How to change what GameObjects are visible with button click events?

I am newbie in Unity I am working on Augmented reality project where I am showing 3D Objects based on the marker that is working fine. But what I would like is to show different objects based on click events
Here is the scenario I did so far:
I created 4 different scenes with 3D objects with markers
Made one canvas frame where I put 3 buttons on it
In each button click I am loading next scene, below is the code that I wrote. The problem is it is showing black screen instead of loading new objects. I don't want to load a camera again. Can anyone help me with this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // <<<<<< ADD THIS.
public class Button_1 : MonoBehaviour
{
public void Button_Click()
{
Debug.Log("Hello, World!");
// Application.LoadLevel("Multi Target");
SceneManager.LoadScene("MultiTarget_1"); // <<<< Then Do this.
}
public void Button_Click2()
{
Debug.Log("Hello, World!");
// Application.LoadScene("Multi Target_1");
SceneManager.LoadScene("NameOfScene"); // <<<< Then Do this.
}
public void Button_Click3()
{
Debug.Log("Hello, World!");
Application.LoadLevel("Multi Target_2");
}
public void Button_String(string msg)
{
Debug.Log("Hello, All!");
Application.LoadLevel("Multi Target_1");
}
}
image
If you have, let's say, two groups of Objects in a Scene, for example:
GoupA = Cars
GroupB = Pedestrians
And you want that by default Cars are visible and Pedestrians are not, so as soon as you click a button Cars become invisible in your scene and Pedestrians become visible, one thing you can do is to assign different layers for each group of objects and then change the culling mask of your camera programatically when one of the buttons is pressed.
Step 1:
You need to create two or more layers in your scene, and assign those layers to your GameObjects in your scene, depending on what objects you want to make visible at the same time after button click. You will need to read about this here:
https://docs.unity3d.com/Manual/Layers.html
Step 2:
Create in your code a reference to the active Camera in your scene:
Camera cam;
Step 3:
Change your logic inside Button_Click methods
public void Button_Click1()
{
// Only render objects in the first layer (Default layer)
cam.cullingMask = 1 << 0;
}
...
These are other things you can do with the culling mask (depending on how you want to display your GameObjects):
// Render everything *except* layer 3
camera.cullingMask = ~(1 << 3);
// Switch off layer 3, leave others as-is
camera.cullingMask = ~(1 << 3);
// Switch on layer 3, leave others as-is
camera.cullingMask |= (1 << 3);
You can read more about it here:
https://docs.unity3d.com/ScriptReference/Camera-cullingMask.html
Hi i think you can fix your project by just grouping and hiding the GameObject. its much more simple that you think... i already write a sample code... and i already add a link to do just that on how to group the object if you need help on that... i am an Augmented Reality Developer as well so i understand the problem that you are having.... hope this will help..
URL: https://www.youtube.com/watch?v=MP62CcK-qTc
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // <<<<<< ADD THIS.
public class Button_1 : MonoBehaviour
{
public GameObject MultiTarget_1, NameOfScene,Multi_Target_2,Multi_Target_1;
public void Button_Click()
{
Debug.Log("Hello, World!");
HideAll();
MultiTarget_1.SetActive(true);
}
public void Button_Click2()
{
Debug.Log("Hello, World!");
HideAll();
NameOfScene.SetActive(true);
}
public void Button_Click3()
{
Debug.Log("Hello, World!");
HideAll();
Multi_Target_2.SetActive(true);
}
public void Button_String(string msg)
{
Debug.Log("Hello, All!");
HideAll();
Multi_Target_1.SetActive(true);
}
//call this to hide all
public void HideAll(){
MultiTarget_1.SetActive(false);
NameOfScene.SetActive(false);
Multi_Target_2.SetActive(false);
Multi_Target_1.SetActive(false);
}
}
There are two things. First check if the correct scene name is given and that it is loading.
If you want to persist the Camera Object over different scenes, then make the object DontDestroyOnLoad() using a script attached to the Camera.
Read more here:
https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
You dont need different scenes, just 1 scene which has AR sessions and AR session origin.
create a new blank gameobject and reset its transform ( Scale , rotation , position) so that everything is at 0, except "scale" which will be at 1,
select all the gameobject you want during "BUTTON 1" click event , make them the child of the new blank gameobject which you created.
Repeat the same for the all the gameobjects which you want to change during button click.
After you have created each game object for each button, make them PREFABS. ( just drag the game object from The Hierarchy window to project wind where you can see all your files )
Create a script and create public or serialised array of Gameobect variable , and save the script.
public Gameobject obj1[];
If you are not aware of using arrays, you can just create multiple(number of buttons / Parent Gameobjects you have) gameobject variables
Drop the script on a gameobject , on the script you will see that you can drag drop the game objects with the same name which you have given during creation of variables.
In the UI Script ( on button click event) , you just have to enable and disable the prefabs ( VARIABLES WHICH YOU CREATED) accordingly,

Unity3d C# - How to check if a button has been pressed, and then instantiate an object

So for the past two days (no joke) I have been trying to figure out how to check if a button is pressed, and then if so, make it instantiate an object. I have tried multiple methods so far and maybe one of those methods were closer to getting where I wanted but for now I will just show what I have currently. Right now, the problem is me detecting if the button has even been clicked in the first place.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Master : MonoBehaviour
{
public Button storeButton;
public Transform hands;
public GameObject gun1;
void OnEnable()
{
gun1 = GameObject.FindGameObjectWithTag("Weapon1");
hands = GameObject.FindGameObjectWithTag("Player").transform;
// storeButton.onClick.AddListener(MyFunction);//adds a listener for when you click the button
storeButton.onClick.AddListener(() => MyFunction());
}
void MyFunction()
{
Debug.Log("YOUR PRESSED THE DAMN BUTTON");
// Instantiate(gun1, hands.position, hands.rotation);
GameObject.Instantiate(gun1, hands.position, hands.rotation);
}
}
Add an EventSystem to your Scene.
Otherwise you cant click Buttons an other Stuff.
http://docs.unity3d.com/Manual/EventSystem.html

Categories