I've got an issue. When (Input.GetMouseButtonUp (0), Speedy script is disabled, thus we cannot enable it again from inside the script like shown below. How can we go around this?
public class Speedy : MonoBehaviour {
GameObject car;
if (speed == good)
{
GameObject car = GameObject.FindWithTag ("Car");
if (Input.GetMouseButtonUp (0))
{
car.GetComponent<Speedy>().enabled = false;
}
else car.GetComponent<Speedy>().enabled = true;
}
}
When disabled, a script wont run anymore and therefore you cannot enable it from the same script again (of course you could create a background thread which keeps it running, that would be a terrible solution).
Create a separate script called SpeedyEnabler, that enables the Speedy script on mouse click and add it to the GameObject.
Alternatively, declare a field isEnabled in Speedy, replace this.enabled by isEnabled and perform the desired actions when isEnabled is true.
If your script simply is supposed to act on input, enabling and disabling the script is not a good idea anyway. Instead, call a method from the input controller to act...
Related
I have an MRTK Slate which comes with Pressable Button to close the slate.
When the close button is pressed, the Slate is disabled but not destroyed. This is because in the Events section>Interactable script> GameObject.SetActive() is set by default as shown in fig:
I want to destroy the slate after clicking close button.
I know I can do this by making a script, attaching the slate prefab to the script(or taking the parent of the button till I get slate as parent game object), calling the function, and using GameObject.Destroy().
But I want to understand how the GameObject dropdown in the Interactable script is getting populated :
I understand that the other dropdowns like Transform, Follow me toggle, Solverhandler, etc are displayed because they are attached to the Slate.
But how does the GameObject option is available? This seems a basic thing, but I would like to be sure about how it is coded.
And if it is possible to add my new action in the Gameobject dropdown, if so, how?
I spent time looking at the scripts of Interactable and others, but I am a beginner in C# and was not able to see where is the code which does this.
Any input will help me.
No you can't because Object.Destroy is static and in UnityEvent (which Interactable.OnClick uses) via the Inspector you can only select instance methods.
You at lest need a minimal component like
public class ObjectDestroyer : MonoBehaviour
{
public void DestroyObject()
{
Destroy(this.gameObject);
}
}
or if you don't want to do it via the Inspector but automatically
public class ObjectDestroyer : MonoBehaviour
{
// store the itneractable reference
[Tootltip("If not provided uses the Interactable on this GameObject")]
[SerialzieField] private Interactable _interactable;
// Optionally provide a different target, otherwise destroys the Interactable
[Tooltip("If not provided destroys the GameObject of the Interactable")]
[SerializeField] private GameObject _targetToDestroy;
private void Awake()
{
// use get component as fallback if no Interactable was provided
if(!_interactable) _interactable = GetComponent<Interactable>();
// attach the callback on runtime (won't appear in the inspector)
_interactable.OnClick.AddListener(DestroyObject);
}
private void DestroyObject()
{
// destroy the object of the interactable if no target was provided
if(!_targetToDestroy) _targetToDestroy = _interactable.gameObject;
Destroy(_targetToDestroy);
}
}
I have four GameObjects in the game I am making and when I click on each one a dialogue box opens.
My problem is that I am using OnMouseDown and the first one always need to be clicked twice. It happens just on the OnMouseDown, I have buttons on the game that work just fine.
public static GameObject selectedClient;
public bool isBuying;
private Manager manager;
private void Start()
{
manager = GameObject.FindObjectOfType(typeof(Manager)) as Manager;
}
private void OnMouseDown()
{
if (isBuying == true)
{
selectedClient = this.gameObject;
manager.Talk();
}
else if (isBuying == false)
{
manager.NotTalk();
}
}
The Talk() and NotTalk() are as follows:
public void Talk()
{
dialogueBox.SetActive(true);
Time.timeScale = 0f;
actualClient = Client.selectedClient;
}
public void NotTalk()
{
dialogueBox.SetActive(false);
Time.timeScale = 1f;
}
Someone knows why this happens?
Thanks in advance.
Assuming manager.Talk() opens the dialog, perhaps isBuying is false initially, and is toggled when you click once?
Edit: User updated question with Talk and NotTalk methods.
Since your say that initially, only the time stops, but the dialogueBox doesn't show, by any chance, is this because it isn't populated, or correctly initialized? Can you show is code of what your expect to show up?
It may just be that dialogueBox has nothing to display, and therefore, doesn't, however, by the second click, it somehow it's correctly populated and can display.
If I understand correctly, it seems that OnMouseDown() and Talk() is being called successfully on the first mouse click, but a second mouse click is required to get the dialogueBox to show.
If dialogueBox.SetActive(true) is being called successfully, you could take a look at the Unity Scene Hierarchy window to see if it became active like you expect after the first mouse click. If it did, then you can examine that object to see why it's not appearing on screen. (As another poster mentioned, it may be related to dialogueBox initialization.)
Also, these questions might help us debug and figure out the issue:
What error do you get when you "click on one object and then on other"?
What happens if you click the buttons in a different order? If there are 4 buttons, is it the first button that is always affected, or the first button that you click?
In general, as other posters have suggested, using Debug.Log and Debug.Assert should help you narrow down the issue. Similarly, you can set breakpoints in the code and step through to see if the code is running like you expect. And as I mentioned in this post, the Unity Scene Hierarchy window is useful for debugging as well.
Add a Debug.log(isBuying); above (isBuying == true).
Then you'll know if the OnMouseDown() is being called in the first place and if it proceeds like you expect it to. After that, you should probably be able to fix it yourself, otherwise, please let me know what you found.
I'm creating custom layout group and I want to control RectTransform on the child Objects. I want to lock some fields on child's RectTransform like when using canvas or Unity's Horizontal or Vertical group so that it cannot be modified.
I need the same effect. You can see this message on top of child's RectTransform : Some values driven by HorizontalLayoutGroup
I find a halfway :
Adding [ExecuteInEditMode] then:
public void Update()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
/* Todo => update child's positions here. */
}
#endif
}
Any other idea?
This is done with the DrivenRectTransformTracker API.
From the doc:
Driving a RectTransform means that the values of the driven
RectTransform are controlled by that component. These driven values
cannot be edited in the Inspector (they are shown as disabled). They
also won't be saved when saving a scene, which prevents undesired
scene file changes.
Whenever the component is changing values of driven RectTransforms, it
should first call the Clear method and then use the Add method to add
all RectTransforms it is driving. The Clear method should also be
called in the OnDisable callback of the component.
No example from the doc but below is how to use it:
public RectTransform targetRC;
UnityEngine.Object driver;
void Start()
{
DrivenRectTransformTracker dt = new DrivenRectTransformTracker();
dt.Clear();
//Object to drive the transform
driver = this;
dt.Add(driver, targetRC, DrivenTransformProperties.All);
}
The RectTransform linked to the targetRC variable will now be locked and cannot be modified from the Editor. It should now say something like "Some values are driven by another object". You can use DrivenTransformProperties to specify which variables to lock.
This is what it looks like after executing this code:
In my unity game I have two toggle buttons that are both in a toggle group together. They are buttons that are labeled "On" and "Off" for turning the game music on and off.
The way I have it set up right now makes it behave very strange. If the music is on and I click the "Off" toggle, the music turns off. Then if I hit "On" again, I get a null object reference error and the check mark doesn't show up in the "On" toggle button until I hit "On" a second time and then the sound comes back on. The really weird part is that when it turns back on, a gameobject is created for the musicplayer, of course. When I try to turn it off again, the music stays on and a second musicplayer gameobject is created. I don't understand what is going on.
void Start ()
{
checkWhatsOn();
}
void checkWhatsOn()
{
bool sound = PlayerPrefs.GetInt("Sound Playing", 1) == 1;
//if (sound) soundToggle.isOn = true; //THESE TWO STATEMENTS
//else soundToggle.isOn = false; //ARE CAUSING THE ISSUE!!
}
public void switchSound()
{
print (string.Format("In switch method sound is {0}", PlayerPrefs.GetInt("Sound Playing", 6)));
bool sound = PlayerPrefs.GetInt("Sound Playing", 1) == 1;
if (sound)
{
if (GameObject.FindObjectOfType<MusicPlayer>() != null)
{
PlayerPrefs.SetInt("Sound Playing", 0);
PlayerPrefs.Save();
GameObject.FindObjectOfType<MusicPlayer>().GetComponent<MusicPlayer>().Disable();
}
else print ("Sound wasn't changed, MusicPlayer needs to be null.");
}
else if (!sound)
{
PlayerPrefs.SetInt("Sound Playing", 1);
PlayerPrefs.Save();
if (GameObject.FindObjectOfType<MusicPlayer>() == null)
{
musicPlayer = Instantiate (Resources.Load ("MusicPlayer")) as GameObject;
GameObject.DontDestroyOnLoad(musicPlayer);
}
else print ("Sound wasn't changed, MusicPlayer shouldn't be null.");
}
print (string.Format("After switch method sound is {0}", PlayerPrefs.GetInt("Sound Playing", 7)));
}
In the inspector I have the "On" button call the function above while passing in a 1. When "Off" pressed, it calls the same function with a 0.
9/2/14
I have updated my code using only one toggle button. The toggle button calls a method which checks the PlayerPrefs to see whether the sound should be on or not. I still end up with an issue when I move from one scene into the scene that has the toggle button in it. When I do that, the music stops. It is for some reason calling the method that should only be called when the toggle button is pressed. Any ideas?
9/4/15
After testing what Thaina had told me (code updated above), I narrowed my issue down to the fact that if I try to set my toggle button to on, it automatically calls the function that is attached to the toggle. I only want to have the function called if it is pressed, not when setting it's saved state. Is there a way to do this?
SOLUTION
I ended up just letting the toggle.isOn call the function that it was trying to access and used a static bool to only let it access certain code when I wanted it to. Thaina's answer is what got me far enough to get to that point so credit goes to Thaina.
I suggest you should use GameObject.FindObjectOfType<MusicPlayer>(). So you can be sure that it will get MusicPlayer in the scene
I suspect that your MusicPlayer object is actually named "MusicPlayer " not "MusicPlayer". Anyway get object by its name is bad idea in my opinion. It prone to error
I've been struggling with what appears to be a simple task for the past few hours. I have been successfully able to turn a GameObject's guiTexture on an off using GameObject.guiTexture.enabled as I have read in other similar questions. I do this in a script that is attached to the GameObject I wish to toggle.
The problem arises when I try to preform this same command from another script that is attached to an empty game object in my scene. When I interact with the button, simply nothing happens.
To give this some context, I am trying to create functionality to switch menus on the screen. When a user taps a certain UI button, I want to call unloadMenu() so I can wipe everything off the screen and draw the textures that belong to the appropriate menu.
//When the user lifts their finger
void OnTouchEnded ()
{
switch (this.gameObject.name)
{
//If they have selected the quiz button
case "QuizButton":
//this.guiTexture.enabled = false;
//Call the unloadMenu function which will clear the GUITextures
menuMgr.unloadMenu();
break;
The commented out section is what works fine. But now, I wish to perform this code in a function that is located in another script - menuMgr.unloadMenu()
This is what the MenuManager script looks like:
public GameObject quizButton;
void unloadMenu()
{
quizButton.guiTexture.enabled = false;
}
I have ensured to drag the quizButton gameobject from my scene into the inspector and connect it properly with the variable I have created yet nothing happens when this function is called. Does anyone have any idea why? Thanks in advanced.
How you declare MenuManager creates a new script while the reference to quizButton is in your MenuManager GameObject. That is why your menuMgr.UnloadMenu didn't do anything.
I have created something similar to yours and I found it worked fine :
Quizbutton Script:
public GameObject menuMgr; // reference to the empty game object (menu manager)
void OnMouseDown() // In your case, this is OnTouchEnded
{
// get the script of menu manager here
MenuMgrScript menuscript = menuMgr.GetComponent<MenuMgrScript>();
// and execute the function you want
menuscript.UnloadMenu();
}
Menu Manager Script:
// this script is exactly the same as yours, nothing's wrong here
// oh except add public to function UnloadMenu, so it can be called
// in the quizbutton script
public GameObject quizButton;
public void UnloadMenu() {
quizButton.guiTexture.enabled = false;
}