Reload GameScene without reloading UIScene in Unity3d - unity3d

I have 2 scenes "GamePlay" and "GameUI".
I load GameUI additively with GamePlay
void Awake () {
if (!instance) {
instance = this;
} else {
Destroy(this.gameObject) ;
}
SceneManager.LoadScene ("GameUI", LoadSceneMode.Additive);
DontDestroyOnLoad(this.gameObject);
}
Now when I reload the "GamePlay" scene using
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
How can I prevent reloading "GameUI" scene?

You could add an MonoBehaviour that is attached to the GameUI which contains a static bool that indicates if the object exists. Make your whole UI Scene a child of one object with the following script.
public class UIExistance : MonoBehaviour
{
public static bool Exists { get; private set; }
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
UIExistance.Exists = true;
}
void OnDestroy()
{
UIExistance.Exists = false;
}
}
When you are in your posted Awake method you can check with if(!UIExistance.Exists) whether the UI is already in the scene.

Related

How to reset back position of a dragging object, if the dragging object dont met IDropHandler script containing object

In Unity i am using IBeginDragHandler, IDragHandler, IEndDragHandler to drag and drop object. it's working fine. My need is to reset the position of the draggable object to the starting position if it doesn't touch another object that contains IDropHandler. below is my code
Drag script:-
using UnityEngine.EventSystems;
public class Compiler_Drag : MonoBehaviour, IPointerDownHandler, IBeginDragHandler, IEndDragHandler, IDragHandler
{
[SerializeField] private Canvas canvas;
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
Vector3 myPosition;
// Start is called before the first frame update
void Start()
{
myPosition = this.gameObject.transform.position;
}
private void Awake()
{
rectTransform =GetComponent<RectTransform>();
canvasGroup = GetComponent<CanvasGroup>();
}
// Update is called once per frame
void Update()
{
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("OnBeginDrag");
canvasGroup.alpha = .6f;
canvasGroup.blocksRaycasts = false;
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("OnDrag");
rectTransform.anchoredPosition +=eventData.delta/ canvas.scaleFactor;
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("OnEndDrag");
canvasGroup.alpha = 1f;
canvasGroup.blocksRaycasts = true;
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("OnPointerDown");
}
}
> Drop object script:-
using UnityEngine.EventSystems;
public class Compiler_Drop_Handler : MonoBehaviour, IDropHandler
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnDrop(PointerEventData eventData)
{
Debug.Log("OnDrop");
if(eventData.pointerDrag !=null)
{
eventData.pointerDrag.GetComponent<RectTransform>().anchoredPosition = GetComponent<RectTransform>().anchoredPosition;
}
}
}
what I need is that I should be only able to drop the dragging object, to the object that contains/is attached to the second script.

Loading a scene

I have a "Start Game" button
public static bool GameIsStart;
public void changeCamera ()
{
if (GameIsStart == true)
return;
GameIsStart = true;
SceneManager.LoadScene ("Game");
}
}
``
There is a script that I added to the Prefabs
public GameObject [] gameobject;
private bool gameobject_IS_Spawn;
private float RandomPositionforX;
private int RandomObjects;
private void Update ()
{
if (StartGame.GameIsStart &&! gameobject_IS_Spawn)
{
StartCoroutine (Spawngameobject ());
gameobject_IS_Spawn = true;
}
}
IEnumerator Spawngameobject ()
{
while (true)
{
if (StartGame.GameIsStart)
{
yield return new WaitForSeconds (1.3f);
RandomPositionforX = Random.Range (-2.28f, 2.28f);
RandomObjects = Random.Range (0, gameobject.Length);
Instantiate (gameobject [RandomObjects], new Vector2 (RandomPositionforX, 24f), Quaternion.identity);
}
}
}
}
There is a button on the "Game" scene to access the preview
public void ChangeScene ()
{
SceneManager.LoadScene ("preview");
}
}
I click on the button, the "Preview" scene is loaded, but the "Start game" button does not work.
If I put in the "Preview" button SceneManager.LoadScene ("Game")
then I restart the scene ("Game") and everything works.
But if SceneManager.LoadScene ("Preview") but the buttons don't work.
When switching between scenes, is it necessary to stop Coroutine
How can this problem be corrected?
Without seeing the code it's a bit harder to find where the problem is coming from.
The only thing that is coming to my mind is that it may be something related with how the scene is stored and loaded after.
According to the Scene Manager Documentation, you could save the scene1 in a variable and keep the DontDestroyOnLoad(scene1) on its awake method, then add something like:
Scene scene2 = SceneManager.GetActiveScene(); SceneManager.LoadScene(scene1); To the button that reloads the previous scene.

Can't find GameObject in new scene in DontDestroyOnLoad

I have a GameController in Scene1 and I made it DontDestroyOnLoad.
When I loaded Scene2, I'm trying to find a GameObject in Scene2 and the thing is obj2 is null but obj1 is not.
Why?
How could I find the GameObjectInScene2?
public class GameController: MonoBehaviour
{
private void Awake()
{
DontDestroyOnLoad(this);
}
private void Start()
{
SceneManager.LoadScene("Scene2");
GameObject obj1 = GameObject.Find("GameObjectInScene1");
GameObject obj2 = GameObject.Find("GameObjectInScene2");
}
}
Start is not called again since your component already ran it in Scene1
You can register to SceneManager.sceneLoaded and do the find in the callback instead.
I would also store the references global like
private GameObject obj1;
private GameObject obj2;
void Start()
{
// This first line just makes sure the listener isn't added twice
SceneManager.sceneLoaded -= OnSceneLoaded;
// Whenever a scene is loaded call OnSceneLoaded
SceneManager.sceneLoaded += OnSceneLoaded;
obj1 = GameObject.Find("GameObjectInScene1");
SceneManager.LoadScene("Scene2");
}
void OnDestroy ()
{
// Always clean up listeners when not needed anymore!
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if(scene.name == "Scene2")
{
obj2 = Find("GameObjectInScene2");
}
}

Mute button does not work when I switch the scenes

AudioManager and sound effects are working just fine at the beginning of scene, however it does not work when i switch the scenes. Or even with the same scene.
I would be grateful if you could help with that and PlayerPrefs issue. I have been searching all around the forum about PlayerPrefs but i could not be sure about what to type.
Thank you very much.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using System;
public class AudioManager : MonoBehaviour {
bool mutebutton = false;
public Sound[] sounds;
public static AudioManager instance;
// Use this for initialization
void Awake () {
if (instance == null)
instance = this;
else
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
foreach (Sound s in sounds)
{
s.source = gameObject.AddComponent<AudioSource>();
s.source.clip = s.clip;
s.source.volume = s.volume;
}
}
void Start()
{
Play("Theme");
PlayerPrefs.SetFloat("volume", AudioListener.volume);
PlayerPrefs.Save();
}
// Update is called once per frame
public void Play (string name)
{
Sound s = Array.Find(sounds, sound => sound.name == name);
s.source.Play();
}
public void Mute()
{
if (!mutebutton)
{
mutebutton = true;
AudioListener.volume = 0;
}
else
{
mutebutton = false;
AudioListener.volume = 1;
}
}
}
If you only miss "Theme" sound on scene load:
Start() method won't be called again on scene load.
You have to actively call Play("Theme") after loading a scene.

Preserving object after a reload scene

In a scene of my quiz game I have an animation object that changes for another animation when a button to move to the next question is pressed (the button reload the scene). I would like to keep the animation, the last animation referenced to the object, after the scene is reloaded, but I don't know how. The object always returns to its normal state (the first animation).
I currently have a script called 'tower' referenced to the object where I make a static object and a DontDestroyOnLoad function:
public static SpriteRenderer towerAnimation;
void Awake()
{
DontDestroyOnLoad(gameObject);
towerAnimation = GetComponent<SpriteRenderer>();
}
And this code in the Update of 'GameManager' script:
public static int counterQuestionChances = 2;
void DestroyTower()
{
if (counterQuestionChances == 1)
{
Tower.towerAnimation.SetTrigger("error 1");
}
else
{
if (counterQuestionChances == 0)
{
Tower.towerAnimation.SetTrigger("error 2");
}
}
But it doesn't work. I'm taking shots in the dark because I don't know how to solve this. I'd appreciate if you could give me any ideas that can help me with this. Thanks!
You're going to have to use the SceneManagement library that Unity has so when the scene changes the method below called OnActiveSceneChanged gets called.
using UnityEngine.SceneManagement;
public class Tower : MonoBehaviour
{
public static SpriteRenderer towerAnimation;
public int storedCounter = 0;
void Awake()
{
DontDestroyOnLoad(gameObject);
towerAnimation = GetComponent<SpriteRenderer>();
SceneManager.activeSceneChanged += OnActiveSceneChanged;
}
private void OnActiveSceneChanged(UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.Scene currentScene)
{
//tower animation stuff here
}
}