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
Related
I have a joystick display picture for my game. Currently, when the player touches the screen the image disappears and when the player is not touching the screen, it reappears. I wrote that using an if else statement.
if (indicator.inputIndicator.x != 0)
{
joystick.SetActive(false);
}
else
{
joystick.SetActive(true);
}
The problem is, I want the image to reappear after some time like 2 seconds. I want to delay the "else", but I do not want to use a coroutine. I want "else" to work after 2 seconds since the player takes his hand off the screen but I couldn't figure out how to do it. any help will be great.
Setting a timer is a pretty common problem you have to solve in Unity. One basic approach is to have a variable that you add Time.deltaTime every update. That way you can tell how long it has been since some condition was met.
Every Update iteration that meets the condition, add Time.deltaTime to the variable. If at some point the condition fails, reset the variable to 0. Then you can just base your joystick.SetActive() call on the value of your variable.
For example, your script might become:
float thresholdTimeToShowPrompt = 2;
// By starting at the threshold, the image is hidden at the start until a touch
float timeSincePlayerTouch = 2;
void Update()
{
// Rather than calling SetActive directly, just update the timer
if (indicator.inputIndicator.x != 0)
{
timeSincePlayerTouch = 0;
}
else
{
timeSincePlayerTouch += Time.deltaTime;
}
// Now we can base visibility on the time since the last user touch
bool shouldShowIcon = timeSincePlayerTouch >= thresholdTimeToShowPrompt;
// Only call SetActive when needed, in case of overhead
if (shouldShowIcon && !joystick.activeSelf)
{
joystick.SetActive(true);
}
else if (!shouldShowIcon && joystick.activeSelf)
{
joystick.SetActive(false);
}
}
I have created a script that receives a List of game object. When I press the tab key, the script must update the index by 1 (index++), get the gameobject in that position, then log the name of the gameobject, this is the piece of code for the script
void Start() {
index = 0;
}
void Update(){
ChangeLeader();
}
void ChangeLeader(){
if (index >= playerList.Count){
index = 0;
}else{
if (Input.GetKey(KeyCode.Tab)){
leader = playerList[index];
index += 1;
Debug.Log(leader.name);
}
}
}
What I was expecting was that every time I press tab, it will log the objects name then updates the index in 1 unit.
The problem is that I was expecting the code to log all the names in the List at once.
It don't feel discouraged to call me dumb. I only started with unity a few days ago, thanks for the help.
Update() is called every frame.
(Input.GetKey(KeyCode.Tab)) is gonna be true for consecutive frames, because your finger is down for a few milliseconds.
Use:
(Input.GetKeyDown(KeyCode.Tab))
or
(Input.GetKeyUp(KeyCode.Tab)) instead. This is triggered just once.
I'm going to make a rhythm game.
music playing time is variable which change by music playing in millisecond
List is a float list which have the time(float second) I filled , let me to access it and use for compare with music playing time to instance object .
when list time = music time then instant object.
but sometimes will missing(not found value in list but value is really exist in list).
Here is my assumption.
I think List.indexOf performance are not good and thread have some delay.
Music playing time change every millisecond , a little delay from unity or others will cause missing(doesn't entering if statement)
I don't know if it's correct.
Could any one help me.
Here is my code.
IEnumerator Execute(MethodDelegate Start,MethodDelegate Stop)
{
while (true) {
int res = result.IndexOf ((float)System.Math.Round (GameObject.Find ("Music").GetComponent<AudioSource> ().time, DigitalAdjust)-TimeAdjust);
if (res!=-1) {
if (res == result.Count-2) {
Stop.Invoke ();
print ("CoroutineStop");
StopCoroutine (_Execute);
}
//execute
num=Positoin[res];
print (res);
Start.Invoke();
}
yield return null;
}
}
Thanks.
Chances are that you are correct. You might miss some if statement because you don't match the millisecond exactly. Here are some things that could help:
It you game reaches 60 FPS (the usual rate for a smooth rendering), each frame will take around 16 milliseconds. If you have events that must trigger at exact milliseconds you will miss some because your Execute function calls are separated by around 16ms (a coroutine is called once per frame).
A solution to this is remember the last time the Execute function was called and check everything in between:
private float _lastTime;
IEnumerator Execute(MethodDelegate Start,MethodDelegate Stop)
{
while (true) {
// here your code must check all the event between _lastTime and Time.time
var lastTimeMilliseconds = (int)(_lastTime*1000);
var currentTimeMilliseconds = (int)(Time.time*1000);
for(int time = lastTimeMilliseconds+1; time <= currentTimeMillisedons; time++)
{
// let's say last frame was at time 1000ms
// This frame occurs at time 1016ms
// we have to check your list for events that have occured since last frame (at time 1001, 1002, 1003, ...)
// so we have a for loop starting at 1001 until 1016 and check the list
int res = result.IndexOf ((float)System.Math.Round (time, DigitalAdjust)-TimeAdjust);
if (res!=-1)
{
if (res == result.Count-2)
{
Stop.Invoke ();
print ("CoroutineStop");
StopCoroutine (_Execute);
}
//execute
num=Positoin[res];
print (res);
Start.Invoke();
}
}
// At the end, remember the time:
_lastTime = Time.time;
yield return null;
}
}
Check the Time class, you also have access to Time.deltaTime to know the time elapsed between two frames, if that helps.
EDIT:
As you requested in comment, I added some bit of code from your example to explain better this idea. Note that I don't know what your variables do so you will have to adapt. For instance, Time.time gives that time since app start. You will likely need to adapt this use the time since you started the audio
Another important thing:
GameObject.Find must look in all the objects. It is really slow and shouldn't be used every frame
GetComponent looks for all your scripts and is slow as well. It shouldn't be used every frame.
Instead, do this:
private AudioSource _audioSource;
private void Start()
{
_audioSource = GameObject.Find ("Music").GetComponent<AudioSource> ();
}
This will retrieve the source only once. Then in your code you simply call
_audioSource.time;
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.
I have a "datapack" hidden in each of my levels, the system remembers per level if the artifact has been taken and if so it disables the artifact when a player replays it but i also want to keep track of the total amount taken, the system almost works there's just 1 small issue:
When i finish the level with the first datapack, in the menu it says: 1, this is correct.
but when i do it with the 2nd, it says 3, with the 3rd it says 4, 4th says 5 etc
i don't understand why and thus can't fix it
here's the code:
function OnTriggerEnter(other : Collider) {
if(other.CompareTag("DataPacket")){
pickedUpDataPacket = 1;
Destroy(other.gameObject);
gameObject.Find("DatapackFound").guiText.enabled = true;
yield WaitForSeconds (1.5);
gameObject.Find("DatapackFound").guiText.enabled = false;
}
if(other.CompareTag("Finish") && pickedUpDataPacket == 1){
PlayerPrefs.SetInt("DataPackLevel" + levelindex.ToString(), 1);
//if(!PlayerPrefs.HasKey("totalDatapacks")){
//PlayerPrefs.SetInt("totalDatapacks", 1);
//} else {
PlayerPrefs.SetInt("totalDatapacks", (PlayerPrefs.GetInt("totalDatapacks")+1));
}
}
//}
i already commented a part out, i believe this was also part of the issue.
and part of a 2nd script:
if(datapacktotal){
if(PlayerPrefs.GetInt("totalDatapacks") > 0){
findText.text = "Collected:" + PlayerPrefs.GetInt ("totalDatapacks");
}
Thanks in advance :)
From the described behaviour it seems that, in some occasions, the collision is triggered multiple times, before the datapack is being destroied. As in level 2, where the counter passes from 1 to 3.
My though is that your collider has multiple contact points, so that - if you touches n of them - the collision is triggered n times.
I would try a simple experiment, just use a flag to determine if that's the first time you "touch" the collider; then, you'll update the PlayerPref just in that case:
function OnTriggerEnter (other : Colliderstrong text){
if (collisionAlreadyConsidered) return;
collisionAlreadyConsidered = true;
// your code here...
}
function Update(){
collisionAlreadyConsidered = false;
}
, where collisionAlreadyConsidered is a global variable.