I am allowing users to be rewarded for watching unity video ads with a button click. When you click the button if the ad is ready it displays a video without the option to skip. I add points to the currency as well.
Advertisement.Show ("rewardedVideoZone");
currency += 10;
The ads run fine, at least in test mode, and you cannot skip them. You are also rewarded the 10 points for watching. The problem is that if I start an ad, close my app, then re-open it the ad is gone and I have the 10 extra points.
Is there a way of finding if a user watched the full video to prevent someone from cheating it?
Yup, there is. What you can use is the ShowOptions.resultCallback event to detect whether the user has finished seeing the ad.
Specifically, the event has a parameter ShowResult, which will have a value of ShowResult.Finished if the user watched the ad completely.
Partial Example
if(Advertisement.IsReady("rewardedVideoZone")) {
var showOptions = new ShowOptions();
showOptions.resultCallback += ResultCallback;
Advertisement.Show("rewardedVideoZone", showOptions);
}
private void ResultCallback (ShowResult result) {
if(result == ShowResult.Finished) {
currency += 10;
}
else {
Debug.Log ("No award given. Result was :: "+result);
}
}
Use this code:
using UnityEngine;
using UnityEngine.Advertisements;
public class UnityAdsExample : MonoBehaviour
{
public void ShowRewardedAd()
{
if (Advertisement.IsReady("rewardedVideo"))
{
var options = new ShowOptions { resultCallback = HandleShowResult };
Advertisement.Show("rewardedVideo", options);
}
}
private void HandleShowResult(ShowResult result)
{
switch (result)
{
case ShowResult.Finished:
Debug.Log("The ad was successfully shown.");
//
// YOUR CODE TO REWARD THE GAMER
// Give coins etc.
break;
case ShowResult.Skipped:
Debug.Log("The ad was skipped before reaching the end.");
break;
case ShowResult.Failed:
Debug.LogError("The ad failed to be shown.");
break;
}
}
}
For more info check the documentations.
Related
I've AdMob test ads fully working in my project.
When the ad is watched the below code should run, however only the first line is being executed, the 2 other lines are being ignored with no error.
public void HandleUserEarnedReward(object sender, Reward args)
{
GameControl.control.life += 1;
GameControl.control.Save();
txtLife.text = GameControl.control.life.ToString();
}
I've placed the same code in another method that I trigger with a button to test.
In this instance the full method is run.
public void runtest()
{
GameControl.control.life += 1;
GameControl.control.Save();
txtLife.text = GameControl.control.life.ToString();
}
If i'm not wrong you are trying to give reward after User watches rewarded video. I had the same problem one time, the problem is that functions that are executing inside of "HandleUserEarnedReward" will NOT be executed on unity's MainThread, but on Google's SDK thread.
There are several solutions:
https://github.com/PimDeWitte/UnityMainThreadDispatcher - Switch to main thread using this. Check readme file to more info.
Create global booleans with false value. Then on "HandleUserEarnedReward" change "isRewarded" boolean to true. Create Update function to check boolean value. Something like:
void Update()
{
if (isRewarded)
{
// do all the actions
// reward the player
isRewarded = false; // to make sure this action will happen only once.
}
}
Use Coroutine. Coroutines autoMagically switch to Unity's MainThread after "yield return"
public void HandleRewardBasedVideoRewarded(object sender, Reward args)
{
string type = args.Type;
double amount = args.Amount;
Debug.Log(
"HandleRewardBasedVideoRewarded event received for "
+ amount.ToString() + " " + type);
StartCoroutine(AfunctionName());
}
IEnumerator AfunctionName()
{
yield return new WaitForSecondsRealtime(0.1f);
// FB.LogAppEvent("AdmobRewardedView");
Debug.Log("Reward Function Called!!!!!");
GiveReward();
this.RequestRewardBasedVideo();
}
I tried to do a video streaming application with Unity and I have successfully connect two user and are able to video chat & sharescreen. The problem is now when the other/second user press leave channel and rejoin again, first user will see the second user screen just stopped at the last frame. Only way to deal with it right now is to exit Unity play mode and re-enter again. Below are the code:
void LoadEngine()
{
print("Loading Engine...");
if (engine != null)
{
print("Engine already exists. Please unload it first!");
return;
}
engine = IRtcEngine.GetEngine(appId);
engine.SetLogFilter(LOG_FILTER.DEBUG);
}
void UnloadEngine()
{
print("Unloading Engine...");
if (engine != null)
{
IRtcEngine.Destroy();
engine = null;
}
}
void EnableVideo(bool yes)
{
engine.DisableAudio();
if (yes)
{
engine.EnableVideo();
engine.EnableVideoObserver();
}
else
{
engine.DisableVideo();
engine.DisableVideoObserver();
}
}
private void JoinChannel()
{
print("Joining Channel...");
EnableVideo(true);
// add our callback to handle Agora events
engine.OnJoinChannelSuccess += OnJoinChannelSuccess;
engine.OnUserJoined += OnUserJoined;
engine.OnUserOffline += OnUserLeave;
engine.OnLeaveChannel += OnLeaveChannel;
button_Join.onClick.RemoveListener(JoinChannel);
button_Join.onClick.AddListener(LeaveChannel);
button_Join.GetComponentInChildren<Text>().text = "Leave Channel";
if (string.IsNullOrEmpty(channelName))
{
return;
}
engine.JoinChannel(channelName, null, 0);
}
private void LeaveChannel()
{
print("Leaving Channel...");
button_Join.onClick.RemoveListener(LeaveChannel);
button_Join.onClick.AddListener(JoinChannel);
button_Join.GetComponentInChildren<Text>().text = "Join Channel";
playerOne.Clear();
playerTwo.Clear();
engine.LeaveChannel();
EnableVideo(false);
engine.OnJoinChannelSuccess -= OnJoinChannelSuccess;
engine.OnUserJoined -= OnUserJoined;
engine.OnUserOffline -= OnUserLeave;
engine.OnLeaveChannel -= OnLeaveChannel;
}
private void OnJoinChannelSuccess(string channelName, uint uid, int elapsed)
{
print("Joined with uid " + uid);
myId = uid;
playerOne.Set(0);
}
private void OnUserJoined(uint uid, int elapsed)
{
string userJoinedMessage = string.Format("onUserJoined callback uid {0} with elapsed {1}", uid, elapsed);
print(userJoinedMessage);
playerTwo.Set(uid);
}
private void OnUserLeave(uint uid, USER_OFFLINE_REASON reason)
{
string userLeaveMessage = string.Format("onUserOffline callback uid {0} with reason {1}", uid, reason);
print(userLeaveMessage);
playerTwo.Clear();
}
private void OnLeaveChannel(RtcStats stats)
{
playerTwo.Clear();
}
private void OnApplicationQuit()
{
UnloadEngine();
}
Is there anything I missed out in the code?
Edit
I suspect this is Agora API bugs where the video surface will not continue to stream the video when the UID was being changed in the runtime. This explained when the same user leave and rejoin, he will get different uid everytime he rejoin. The video surface will need to set UID to another number which causes the video surface stopped streaming.
Solution
I solved it using unity instantiate to real time instantiate the video surface when connected to channel and destroy the video surface game object when leaving a channel.
first of all, great name! ;)
I'm glad that you were able to work out a solution.
Another technique you can try, is calling:
yourVideoSurface.SetForUser(yourNewUID);
It looks like you're already implicitly doing that in your playerOne.Set(0) call, however I'd figure I'd mention it just in case.
I had the same issue in Unity. The tmp was returning -1. In the Update loop of VideoSurface.cs if this occurs, the update loop stops.
if (tmpi == -1)
return;
I agree with Jeremy, the Agora VideoSurface doesn't support changing users. I set the UID on the VideoSurface manually and it fixed the issue. I also agree that the sdk implies that it would change- which is misleading and frustrating.
I believe the issue may occur because VideoSurface.cs sets uint uid = mUid; in the update loop, so it is set to the default ID when the Unity scene starts then errors out when videoSurface.SetForUser(uid); is called by TestHelloUnityVideo when a user joins.
I am trying to implement the auth state change with firebase in unity. I dont know if i do it right cuz the doc kinda unclear for me. a good sample of code from your guys would be super respectful from me. this is the link of the doc. https://firebase.google.com/docs/auth/unity/manage-users?authuser=0
and the title is (Get the currently signed-in user) in the doc. I really need help guys. I dont understand how to use it correctly.I have tried to get help from the firebase dev but haven't got a response. I you guys want a close detail we can chat at discord. Just let me know. :)
DatabaseReference reference;
public static Login instance;
FirebaseAuth auth;
FirebaseUser Player;
bool isServiceAvailable;
bool isAuthenticated;
public Text TEXTName;
public Text TEXTID;
public Text Data;
public Text State;
private User user;
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
DontDestroyOnLoad(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(" I hide the url");
reference = FirebaseDatabase.DefaultInstance.RootReference;
State.text = "Checking state";
InitializeFirebase();
LogInUser();
}
// Update is called once per frame
void Update()
{
}
// Handle initialization of the necessary firebase modules:
void InitializeFirebase()
{
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
if (auth.CurrentUser != Player)
{
bool signedIn = Player != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null)
{
Debug.Log("Signed out " + Player.UserId);
State.text = "Sign out";
}
Player = auth.CurrentUser;
if (signedIn)
{
Debug.Log("Signed in " + Player.UserId);
State.text = "Sign in";
}
}
}
void OnDestroy()
{
auth.StateChanged -= AuthStateChanged;
auth = null;
}
public void SignIn()
{
FirebaseAuth auth = FirebaseAuth.DefaultInstance;
auth.SignInWithEmailAndPasswordAsync(TEXTID.text, TEXTName.text).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
}
I have good news, there is a sample and a video tutorial!
With that said, let me go through a quick impromptu code review:
You are registering the event correctly, and even unregistering in OnDestroy (I find that many folk who are used to UnityEvent will omit this step).
I don't think the check against player is doing what you want though. I would make two changes:
First, I'd change ContinueWith to ContinueWithOnMainThread. If you ever end up making any calls into the UnityEngine namespace other than Debug.Log, you're asking for trouble.
Next, FirebaseUser is implemented in sort of an odd way right now. It references a global static object on the C++ side rather than being a typical PIMPL construct. There are various reasons for this, and it is being worked on, but I wouldn't count on comparisons other than the comparison to null saving you any time right now. This likely won't cause any issues with the code you've posted other than adding a few redundant checks (and Player.UserId might be unreliable in your sign out logic), but if you plan to cache FirebaseUser for comparison later, it won't work the way you think it will work.
I'm not sure if I've set up my event callbacks correctly, where would these events be firing to? I've setup test ads and all the different types of ads are working correctly.
I've got a game object UI_Menu with my listener attached to it like so
AppLovin.SetUnityAdListener("UI_Menu");
But none of the events are firing
public void ShowInterstitial()
{
Log("Showing interstitial ad");
// Optional: You can call `AppLovin.PreloadInterstitial()` and listen to the "LOADED" event to preload the ad from the network before showing it
// Showing utilizing PreloadInterstitial and HasPreloadedInterstitial
if (AppLovin.HasPreloadedInterstitial())
{
// An ad is currently available, so show the interstitial.
#if UNITY_ANDROID
AppLovin.ShowInterstitialForZoneId("998d2ed211ae3efc"); // For Zone Non-RewardedFullScreen3
#endif
}
else
{
// No ad is available. Perform failover logic...
}
}
void onAppLovinEventReceived(string ev)
{
Debug.Log("called");
Log(ev);
if (ev.Contains("VIDEOBEGAN "))
{
Debug.Log("working");
// An ad was shown. Pause the game.
}
else if (ev.Contains("HIDDENINTER"))
{
// Ad ad was closed. Resume the game.
// If you're using PreloadInterstitial/HasPreloadedInterstitial, make a preload call here.
AppLovin.PreloadInterstitial();
}
else if (ev.Contains("LOADEDINTER"))
{
// An interstitial ad was successfully loaded.
}
else if (string.Equals(ev, "LOADINTERFAILED"))
{
// An interstitial ad failed to load.
}
}
everything works fine. downloading and displaying ads. after showing one gives 1 life. what I want is to not give a prize after canceling the ad. is also annoyed when you leave the ad. how can I make sure that the ad is not killed when it is closed? how can I do it ? is there a function that checks that the ad is fully tracked? or is there a function that checks that the ad is closed? and I can determine the duration of the ads. thank you for your interest
`
// Get singleton reward based video ad reference.
this.rewardBasedVideo = RewardBasedVideoAd.Instance;
// RewardBasedVideoAd is a singleton, so handlers should only be registered once.
this.rewardBasedVideo.OnAdLoaded += this.HandleRewardBasedVideoLoaded;
this.rewardBasedVideo.OnAdFailedToLoad += this.HandleRewardBasedVideoFailedToLoad;
this.rewardBasedVideo.OnAdOpening += this.HandleRewardBasedVideoOpened;
this.rewardBasedVideo.OnAdStarted += this.HandleRewardBasedVideoStarted;
this.rewardBasedVideo.OnAdRewarded += this.HandleRewardBasedVideoRewarded;
this.rewardBasedVideo.OnAdClosed += this.HandleRewardBasedVideoClosed;
this.rewardBasedVideo.OnAdLeavingApplication += this.HandleRewardBasedVideoLeftApplication;
}
public void Update()
{
// Calculate simple moving average for time to render screen. 0.1 factor used as smoothing
// value.
this.deltaTime += (Time.deltaTime - this.deltaTime) * 0.1f;
}
// Returns an ad request with custom ad targeting.
private AdRequest CreateAdRequest()
{
return new AdRequest.Builder()
.AddTestDevice(AdRequest.TestDeviceSimulator)
.AddTestDevice("0123456789ABCDEF0123456789ABCDEF")
.AddKeyword("game")
.SetGender(Gender.Male)
.SetBirthday(new DateTime(1985, 1, 1))
.TagForChildDirectedTreatment(false)
.AddExtra("color_bg", "9B30FF")
.Build();
}
private void RequestRewardBasedVideo()
private void ShowRewardBasedVideo()
{
if (this.rewardBasedVideo.IsLoaded())
{
this.rewardBasedVideo.Show();
}
else
{
MonoBehaviour.print("Reward based video ad is not ready yet");
}
}`
NOTE : cut some small parts because it does not publish the code. it would be enough if you tell me the meaning of not giving a prize only in the cancellation of advertisement.
You subscribe to the OnAdRewarded-event in your code:
this.rewardBasedVideo.OnAdRewarded += this.HandleRewardBasedVideoRewarded;
Your this.HandleRewardBasedVideoRewarded-method will be called when the user has completed watching the video.
You can use OnAdClosed to see if the ad was closed.
Check out all the events here
https://developers.google.com/admob/unity/rewarded-video