I've been having trouble figuring out this error I've been getting. The code works for my other projects, but for some reason it isn't working in this project.
This is the error
NullReferenceException: Object reference not set to an instance of an object LevelManager.AdsLoadlevel (System.String name) (at Assets/Scripts/LevelManager.cs:21) LevelManager.ScoreLevelLoad () (at Assets/Scripts/LevelManager.cs:46) UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:153) UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:634) UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent.cs:769) UnityEngine.Events.UnityEvent.Invoke () (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53) UnityEngine.UI.Button.Press () (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44) UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52) UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269) UnityEngine.EventSystems.EventSystem:Update()
this is the code from the LevelManager class
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class LevelManager : MonoBehaviour {
private AdsManager ads;
// Use this for initialization
void Start () {
ads = GameObject.FindObjectOfType<AdsManager> ();
}
//LEVELMANAGEMENT
public void AdsLoadlevel(string name){
ads.ShowRewardedAd ();
SceneManager.LoadScene(name);
}
public void LoadLevel(string name){
SceneManager.LoadScene(name);
}
//For death
private void LoadLevelDeath(){
SceneManager.LoadScene ("LoseScreen");
}
public void DeathLevel(){
Invoke ("LoadLevelDeath", 2.5f);
}
//Score level management
public void ScoreLevelLoad(){
if (Score.score < 200) {
AdsLoadlevel ("Level1");
}
if (Score.score >= 200 && Score.score < 400) {
AdsLoadlevel ("Level2");
}
if (Score.score >= 400 && Score.score < 600) {
AdsLoadlevel ("Level3");
}
if (Score.score >= 600 && Score.score < 800) {
AdsLoadlevel ("Level4");
}
if (Score.score >= 800 && Score.score < 1000) {
AdsLoadlevel ("Level5");
}
}
}
and this is the code for the AdsManager class
using UnityEngine;
using System.Collections;
using UnityEngine.Advertisements;
public class AdsManager : MonoBehaviour {
public void ShowAd()
{
if (Advertisement.IsReady())
{
Advertisement.Show();
}
}
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;
}
}
}
The error occurs when I press a button to call the ScoreLevelLoad function, and the line it highlights is "ads.ShowRewardedAd()". Also, SOMETIMES a warning pops up saying I'm missing a reference and when I click on that it shows "Unity ads coroutine host". I've been struggling with this for a few days and can't seem to figure it out.
I figured it out, although I do not fully understand why, I assume it has to do with global variable or something, but basically all I needed to do was move what was in the Start function, into the AdsLoadlevel function so it reads like
public void AdsLoadlevel(string name){
ads = GameObject.FindObjectOfType<AdsManager> ();
ads.ShowRewardedAd ();
SceneManager.LoadScene(name);
}
if any one has a more detailed reason for why this is, please comment!
Related
I have looked at other answers, but it hasnt helped because I did add the object and not the script in the OnClick() box, but it still won't let me access the variable. What's going on?
The object in the box, not the script
The Method I want to access
public void IncreaseStat(string stat, float val)
{
switch (stat)
{
case "Hunger":
gm.juice.hunger += val;
break;
case "Energy":
gm.juice.energy += val;
break;
case "Happiness":
gm.juice.happiness += val;
break;
case "Health":
gm.juice.health += val;
break;
default:
Debug.LogError("INVALID STAT: " + stat);
break;
}
}
Look like Unity not allow you to put function with more than one parameter into the OnClick() event
using UnityEngine;
using UnityEngine.UI;
public class ButtonEventDemo : MonoBehaviour
{
public void FunctionWithNoParams()
{
// This is working fine
}
public void FunctionWithStringParam(string text)
{
// This is working fine
}
public void FunctionWithIntParam(int number)
{
// This is working fine
}
public void FunctionWithButtonParam(Button button)
{
// This is working fine
}
public void FunctionWithTwoParams(int first, int second)
{
// Cannot put this function into OnClick() event
}
}
OnClick() demo
Hey guys I'm learning how to create a character controller via the state pattern, which is pretty snazzy, but I'm running into this weird error
I've got a state machine pattern put together so this should be pretty straightforward and easy to handle, but it's kinda confusing. I tried freezing him in the state to see if he was transitioning from wallgrab to wallslide, but when I stop the velocity on the x and y he still slides. There's no other movement physics being applied at this time (why I'd recommend the state pattern), but for some reason his movement isn't being frozen. I can't pin a reason as to why, other than point you to my code and my github, and hope someone like my pixel art and has fun with the movement for a little bit.
All the code is in the scripts folder within the assets folder, and the states are within Assets > Scripts > Player > and then there are two folders (sub and super) The WallGrabState inherits from the PlayerTouchingWallState, and the logic is coming mainly from the WallGrabState for the physics. I'm just setting the x and y to zero, and yet he still slides, and idk what to do.
PlayerTouchingWall inherits the main state logic from playerState, and the player script loads all the states together and holds the physics and miscellaneous functions. The link to my github project is here https://github.com/roninMo/2d-Intro-Unity-Project
Here's the PlayerWallSlideState:
using UnityEngine;
public class PlayerWallSlideState : PlayerTouchingWallState
{
public PlayerWallSlideState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
{
}
public override void LogicUpdate()
{
base.LogicUpdate();
player.SetVelocityY(-playerData.wallslideVelocity);
// State logic
if (grabInput && input.y > 0)
{
player.StateMachine.ChangeState(player.wallGrabState);
}
}
}
And Here's the PlayerTouchingWallState:
using UnityEngine;
public class PlayerTouchingWallState : PlayerState
{
protected bool isTouchingGround;
protected bool isTouchingWall;
protected Vector2 input;
protected bool grabInput;
public PlayerTouchingWallState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void LogicUpdate()
{
base.LogicUpdate();
input = player.InputHandler.RawMovementInput;
grabInput = player.InputHandler.GrabInput;
// State logic
if (isTouchingGround && !grabInput)
{
StateMachine.ChangeState(player.IdleState);
}
else if (!isTouchingWall || (input.x != player.FacingDirection && !grabInput))
{
StateMachine.ChangeState(player.InAirState);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
}
public override void DoChecks()
{
base.DoChecks();
isTouchingGround = player.CheckIfTouchingGround();
isTouchingWall = player.CheckIfTouchingWall();
}
}
The problem is that unity still applys physics to the character. I stopped it by grabbing the transform, and setting the player the position it entered in this state, along with freezing the velocity. Setting the transform is enough, but the camera was dragging upwards in place... So freezing the velocity fixed that. Anyways here's the code:
using UnityEngine;
public class PlayerWallGrabState : PlayerTouchingWallState
{
private Vector2 holdPosition;
public PlayerWallGrabState(Player player, PlayerStateMachine stateMachine, PlayerData playerData, string currentAnimation) : base(player, stateMachine, playerData, currentAnimation)
{
}
public override void Enter()
{
base.Enter();
holdPosition = player.transform.position;
HoldPosition();
}
public override void Exit()
{
base.Exit();
}
public override void LogicUpdate()
{
base.LogicUpdate();
HoldPosition();
// State logic
if (input.y > 0)
{
StateMachine.ChangeState(player.wallClimbState);
}
else if (input.y < 0 || !grabInput)
{
StateMachine.ChangeState(player.wallSlideState);
}
}
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
}
public override void DoChecks()
{
base.DoChecks();
}
private void HoldPosition()
{
player.transform.position = holdPosition;
player.SetVelocityX(0f);
player.SetVelocityY(0f);
}
}
Im new in developing so need some help for my game!
On my game I have 2 buttons one is "Play" and other "Level Select"
I stuck at the "Play" button, need to make a script that is always loading the highest level that is unlocked, not current but highest.
Here is the code that im using for level manager
public List<Button> levelButton;
public Sprite lockimage;
public bool delete;
private void Start()
{
int saveIndex = PlayerPrefs.GetInt("SaveIndex");
for (int i = 0; i < levelButton.Count; i++)
{
if (i <= saveIndex)
{
levelButton[i].interactable = true;
}
else
{
levelButton[i].interactable = false;
levelButton[i].GetComponent<Image>().sprite = lockimage;
}
}
}
public void LevelSelect()
{
int level = int.Parse(EventSystem.current.currentSelectedGameObject.name);
SceneManager.LoadScene(level);
}
public void PlayGame()
{
//code here
}
public void ResetGame()
{
PlayerPrefs.SetInt("SaveIndex", 0);
SceneManager.LoadScene(0);
}
public void DontResetGame()
{
SceneManager.LoadScene(0);
}
}
SceneManager.LoadScene(PlayerPrefs.GetInt("SaveIndex"));
edit: adding some info/context.
I realized that you set level buttons interactivity on the start functions based on the int save_index value you get from PlayerPrefs.
From there, I assumed that you could load the level directly using that same value on the PlayGame function.
Do note that the code I wrote will throw an error, if the "SaveIndex" key is not yet on PlayerPrefs
I really need help, when I put Invoke in C#, I have this error:
The local function 'RestartGame' is declared but never used Assembly-CSharp
I really don't know why it is happening, but here is the code:
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
bool gameHasEnded = false;
public float restartDelay = 2f;
public void EndGame()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("RestartGame", restartDelay);
}
void RestartGame ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
}
unity manual: For better performance and maintability, use Coroutines instead.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
Try someting like this:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
bool gameHasEnded = false;
public float restartDelay = 2f;
private IEnumerator coroutine;
public void EndGame()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
coroutine = RestartDelayed(restartDelay);
StartCoroutine(coroutine);
}
void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
IEnumerator RestartDelayed(float delay)
{
yield return new WaitForSeconds(delay);
RestartGame();
}
}
}
https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html
I upvoted flyingchris answer but just to explain your error message, I'm assuming its a yellow warning message, is that you are never calling the method RestartGame() directly anywhere in your code, you are invoking it however. Invoking is typically used for UnityEvents and coroutines are typically used for delaying a method.
I've made a script that take some public object reference.
But depending on which function i call, one reference is fine but in the other function it's null, i don't understand why.
In the function onSave(), the reference to database is fine and i can access her function like add.
Then, when i call the function edit (which is supposed to retrieve an object into database and fill the form with data) the reference to database is null.
Error log (line 33 is this one: Step step = this.database.get(this.scrollList.selectedItem);:
> NullReferenceException: Object reference not set to an instance of an object
StepForm.edit () (at Assets/Prefabs/Scripts/StepForm.cs:33)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:110)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:574)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:716)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()
here is my script:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class StepForm : MonoBehaviour {
public Database database;
public ScrollList scrollList;
public InputField title;
public InputField content;
private string uid;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void onSave(){
Step newStep = new Step (this.title.text, this.content.text);
this.database.addStep (newStep);
}
public void onCancel(){
Debug.Log ("onCancel");
}
public void onDelete(){
Debug.Log ("onDelete");
}
public void edit(){
Step step = this.database.get(this.scrollList.selectedItem);
if (step != null) {
this.title.text = step.Title;
this.content.text = step.Content;
}
}
}
The script reference source:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Database : MonoBehaviour {
// Update is called once per frame
void Update () {
}
private List<Step> steps = new List<Step>();
// Use this for initialization
void Start () {
}
public List<Step> Steps {
get {
return this.steps;
}
}
public void addStep(Step newStep)
{
//if (!this.exist(newStep.Uid))
this.steps.Add(newStep);
}
public void deleteStep (Step newStep)
{
this.steps.Remove(newStep);
}
public void updateStep(string uid, Step newStep)
{
Step step = this.Steps.Find(o => o.Title == newStep.Title);
if (step != null) {
step.Title = newStep.Title;
step.Content = newStep.Content;
}
}
private bool exist(string uid)
{
if (this.Steps.Find (o => o.Uid == uid) != null)
return (true);
return (false);
}
public Step get(string uid)
{
Step step = this.Steps.Find (o => o.Uid == uid);
Debug.Log ("GET DATABASE");
Debug.Log (step.Title);
return (step);
}
public void debugContent(){
foreach (Step step in this.steps) {
Debug.Log ("### Debug Step ###");
Debug.Log(step.Uid);
Debug.Log(step.Title);
Debug.Log(step.Content);
}
}
public void clearDatabase(){
this.steps.Clear ();
Debug.Log ("Database cleared!");
}
}