Unity script reference is null depend on which function use the reference - unity3d

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!");
}
}

Related

How to get other player's value in Unity when I use Mirror Network?

Hello? I'm studying the MIRROR Network Now.
enter image description here
However, I have a problem about getting other player's value. This image explain what I want to do.
enter image description here
I create 3 projects. One is server(local host) and other is Client A , the other is Client B.
Firstly, I wrote code like this :
public class PlayerManager : NetworkBehaviour
{
[SyncVar(hook = nameof(onValueChanged))]
int value = 0;
private void Update()
{
if(isServer && Input.GetKeyDown("x"))
{
Message();
}
}
public override void OnStartServer()
{
Debug.Log("Here is Game Room Scene, Player add Successfully");
}
[Command]
private void Hola()
{
value++;
Debug.Log("Received Hola from the client!");
Debug.Log("Server Value : " + value);
ReplyHola();
}
[TargetRpc]
private void ReplyHola()
{
Debug.Log("Received Hola from Client!");
}
[ClientRpc]
private void Message()
{
Debug.Log("Ping...");
}
[ClientRpc]
private void UpdateValue(int value)
{
this.value = value;
}
private void onValueChanged(int oldValue, int newValue)
{
Debug.Log("New Value Detective :");
Debug.Log("Old Value : " + oldValue);
Debug.Log("New Value : " + newValue);
Debug.Log("Sum Value : " + PlayerStat.Value);
}
}
3 Projects have all same code. I referenced code from this video(https://www.youtube.com/watch?v=8tKFF0RP9Jw).
And, I wrote code about sum client A and B's code like this:
private void SumDatas()
{
foreach(var playerObj in FindObjectsOfType(typeof(GameObject)) as GameObject[])
{
if(gameObject.name == "Player(Clone)")
{
PlayerStat.Value += GameObject.Find("Player(Clone)").transform.GetComponent<PlayerManager>().GetValue();
}
}
}
PlayerStat is a static class and Code is like this:
public static class PlayerStat
{
public static int Value { get; set; }
}
Is there anybody help me?
I solved this problem. I will not delete this question for other people who will have same problem with me.
I add this code at my server project, Client A and B project:
[SyncVar(hook = nameof(onValueChanged))]
int value = 0;
int myValue = 0;
private void Update()
{
myValue = PlayerStat.Value;
}

Button OnClick() not detecting public method

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

Unity ads coroutine host missing and NullReferenceException

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!

Postsharp Aspect with Async methods

I'm using Trial Ultimate version of PostSharp 4.0 but this doesn't work for me. Can you please check my code and advise. The error doesn't gets logged. And if i put the breakpoint doesn't hit onException method
This is code that I've written for Error handling Aspect
[Serializable]
public class MyMethodAspectAttribute : OnMethodBoundaryAspect
{
public MyMethodAspectAttribute()
{
this.ApplyToStateMachine = true;
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.Write("Method Entry");
}
public override void OnException(MethodExecutionArgs args)
{
Console.Write(args.Exception.Message);
args.ReturnValue = null;
args.FlowBehavior = FlowBehavior.Return;
}
}
This is class where I've implemented this aspect
public class ErrorMethods
{
[MyMethodAspect]
public Task<int> Calculate(int i, int j)
{
var task = Task.Factory.StartNew(
() => i / j);
return task;
}
}
This is how I've used this method
private async void Button_Click(object sender, RoutedEventArgs e)
{
var obj = new ErrorMethods();
var result = await obj.Calculate(1, 0);
if (null == result)
{
MessageBox.Show("error");
}
}
The Calculate method in your example is not an async method, so setting ApplyToStateMachine aspect's property doesn't have effect on this method. The exception is thrown when a newly created task executes in the background and the aspect has no chance of catching it.
If you change your Calculate method to async method, then the async state machine execution can be intercepted by the aspect and OnException handler is invoked upon exception.
Note, however that setting the ReturnValue and FlowBehavior does not alter the flow of the state machine, so the exception will not be swallowed.
public class ErrorMethods
{
[MyMethodAspect]
public async Task<int> Calculate( int i, int j )
{
return await Task.Factory.StartNew( () => i / j );
}
}

JavaFX MediaPlayer "Error: 80de0001 in CallbackToJava..."

I am making a media player which allows users to drag and drop media thumbnails onto a media player (using JavaFX MediaPlayer).
When I run it and try the drag/drop functionality, some of the time it works just as expected. However sometimes it produces a weird error.
The error in its fullness is:
Error:80de0001 in CallbackToJava(javaIDs.View.notifyDragDrop, grfKeyState, pt, pdwEffect)
COM Error:80de0001 Unknown Error 0x80DE0001
Error:80de0001 in :: DoDragDrop( pcd, IDropSourcePtr(new GlassDropSource(obj), getDROPEFFECT(supportedActions, &performedDropEffect)
COM Error:80de0001 Unknown error 0x80DE0001
The print-out in Eclipse looks like: (all double-spaced)
I really have no idea why this is happening - I'm clearly doing something wrong. The error doesn't point me to any line of code. I would suggest that the error is referring to a memory address? Are you able to help me, please?
The listeners/handlers which perform the Drag/Drop functionality are:
root.setOnMouseEntered(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
root.setStyle(highlightBackgroundStyle);
parentScene.setCursor(Cursor.OPEN_HAND);
}
});
root.setOnMouseExited(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
root.setStyle(backgroundStyle);
//parentScene.setCursor(Cursor.DEFAULT);
}
});
root.setOnDragDetected(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
parentScene.setCursor(Cursor.CLOSED_HAND);
Dragboard db = parentScene.startDragAndDrop(TransferMode.COPY);
ClipboardContent content = new ClipboardContent();
content.putString(mediaFile.toURI().toString());
db.setContent(content);
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragDropped(new EventHandler<DragEvent>(){
#Override
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOff();
Dragboard db = arg0.getDragboard();
if (db.hasString())
{
//System.out.println(db.getString());
String mediaURI = db.getString();
System.out.println(mediaURI);
mediaPanel.getMixerA().getJfxMediaPlayer().loadAndPlayMediaA(new Media(mediaURI));
mediaPanel.getMixerA().prepareMedia();
arg0.setDropCompleted(true);
}else{System.out.println("Drag error");arg0.setDropCompleted(false);}
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragExited(new EventHandler<DragEvent>(){
#Override
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOff();
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragOver(new EventHandler <DragEvent>() {
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOn();
if (arg0.getGestureSource() != mediaPanel.getDropZoneB() && arg0.getDragboard().hasString())
{
arg0.acceptTransferModes(TransferMode.COPY);
}
arg0.consume();
}
});
Update 1
I am wondering whether this is caused by the way I 'change' the media for the MediaPlayer. I do the following:
public void loadAndPlayMediaA(Media playableMedia)
{
if((player != null))
{
player.stop();
}
media = playableMedia;
player = new MediaPlayer(media);
player.play();
}
I then immediately call:
public void prepareMedia()
{
view.setMediaPlayer(jfxMediaPlayer.getMediaPlayer());
view.setPreserveRatio(preserveRatio);
view.setFitWidth(miniaturePlayerX);
view.setFitHeight(miniaturePlayerY);
playerSlider.setValue(0.0);
}
...The key line being player = new MediaPlayer(media);. I wonder whether occasionally I am hitting the split second where the MediaView is trying to get the next frame, but failing because the media has been re instantiated. (?)
What's the best way to load up a new video?
I don't know if you haven't found a solution yet...
I had the same problem and solved it by following code:
setOnDragDropped(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragDropped");
event.setDropCompleted(true);
}
});
setOnDragExited(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragExited");
Dragboard db = event.getDragboard();
ArrayList<Object> f = (ArrayList<Object>) db.getContent(DataFormat.FILES);
for(Object o:f)
System.out.println(o.getClass().getName() + ":" + o);
File file = (File) f.get(0);
newMedia(file.toURI());
}
});
setOnDragOver(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragOver");
event.acceptTransferModes(TransferMode.ANY);
}
});
public void newMedia(URI uri)
{
m = new Media(uri.toASCIIString());
mp = new MediaPlayer(m);
mV = new MediaView(mp);
mp.setOnReady(new Runnable()
{
#Override
public void run()
{
mp.play();
}
});
}
In the DragDropped handler I call setDropCompleted to call the DragExited handler. Then I get the File out of the Dragboard and create a new MediaPlayerInstance. And then, you aren't allowed to call play immideately, else nothing will happen. You need to call play in the OnReady Handler, or at least after the MediaPlayer's status has been changed to Ready.
The Error will still appear, but it should work now ;)