I'm buidling a smooth transtion from a level scene to a menu scene.
The idea is to make a screenshot of the level just before the next scene(menu) loads.
then take this screenshot which overlays the entire screen and will fade out to reveal the menu.
At the end of a level I take a screen shot.
ScreenCapture.CaptureScreenshot("Resources/DestroyedBoss.png");
When I load the next scene this screenshot should load and overlay the entire scene.
public Texture2D myTexture;
void Start()
{
// load texture from resource folder
myTexture = Resources.Load("DestroyedBoss") as Texture2D;
GameObject rawImage = GameObject.Find("RawImage");
rawImage.GetComponent<RawImage>().texture = myTexture;
}
The screenshot will fade and the object containing it will be destroyed.
public RawImage imageToFade;
void Update()
{
imageToFade.color -= new Color(0, 0, 0, 0.2f * Time.deltaTime);
if (imageToFade.color.a < 0.1)
Destroy(this.gameObject);
}
This all works fine, except for loading of the screenshot itself.
It would seem that unity does not update the image while running the game. And always uses the screenshot from the previous time I ran the game.
I have been searching/googling and trying for 2 days now and I am at a loss.
How can I make this work? Is there a way to update the png file while running my game? Maybe create a temp container for the screenshot and set this to the RawImage?
Like derHugo commented. you can use Application.persistentDataPath to save your image.
ScreenCapture.CaptureScreenshot(Application.persistentDataPath+"DestroyedBoss.png");
For loading the image, you can use UnityWebRequestTexture.GetTexture.
IEnumerator SetImage()
{
yield return new WaitForSeconds(1);
using (UnityWebRequest uwr =
UnityWebRequestTexture.GetTexture(Application.persistentDataPath + "DestroyedBoss.png"))
{
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
// Get downloaded asset bundle
myTexture = DownloadHandlerTexture.GetContent(uwr);
GameObject rawImage = GameObject.Find("RawImage");
rawImage.GetComponent<RawImage>().texture = myTexture;
FadeOut.instance.StartFade();
}
}
}
It works ok, but it takes a few seconds for the screenshot to appear in the folder. So for me... it does not work great.
I'll be using another technique.
Instead of fading the screenshot while loading the menu. I'll stop the game, (Time.timescale = 0) and fade in a screenshot of the menu, then load the actual menu scene.
Thanks again derHugo.
Related
Is there a way to activate a fade animation every time the game changes from one scene to the other, without the user doing somthing specific like hiting a pre-determined key?
Basically the transtions needs to start just because there is a change in scenes.
I have a bunch of scenes and i need to add a fade to black transition between them.
All tutorials i found need some specific key input or something happening while i only have a few videos with no possible interaction with the user (in most cases).
Just in case that's not possible (or inpractical for rookies) I guess i could hook up the animations to the user pushing buttons that send you to other scenes (could use help with that aswell). And the first scene could work with a timer/delay.
*Unity and visual studio update to latest stable builds.
So every time you need to change scene you actually need to first fade-out your screen, then run scene change and after new scene is loaded - fade screen in. You can do it like that:
1) Create new Canvas object in start scene of your project. Set canvas mode to "Screen Space - Overlay" and make sure Sort Order is set high enough so your canvas will be on top always.
new Canvas object
2) Create an empty Image on this Canvas and size it so it covers all the scree. Set Color to transparent. Dont forget to toggle "Raycast Target" of image off (or you won't be able to mouseclick through it)
new Image object
3) Add this script to your Canvas object:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SceneChanger : MonoBehaviour
{
enum FadeStatus
{
fading_id,
fading_out,
none
}
public static SceneChanger Instance;
public Image fadeImage;
public float fadeDuration;
private FadeStatus currentFadeStatus = FadeStatus.none;
private float fadeTimer;
private string sceneToLoad;
void Start()
{
if (Instance == null)
{
Instance = this;
SceneManager.sceneLoaded += OnSceneLoaded;
}
else
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//scene loaded, running fade-in
currentFadeStatus = FadeStatus.fading_id;
}
public void ChangeScene(string _name)
{
sceneToLoad = _name;
currentFadeStatus = FadeStatus.fading_out;
}
void Update()
{
if(currentFadeStatus != FadeStatus.none)
{
fadeTimer += Time.deltaTime;
if(fadeTimer > fadeDuration) //done fading
{
fadeTimer = 0;
if (currentFadeStatus == FadeStatus.fading_out)
{
SceneManager.LoadScene(sceneToLoad);
fadeImage.color = Color.black;
}
else
fadeImage.color = Color.clear;
currentFadeStatus = FadeStatus.none;
}
else //still fading
{
float alpha = 0;
if (currentFadeStatus == FadeStatus.fading_out)
alpha = Mathf.Lerp(0, 1, fadeTimer / fadeDuration);
else
alpha = Mathf.Lerp(1, 0, fadeTimer / fadeDuration);
fadeImage.color = new Color(0, 0,0, alpha);
}
}
}
}
4) Go back to Editor and assign your transparent Image to its field on SceneChanger script and adjust fadeDuration (time of one fade in seconds)
5) Now you can change scenes from code using
SceneChanger.Instance.ChangeScene("YourSceneName");
6) Don't forget to add all needed scenes to build settings, otherwise it won't work.
build settings
7) You DON'T need to add SceneChanger on other scenes, it will be saved between scenes due to DontDestroyOnLoad().
using UnityEngine;
public class PlayerLoad : MonoBehaviour
{
[SerializeField]
private Sprite pSprite;
private void Start()
{
LoadSprite(this.gameObject, pSprite);
}
void LoadSprite(GameObject p1, Sprite pSprite = null) // p1 = the player's gameobject
{
var sr = p1.GetComponent<SpriteRenderer>();
if (sr == null)// If no sprite renderer exist
{
sr = p1.AddComponent<SpriteRenderer>();
}
if (sr != null && !sr.enabled)// If sprite renderer exist but isn't active
{
sr.enabled = true;
}
if (sr.sprite == null)// If no sprite exist, adds one
{
p1.GetComponent<SpriteRenderer>().sprite = pSprite;
}
}
}
Ok, so I'm having an issue to where sometimes my player's sprite seems to be invisible. As of now, I can build the project onto my mobile device and everything works fine. However, when the second level is completed (Right now I only have two levels I'm using for testing) the game goes to the Death scene. Then it ask's the user to continue or quit. If continue, the player is taken to the last level reached. Code works, but the sprite is now invisible. Sometimes I can pause the game, quit and return to the main menu, click play again and start over and the player appears again. Other times it makes it worse because the bullets even fail to render. I have no clue as to what could cause such a thing. SO I have this code in hopes of forcing the sprite to render whether it wants to or not.
Here's a screenshot of the mobile screen:
To the right you can see the bullets firing but the player cannot be seen. You can tell the player is moving by the offset in the bullet trajectory. (If you look close)
I'm using Unity 2019.0.1a Beta
I am trying to have a simple animated loading screen between my menu scene and the game scene. I am trying to do this by loading the game scene in my loading scene asynchronously. I also want the loading screen to fade in and fade out.
I got the fade-in to work. However, I have two problems which I have been working on for hours, but without any succes. These problems are:
I cannot get the fade-out to work. I tried setting the 'allowSceneActivation' to false for my asynchronous loading, however this causes the loading to not occur at all. Removing this line makes the game load, but it then lacks the fade out.
The animation works very (and I mean VERY) choppy. I understand that the game is loading stuff, so I expect it to be bad, but it's litterally doing a frame every 2 seconds. I tried using a low thread priority (see code below), but no luck. I found people with similar problems, but the frames turned out reasonable when using a lower thread priority.
This is my code for the loading screen:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LoadIntro : MonoBehaviour {
private bool loaded;
private bool fadingOut;
private bool loading;
AsyncOperation async;
void Start(){
loaded = false;
fadingOut = false;
loading = false;
Application.backgroundLoadingPriority = ThreadPriority.Low;
}
// Use this for initialization
void Update() {
//wait for loading screen to fade in, then execute once
if (!GameObject.Find ("SceneFader").GetComponent<Image> ().enabled && !loaded && !loading) {
loading = true;
async = Application.LoadLevelAsync(mainMenuButtons.leveltoload);
async.allowSceneActivation = false;
StartCoroutine (LoadLevel (async));
}
//if next scene is loaded, start fading out loading screen
if (loaded) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
//when faded out, switch to new scene
if (GameObject.Find ("SceneFader").GetComponent<Image> ().color.a >= 0.95f && loaded) {
async.allowSceneActivation = true;
}
}
IEnumerator LoadLevel(AsyncOperation async){
yield return async;
Debug.Log("Loading complete");
loaded = true;
}
}
I have a seperate piece of code for the actual fading, which the code above calls:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SceneFadeInOut : MonoBehaviour
{
public float fadeSpeed = 1.5f; // Speed that the screen fades to and from black.
private bool sceneStarting = true; // Whether or not the scene is still fading in.
public bool sceneEnding = false;
public string scene;
private Image fadeTexture;
void Awake ()
{
fadeTexture = GetComponent<Image>();
}
void Update ()
{
// If the scene is starting...
if(sceneStarting)
// ... call the StartScene function.
StartScene();
if (sceneEnding)
EndScene();
}
void FadeToClear ()
{
// Lerp the colour of the texture between itself and transparent.
fadeTexture.color = Color.Lerp(fadeTexture.color, Color.clear, fadeSpeed * Time.deltaTime);
}
public void FadeToBlack ()
{
// Lerp the colour of the texture between itself and black.
fadeTexture.color = Color.Lerp(fadeTexture.color, Color.black, fadeSpeed * Time.deltaTime);
}
void StartScene ()
{
// Fade the texture to clear.
FadeToClear();
// If the texture is almost clear...
if(fadeTexture.color.a <= 0.05f)
{
// ... set the colour to clear and disable the GUITexture.
fadeTexture.color = Color.clear;
fadeTexture.enabled = false;
// The scene is no longer starting.
sceneStarting = false;
}
}
public void EndScene ()
{
// Make sure the texture is enabled.
fadeTexture.enabled = true;
// Start fading towards black.
FadeToBlack();
// If the screen is almost black...
if (fadeTexture.color.a >= 0.95f) {
// ... reload the level.
if (scene == "") Application.Quit();
else Application.LoadLevel (scene);
}
}
}
Does anyone have an idea how to solve the issues described above? I've litterally tried every topic I could find, but none of them seem to work. Building my game did not resolve the issues either.
Many thanks in advance!
You are fading out when scene loading gets done. What are you expecting when loading is done? :)
//if next scene is loaded, start fading out loading screen
if (async.isDone) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
Obviously it will change the scene and you code doesn't getting enough time to perform fade-out operation. :)
For instance if consider your point. You wrote,
//if next scene is loaded, start fading out loading screen
if (loaded) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
//when faded out, switch to new scene
if (GameObject.Find ("SceneFader").GetComponent<Image> ().color.a >= 0.95f && loaded) {
async.allowSceneActivation = true;
}
in Update. Here your loaded check doing 2 things.
1- Start fading out.
2- Switching scene.
Again, why it should wait for fading it out completely while its getting loaded and you are checking alpha >= 0.95 which should execute at first frame when you get loaded to true, because I believe that in first frame alpha would be greater than 0.95.
I'm hung up on something that I've not been able to work out and I could really use a fresh set of eyes on it. I'm loading up an array of images, assigning one of them to a texture in LoadGallery.cs. Then in LoadImage I have a button that when clicked runs LoadImg but when I click the button nothing happens. The texture doesn't get assigned to the GameObject. I'm not getting any errors either. The script works fine when it's all within the IEnumerator function, but when I pull it out into a different script I'm getting nothing. What am I getting wrong?
LoadGallery.cs
public Texture2D tex;
// Use this for initialization
void Start () {
StartCoroutine("LoadAllImages");
}
IEnumerator LoadAllImages()
{
string[] filePaths = Directory.GetFiles(#"/Users/kenmarold/Screenshots/TATUS/", "*.png");
WWW www = new WWW("file://" + filePaths[0]);
yield return www;
Texture2D tex = new Texture2D(512,512);
www.LoadImageIntoTexture(tex);
}
LoadImage.cs
void LoadImg()
{
GameObject galleryLoader = GameObject.FindGameObjectWithTag("GalleryLoader");
LoadGallery loadGallery = galleryLoader.GetComponent<LoadGallery>();
Rect rct = new Rect(0, 0, loadGallery.tex.width, loadGallery.tex.height);
Vector2 pvt = new Vector2(0.5f, 0.5f);
GameObject screenShotImg = GameObject.FindGameObjectWithTag("screenshot");
Image img = screenShotImg.GetComponent<Image>();
img.sprite = Sprite.Create(loadGallery.tex, rct, pvt);
}
I could not see what's wrong with what you are doing. These are common mistakes from my experience:
1. You might have forgotten to assign the function LoadImg to the button.
2. The size of UI object "screenshot" is too small. Try assigning some dummy image to see if it's actually showing something.
3. There could have been some exception when loading gallery. Try to check for www.error. Debug it carefully.
Good luck with your work.
I am building an application in Unity3d, and I need to download textures from my server and apply them to prefabs.
I have two types of prefabs;
The first is a simple plane that I use to display 2d images, and the second is a prefab to play videos and have a thumbnail texture that is displayed before the video is played in full screen.
I am having problems with the video prefab. If I create a public texture in my script and apply it to the prefab, everything works fine. However, if I download the texture from my server and apply it to the prefab it appears black. This only happens in iOS, in the Unity Player everything appears fine.
Here is my code:
Instantiate the prefab:
newVideo = (GameObject)Instantiate(arvideo, new Vector3(15*i, 0, 0), Quaternion.identity);
newVideo.GetComponent<VideoPlaybackBehaviour>().m_path = ((Assets)Data.Assets[i]).AssetContent; // SET THE URL FOR THE VIDEO
string url = ((Assets)Data.Assets[i]).AssetThumbnail;
StartCoroutine(DownloadImage(url, newVideo, ((Assets)Data.Assets[i]).AssetFilename, "VIDEO"));
newVideo.transform.rotation = Quaternion.Euler(0, -180, 0);
Download IEnumerator:
public IEnumerator DownloadImage(string url, GameObject tex, string filename, string type)
{
WWW www = new WWW(url);
yield return www;
/* EDIT: */
if (!string.IsNullOrEmpty(www.error)){
Debug.LogWarning("LOCAL FILE ERROR: "+www.error);
} else if(www.texture == null) {
Debug.LogWarning("LOCAL FILE ERROR: TEXTURE NULL");
} else {
/* EOF EDIT */
tex.GetComponent<VideoPlaybackBehaviour>().KeyframeTexture = www.texture;
Color color = tex.renderer.material.color;
color.a = 1f;
tex.renderer.material.color = color;
}
}
I struggled with same issue. And after several hours search, for my case i solved this problem with disabling "Metal write-only BackBuffer" in iOS player settings. I'm using unity 2020.1.8f1 and actually i have no any idea about why back buffer setting is causing black texture problem in iOS devices.