I'm trying to load a new scene after clicking on the GUI.Button, and is working, but i want the level to load after a certain amount of time has passed, and my code is not working, what should i change or add to the script?
void OnGUI () {
GUI.skin = zenzaiSkin;
if(GUI.Button(new Rect((Screen.width/2-185),560,370,80), "START")) {
loadLevel1 = true;
audio.Play ();
}
}
public IEnumerator loadLevel() {
if(loadLevel1 = true){
yield return new WaitForSeconds(secondsWaiting);
Application.LoadLevel(1);
}
}
Thanks in advance
well did you call the function ? i can't see the call... just add
StartCoroutine(loadLevel());
under audio.play
so your code should look like something like this
void OnGUI () {
GUI.skin = zenzaiSkin;
if(GUI.Button(new Rect((Screen.width/2-185),560,370,80), "START")) {
loadLevel1 = true;
audio.Play ();
StartCoroutine(loadLevel());
}
}
Related
Im fairly new to Unity and I am trying to make a Pause overlay for my game. Currently Resume does not resume the character movement half of the time. So the first time I pause the game and click resume the overlay is disabled but I will not be able to move, but if I press escape again and then Resume it works fine on the second try. One thing to note is that it works as intended if I press escape while in the pause menu and the logic is exactly the same. Here is my C# script:
public class PauseGame : MonoBehaviour
{
public GameObject Canvas;
bool pausedGame = false;
// Make sure pause screen is not active on game start
void Start()
{
Canvas.GetComponent<Canvas>().enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (pausedGame == false)
{
Time.timeScale = 0;
Canvas.GetComponent<Canvas>().enabled = true;
pausedGame = true;
}
else
{
Time.timeScale = 1;
Canvas.GetComponent<Canvas>().enabled = false;
pausedGame = false;
}
}
}
public void Resume()
{
Time.timeScale = 1;
Canvas.GetComponent<Canvas>().enabled = false;
pausedGame = false;
}
public void MainMenu()
{
SceneManager.LoadScene("MainMenu");
}
}
Let me know if I should add screenshots of my components.
Found the solution to this! For some reason the FirstPersonAIO controller did not get unpaused when I resumed the game. Where player is a public variable I added these two lines to my code and it fixed my problem:
controllerScript = player.GetComponent<FirstPersonAIO>();
controllerScript.ControllerPause();
I'm trying to animate the button while it is being gazed on. I have got the following code in which I Raycast from a sphere to find the button that it hits.
var eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = screenPosition;
var results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
foreach (var result in results)
{
Debug.Log(result.gameObject.name);
}
In order to animate the button, I'm adding the following code to the button. Unfortunately, the OnPointerEnter or ``OnPointerExit is never being called.
[RequireComponent(typeof(Button))]
public class InteractiveItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public Image progressImage;
public bool isEntered = false;
RectTransform rt;
Button _button;
float timeElapsed;
Image cursor;
float GazeActivationTime = 5;
// Use this for initialization
void Awake()
{
_button = GetComponent<Button>();
rt = GetComponent<RectTransform>();
}
void Update()
{
if (isEntered)
{
timeElapsed += Time.deltaTime;
progressImage.fillAmount = Mathf.Clamp(timeElapsed / GazeActivationTime, 0, 1);
if (timeElapsed >= GazeActivationTime)
{
timeElapsed = 0;
_button.onClick.Invoke();
progressImage.fillAmount = 0;
isEntered = false;
}
}
else
{
timeElapsed = 0;
}
}
#region IPointerEnterHandler implementation
public void OnPointerEnter(PointerEventData eventData)
{
CodelabUtils._ShowAndroidToastMessage("entered");
isEntered = true;
}
#endregion
#region IPointerExitHandler implementation
public void OnPointerExit(PointerEventData eventData)
{
CodelabUtils._ShowAndroidToastMessage("exit");
isEntered = false;
progressImage.fillAmount = 0;
}
#endregion
}
am I missing something ? or is there any other way of achieving this?
I guess your Raycast supposed to trigger the OnPointerEnter on all results.
You will need to use ExecuteEvents.Execute like e.g.
ExecuteEvents.Execute(result.gameObject, eventDataCurrentPosition, ExecuteEvents.pointerEnterHandler);
And will also at some point have to invoke pointerExitHandler.
I would therefore store a HashSet like
using System.Linq;
private HashSet<GameObject> previousEnters = new HashSet<GameObject>();
...
foreach (var result in results.Select(r => r.gameObject))
{
Debug.Log(result.name);
ExecuteEvents.Execute(result, eventDataCurrentPosition, ExecuteEvents.pointerEnterHandler);
// Store the item so you can later invoke exit on them
if(!previousEnters.Contains(result)) previousEnters.Add(result);
}
// This uses Linq in order to get only those entries from previousEnters that are not in the results
var exits = previousEnters.Except(results);
foreach(var item in exits)
{
if(item) ExecuteEvents.Execute(item, eventDataCurrentPosition, ExecuteEvents.pointerExitHandler);
}
You might actually want to implement your own custom PointerInputModule.
Alternative/Example
As a starter you could also use my answer to Using Raycast instead of Gaze Pointer from a while ago where I created a script based on Steam's VR Laserpointer which allows to interact with 3D objects and UI elements.
Note: Typed on smartphone but I hope the idea gets clear
In my Unity project I have an Empty GameObject which has 3 child GameObjects. The Empty GameObject is called Cable Strip and if the camera move to a special position, I want that the material of the three child Object start to change from white to yellow and back. Unfortunately all my solutions does not work.
This is what I have so far:
using UnityEngine
public class BlinkingObject : MonoBehaviou
{
public GameObject CableStrip;
public Material white, yellow;
public GameObject camManager; //Empty GameObject with the Main Camera
private Vector3 camPosition;
bool blinkObject;
void Update()
{
if(camManager.transform.position == camPosition)
{
InvokeRepeating("Blink", 0, 1);
}
}
public void Blink()
{
Renderer[] colorCable = CableStrip.GetComponentsInChildren<Renderer>(true);
foreach (var cableChild in colorCable)
{
if(blinkObject)
{
cableChild.material = yellow;
blinkObject = false;
} else
{
cableChild.material = white;
blinkObject = true;
}
}
}
}
How can I get my gameobject to blink in a nice way?
Edit
Sorry wrong definition of does not work. The problem is, that the color changes too fast. Even if I change the seconds by InvokeRepeating nothing changes. It still changes the color in milliseconds even if I write InvokeRepeating("Blink", 0, 10);.
Problem:
InvokeRepeating("Blink", 0, 1);
is called multiple times. So every frame the condition is fulfilled you add a new repeating invoke ... ending up with probably thousands of parallel invocations that are always repeating.
What you want to do instead is enabling the blink when the condition is fulfilled and disable it when not. I wouldn't use Invoke or InvokeReapting in this case. You can achieve it by simply using a timer:
private float timer;
private bool blinkObject;
private Renderer[] colorCable;
private void Awake()
{
// you want to do this only once!
colorCable = CableStrip.GetComponentsInChildren<Renderer>(true);
}
private void Update()
{
HandleBlink();
}
// As suggested by Cid you can ofcourse move it all to a method
// so you don't disturb other things happening in Update
private void HandleBlink()
{
// is the condition fulfilled?
var doBlink = camManager.transform.position == camPosition;
// if not do nothing
if(!doBlink) return;
// reduce the timer by time passed since last frame
timer -= Time.deltaTime;
// if timer not under 0 do nothing else
if(timer > 0) return;
// If timer exceeded invert the blinkObject flag
blinkObject = !blinkObject;
foreach (var cableChild in colorCable)
{
// Shorthand for if(blinkObject) { ... = yellow; } else { ... = white; }
cableChild.material = blinkObject ? yellow : white;
}
// and reset the timer
timer = 1f;
}
Alternatively the same thing could also be achieved by using a Coroutine which is often a bit cleaner (but that's opinions):
// flag for preventing concurrent routines
private bool isBlinking;
private Renderer[] colorCable;
private void Awake()
{
// you want to do this only once!
colorCable = CableStrip.GetComponentsInChildren<Renderer>(true);
}
private void Update()
{
// is the condition fulfilled?
if(camManager.transform.position == camPosition)
{
if(!isBlinking) StartCoroutine(BlinkRoutine());
}
else
{
StopAllCoroutines();
isBlinking = false;
}
}
private IEnumerator BlinkRoutine()
{
isBlinking = true;
var blinkObject = false;
// this looks scary but is fine in a Coroutine
// as long as you YIELD somewhere inside!
while(true)
{
blinkObject = !blinkObject;
foreach (var cableChild in colorCable)
{
// Shorthand for if(blinkObject) { ... = yellow; } else { ... = white; }
cableChild.material = blinkObject ? yellow : white;
}
yield return new WaitForSeconds(1);
}
}
I'd like to know how I can pause and unpause menu from the same button using the mouse pointer when I click on it.
Lets say I have this. C#
void Update () {
if (Button_Pause.OnPointerClick()) {
if(!active){
PauseGame();
}
else{
ResumeGame();
}
active = !active;
}
}
public void PauseGame()
{
Button_Pause = Button_Pause.GetComponent<Button> ();
Canvas_PauseMenu.enabled = true;
Button_Exit.enabled = true;
Button_Pause.enabled = true;
}
public void ResumeGame()
{
Canvas_PauseMenu.enabled = false;
Button_Exit.enabled = false;
Button_Pause.enabled = false;
}
In the first line, where I call the OnPointerClick I'm just guessing because I don't know what to do. What I've searched around, using click to show something it's having a TimeScale or something like that.
¿Can anyone help moi? Please.
Add a listener for your button and in your pause script set timescale to zero to pause the game
[SerializeField] private Button MyButton = null; // assign in the editor
void Start() { MyButton.onClick.AddListener(() => { pause();});
}
void pause(){
if (Time.timeScale == 1)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}
I managed to solve the issue. It might not be efficient but it does what I need.
I created 2 buttons in the same place. Those buttons are represented with different sprites (Pause & Play). "Pause" is visible since the start. When I click on it, the menu pops up, the "Pause" stop being active and the "Play" sprite button activates and pops up too. When I click on it, I unpause and goes back to the "Pause" sprite visible in the screen.
void Start () {
Canvas_PauseMenu = Canvas_PauseMenu.GetComponent<Canvas> ();
Button_Pause = Button_Pause.GetComponent<Button> ();
Button_Resume = Button_Resume.GetComponent<Button> ();
Canvas_PauseMenu.enabled = false;
Button_Resume.enabled = false;
Button_Resume.gameObject.SetActive (false);
}
// Update is called once per frame
public void PauseTest () {
if(!active){
PauseGame();
}
else{
ResumeGame();
}
}
public void BackToMainMenu()
{
Application.LoadLevel (0);
}
public void PauseGame()
{
Canvas_PauseMenu.enabled = true;
Button_Exit.enabled = true;
Button_Pause.enabled = false;
Button_Pause.gameObject.SetActive (false);
Button_Resume.enabled = true;
Button_Resume.gameObject.SetActive (true);
active = true;
Time.timeScale = 0;
}
public void ResumeGame()
{
Canvas_PauseMenu.enabled = false;
Button_Exit.enabled = false;
Button_Pause.enabled = true;
Button_Pause.gameObject.SetActive (true);
Button_Resume.enabled = false;
Button_Resume.gameObject.SetActive (false);
active = false;
Time.timeScale = 1;
}
I'm working on a project in Unity using C# scripting. The GUI.Box will appear at the top the screen. The box will disappear when the player leaves the spot. How can I make the box stay there for an additional 3 seconds after the player leaves the designated spot?
Danpe's code corrected (working code):
bool shown = false;
void OnGUI () {
if (car.transform.position.y>=43 && car.transform.position.y<=44)
{
shown = true;
}
else if (shown)
{
StartCoroutine(DisapearBoxAfter(3.0f));
}
if(shown)
{
GUI.Box(new Rect((Screen.width/2)-200,0,400,30) , "King of the hill");
}
}
IEnumerator DisapearBoxAfter(float waitTime) {
// suspend execution for waitTime seconds
yield return new WaitForSeconds(waitTime);
shown = false;
}
void Update () {
OnGUI ();
}
bool shown = false;
void OnGUI () {
if (car.transform.position.y>=43 && car.transform.position.y<=44)
{
shown = true;
}
else if (shown)
{
StartCoroutine(DisapearBoxAfter(3.0));
}
if(shown) {
GUI.Box(new Rect((Screen.width/2)-200,0,400,30) , "King of the hill");
}
}
IEnumerator DisapearBoxAfter(float waitTime) {
// suspend execution for waitTime seconds
return yield WaitForSeconds (waitTime);
shown = false;
}
void Update () {
OnGUI ();
}
function Start ()
{
ShowBox ();
}
function ShowBox ()
{
// show label
show = true;
// cancel invoking method if already set to call after 3 seconds
CancelInvoke("HideBox");
// will call HideBox () after 3 sec
Invoke ("HideBox", 3.0F);
}
function HideBox ()
{
// dont show label
show = false;
}
function Update ()
{
if (car.transform.position.y>=43 && car.transform.position.y<=44)
{
ShowBox ();
}
}
function OnGUI ()
{
if(shown)
{
GUI.Box(new Rect((Screen.width/2)-200,0,400,30) , "King of the hill");
}
}