im having issues with admob for unity, I got the ads working and displaying after a player dies in the game, however if you die very quickly many times in a row the game crashes and I suspect it has to do with requesting ads to fast.
Requesting the ads:
private const string AD_UNIT_ID = "hidden_for_privacy";
private AdMobPlugin admob;
void Start () {
admob = GetComponent<AdMobPlugin> ();
admob.CreateBanner (AD_UNIT_ID, AdMobPlugin.AdSize.SMART_BANNER, true);
admob.RequestAd ();
admob.HideBanner ();
print ("loaded");
}
If you die, ads are shown via
public void showAds(){ print ("showing ads"); admob.ShowBanner(); }
and a gui comes up, when you click the button the level reloads and so does the entire script and start function and thus another request gets made.
void OnGUI() {
if (show) {
GUI.Box (new Rect (0, 0, Screen.width, Screen.height), "");
if (GUI.Button(new Rect(100, 150, 600, 300), "Play again")){
Application.LoadLevel("level1");
show = false;
hideAds(); }
}
Problem being that everytime the player dies this start function gets called over and over (and as i stated earlier the games slows down and crashes if this is done to rapidly), surely I should somehow be able to only request the ad once per "session" and then just hide/show the ads as i please during that session. It seems heavy to request ads so frequently.
Regards,
Emil
Take full control of your ads. Please don't request on every start. To do that you can use DontDestroyOnLoad(). It will not be destroyed and start again when your scene changes. Also check for any duplicates. Long story short-
private static bool created = false;
.....
void Start () {
admob = GetComponent<AdMobPlugin> ();
admob.CreateBanner (AD_UNIT_ID, AdMobPlugin.AdSize.SMART_BANNER, true);
admob.RequestAd ();
admob.HideBanner ();
print ("loaded");
}
void Awake(){
if(!created){
DontDestroyOnLoad(gameObject);
created = true;
} else {
Destroy(gameObject);
}
}
Use a timer function (your session), so that after a basic period of time, if the player die, you show the ads by your code. And don't request the ads if the player die earlier. Hope it helps.
Related
I have a simple goal for my Unity application running on Android: create a function, which disables my GUI, creates a screenshot, stores the image and enables the GUI again.
This is my current code:
The whole UI is stored in a GameObject which my handler class holds as property:
private bool makeScreenshotFlag;
public GameObject UserInterface;
makeScreenshotFlag above is used in the Update function:
// Update is called once per frame
void Update()
{
if (makeScreenshotFlag)
{
// Working with this flag is necessary,
// since we need to wait for the next frame,
// where the gui is not visible;
MakeScreenShot();
}
}
If the corresponding button gets pressed I fire the following Method:
public void OnCreateScreenshotButtonPressed()
{
UserInterface.SetActive(false);
makeScreenshotFlag = true;
}
And at last the method for the screenshot itself:
private void MakeScreenShot()
{
if (UserInterface.activeSelf) return; // wait for the next frame if the gui is still active
try
{
string filename = "screenshot_" + DateTime.Now.ToString("HH-mm-ss--dd-MM-yyyy") + ".png";
ScreenCapture.CaptureScreenshot(filename);
}
catch (Exception e)
{
DebugHelper.NewLog = "Error capturing screenshot: " + e.Message;
}
finally
{
makeScreenshotFlag = false;
UserInterface.SetActive(true);
}
}
In theory this should work, however the documentation for ScreenCapture.CaptureScreenshot() states the following:
The CaptureScreenshot returns immediately on Android. The screen capture continues in the background. The resulting screen shot is saved in the file system after a few seconds.
In practice this means, when my screenshot is made, the GUI is already enabled again. So far I couldn't find any event or similar to get notified as soon as the screenshot is made. The only thing I can think of is to store the screenshot filename and check if the file exists each frame after the screenshot is started.
Is there any other, more practical way?
Most probably, you are capturing the frame with UI itself. It's better to wait till the end of the frame using Coroutine.
public IEnumerator MakeScreenShot()
{
// Wait till the last possible moment before screen rendering to hide the UI
yield return null;
// Disable UI
UserInterface.SetActive(false);
// Wait for screen rendering to complete
yield return new WaitForEndOfFrame();
// Take screenshot
Application.CaptureScreenshot("screenshot.png");
// Show UI after we're done
UserInterface.SetActive(true);
}
I have a really simple script where I have a video start playing in Unity on start, and then pause at a specific time in the movie:
public class PlayVideoScript : MonoBehaviour
{
public UnityEngine.Video.VideoPlayer videoPlayer;
// Start is called before the first frame update
void Start()
{
// Will attach a VideoPlayer to the main camera.
GameObject camera = GameObject.Find("Main Camera");
// VideoPlayer automatically targets the camera backplane when it is added
// to a camera object, no need to change videoPlayer.targetCamera.
videoPlayer = camera.AddComponent<UnityEngine.Video.VideoPlayer>();
// Play on awake defaults to true. Set it to false to avoid the url set
// below to auto-start playback since we're in Start().
videoPlayer.playOnAwake = false;
// By default, VideoPlayers added to a camera will use the far plane.
// Let's target the near plane instead.
videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
// This will cause our Scene to be visible through the video being played.
videoPlayer.targetCameraAlpha = 0.5F;
// Set the video to play. URL supports local absolute or relative paths.
// Here, using absolute.
videoPlayer.url = "Assets/Movie.mp4";
// Skip the first 100 frames.
videoPlayer.frame = 100;
// Restart from beginning when done.
videoPlayer.isLooping = false;
// Each time we reach the end, we slow down the playback by a factor of 10.
//videoPlayer.loopPointReached += EndReached;
// Start playback. This means the VideoPlayer may have to prepare (reserve
// resources, pre-load a few frames, etc.). To better control the delays
// associated with this preparation one can use videoPlayer.Prepare() along with
// its prepareCompleted event.
videoPlayer.Play();
}
// Update is called once per frame
void Update()
{
print(videoPlayer.time);
print(videoPlayer.time);
if (videoPlayer.time == 15.0) {
print("paused;");
videoPlayer.Pause();
}
}
}
I can verify that I've reached the time I want in the Update function, but the videoPlayer doesn't pause at all. I'm pretty new to Unity, so any help appreciated!
In your Update method, you check if the video reached exactly 15s.
The thing is, from one frame to another, you may go further than 15 and so never equal 15.
I will suggest you to do as the following :
void Update()
{
if (videoPlayer.time >= 15.0) {
print("paused;");
videoPlayer.Pause();
}
}
I'm stuck on the last test for my app before submission to the Oculus store. I've tried all sorts with no avail. I need to do is pass the frames when not visible test.
Effectively, the app needs to go into pause mode when the user clicks the menu button on the oculus touch controller.
I need to stop all frames submitting from Unity. For example, things I've tried, turn off cameras, audio, ovrplayercontroller etc but frames being submitted when the menu button is pressed on the rift so it would appear to freeze the application.
I've tried disabling cameras in a foreach loop, disabling the player gameobject, ovr controllers all sorts.
I have a gameobject with a script attached to try and detect when the test will fire based on the HMD losing tracking.
Here's where I'm currently at (gone back to the basics again), any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HMDCheck : MonoBehaviour
{
public GameObject OVRCameraRig;
private void Update()
{
if (!OVRManager.isHmdPresent)
{
OVRCameraRig.SetActive(false);
Time.timeScale = 0f;
}
else
{
OVRCameraRig.SetActive(true);
Time.timeScale = 1f;
}
}
}
Additionally their docs say the test performs this action:
TestSubmitFramesWhenNotVisible
Tests if your app stops submitting frames when the Universal Menu is open.
Note :
My most recent command line response for the test is the following output :
Starting TestSubmitFramesWhenNotVisible
Waiting for the application to run for 5 seconds before testing begins...
Starting test...
Requesting the void...
Number of texture swap chains committed when visible 68
Number of texture swap chains committed when not visible 4
ERROR: Committed a texture swap chain (called ovr_CommitTextureSwapChain) when application not visible
Please refer to VRC Guidelines:
https://developer.oculus.com/distribute/latest/concepts/vrc-pc-input-1/
Cleaning up...
Test FAILED
To get around it, I created a script with public gameobjects. I then dragged my player into the slots inside Unity but left the camera on the scene alone. Here's a screenshot and the code. I initially added the camera to turn off frames sending but Oculus rejected it as it froze in the background upon pressing the menu button.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HMDCheck : MonoBehaviour
{
public GameObject target, scripts, LocalAvatar;
private void Update()
{
if (!OVRManager.hasVrFocus || !OVRManager.isHmdPresent || !OVRManager.hasInputFocus)
{
//target.SetActive(false);
scripts.SetActive(false);
LocalAvatar.SetActive(false);
Time.timeScale = 0f;
AudioListener.pause = true;
}
else
{
//target.SetActive(true);
scripts.SetActive(true);
LocalAvatar.SetActive(true);
Time.timeScale = 1f;
AudioListener.pause = false;
}
}
}
I have almost the same code, but this detects the Universal Menu correctly and does freeze the output, but it still won't pass the test. I think it may pass if you disable splash screens, but can't know since I have the free version of Unity.
Edit: I saw your answer Diego, but cannot comment. Did your action resolve your original question? And what license do you have for Unity?
Camera cam;
bool bPause = false;
void Update()
{
//install 'Oculus Integration' for this to work
bool bPauseNow = !(OVRManager.hasInputFocus && OVRManager.hasVrFocus);
//pause state change
if (Camera.main != null) cam = Camera.main;
if (bPause != bPauseNow)
{
bPause = bPauseNow;
if (bPauseNow)
{
Time.timeScale = 0.0f; //stops FixedUpdate
//Update keeps running, but
// rendering must also be paused to pass vrc
cam.enabled = false;
}
else
{
Time.timeScale = 1.0f;
//
cam.enabled = true;
}
}
//...
}
I am using the "Oculus XR Plugin", and got this issue,
but I found that the results of the "VRC Validator" are not so accurate,
then I submitted the App for review and passed the test.
I made a demo application with two simple view in unity3d for windows phone platform.On first view I have a button and a text, from inspector I assign to button one event ( on Click) to open second view. In this view I have a raw image in a panel used to assign mainTexture to webCamTexture for to Start camera on phone.
var webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
In second View I have a button where I close camera and show first view ( closing current) webCameraTexture.Stop();
If I do that many times Play() and Stop() memory on my phone looks like:
How can I clear memory, when I stop the camera, because sometimes give me an error "Not enought storage to complete this operation" and exit from application.
Code Start Stop Camera:
//call onClick Button (next)
public void StartMyCamera()
{
webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
}
//call onClick btn (back - close camera)
public void StopMyCamera()
{
//to stop camera need only this line
webCamTexture.Stop();
//----try to clear
/*GL.Clear(false, true, Color.clear);
GC.Collect();
GC.WaitForPendingFinalizers();
rawImage.StopAllCoroutines();*/
//----
}
Currently you play the video with:
var webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
webCamTexture.Play();
and stop it with
webCameraTexture.Stop();
This is doing exactly what your code is telling it to do. The new WebCamTexture() line of code is expected to allocate memory each time it is called. You are suppose to do this only once in the Start() function and then you can play and stop camera without memory allocation.
public RawImage rawImage;
WebCamTexture webCamTexture;
void Start()
{
intCam(); //Do this once. Only once
}
void intCam()
{
webCamTexture = new WebCamTexture();
rawImage.material.mainTexture = webCamTexture;
}
public void StartMyCamera()
{
webCamTexture.Play();
}
public void StopMyCamera()
{
//to stop camera need only this line
webCamTexture.Stop();
}
"Resources.UnloadUnusedAssets()" is helpful for your problem.
public void StopMyCamera()
{
webCamTexture.Stop();
Resources.UnloadUnusedAssets();
}
Ive been having some issues programming in unity with c#. I am trying to request an interstitial AD when i start the game so i can show it when the player has died 5 times. The issue is that when i get to the 5th death the ad won't show. and when I try requesting the ad when the level starts it gets laggy and still doesn't show.
This is my code. It seems right.
void Update(){
if (clicks >= 5) {
RequestInterstitial();
Debug.Log("Got 5 clicks");
if (interstitial.IsLoaded()){
Debug.Log("interstitial loaded");
interstitial.Show();
clicks = 0;
}
}
}
EDIT: After modifying my code, I now get the error:
NullReferenceException: Object reference not set to an instance of an object ADS.ADMobsGameplay.Update () (at Assets/Scripts/ADS/ADMobsGameplay.cs:28)
Line 28 corresponds to if (interstitial.IsLoaded()){ in the following code:
void Update(){
if (clicks >= 5) {
Debug.Log("Got 5 clicks");
if (interstitial.IsLoaded()){
Debug.Log("interstitial loaded");
interstitial.Show();
clicks = 0;
}else{
RequestInterstitial();
}
}
}
You are Requesting the Interstitial over and over again. Just run the RequestInterstitial method at the beginning of the program (and make sure it only runs the method once).
Then, in whatever method you increment clicks, simply add something like this to the end:
int clicksRequired = 5;
int currentClicksRequired = 5;
if(clicks > currentClicksRequired){
Debug.Log("Got 5 Clicks");
if (interstitial.IsLoaded()){
Debug.Log("interstitial loaded");
interstitial.Show();
RequestInterstitial();
clicks = 0;
currentClicksRequired = clicksRequired;
}else{
Debug.Log("interstitial not loaded, skipping to next click");
currentClickRequired ++;
}
}
Once clicks reaches 5, it will check if the interstitial has been loaded. If so, it shows the interstitial, requests another interstitial, resets clicks at 0, and then moves on. If the interstitial is not loaded yet, it makes you wait till the 6th click, or the 7th, etc, until the interstitial is loaded.
First of all, you shown NullReferenceException error in yours comment: this is first issue that can provide lags. Second - it is really weird to put some counting logic into Update function - update works every frame - so it`s second possible lag issue. Third Debug.Log function is not a lightweight, into Update function it will be third possible lag issue