Facebook Unity SDK FB.Feed causes NullReferenceException - facebook

I'm having a problem when using the Facebook Unity API, calling the FB.Feed() method. It winds up giving this error:
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.GUILayoutUtility.DoGetRect (UnityEngine.GUIContent content,
UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at
C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:264)
which is immediately followed by:
ArgumentException: Getting control 1's position in a group with only 1 controls
when doing Repaint
I know the second error is usually caused in Unity by GUI elements changing between GUI event calls, etc. In my case, however, I'm not doing anything within OnGUI at all. In fact, because of tearing my hair out trying to figure out what the problem is, I created a totally new project - 1 scene with basic buttons to login, and then "brag" using the FB.Feed. I've written it the exact way that their documents show, and I get the exact same error.
I'm hoping maybe someone might be able to shed some light on what I'm missing or doing wrong.
Here is complete code in my simple barebones scene that also causes this error:
void Start()
{
FB.Init(OnInitComplete, OnHideUnity);
}
void OnInitComplete()
{
Debug.Log("FB Initialized");
}
void OnHideUnity(bool isGameShown)
{
Debug.Log("OnHideUnity");
if (!isGameShown)
Time.timeScale = 0;
else
Time.timeScale = 1;
}
void Update()
{
}
void OnGUI()
{
if (!FB.IsLoggedIn)
{
if (GUI.Button(new Rect(10, 10, 100, 30), "Login"))
FBLogin();
}
else
{
if (GUI.Button(new Rect(10, 50, 100, 30), "Brag"))
{
Brag();
}
}
}
void Brag()
{
FB.Feed(
linkCaption: "This is testing the testapp FEED",
picture: "http://myapp.com/myapplogo.jpg",
linkName: "Foo Link",
link: "http://apps.facebook.com/" + FB.AppId + "/?challenge_brag=" + (FB.IsLoggedIn ? FB.UserId : "guest")
);
}
void FBLogin()
{
FB.Login("email, publish_actions", OnLoggedIn);
}
void OnLoggedIn(FBResult result)
{
if (FB.IsLoggedIn)
Debug.Log("Logged in successfully");
}
My Facebook API is version 140220, and my Unity is 4.3.4
I'll do my best to answer any other questions for info I've missed
I've also tried using the FB API version 131022, and have the same results.
This error also happens with the FriendSmash example and as well with the InteractiveConsole example scene provided with the plugin.
I should also point out that the Window does open for the post, and loads the image, link, etc. The exception prevents anything else from working however
Additional Info: I've found that when the app is ran on an actual android device, the feed post works with no problem. It only appears to have this error within the Unity editor. I have another issue with test users logging in on the android device - they can't if the device has the Facebook app itself installed, but that issue probably warrants a separate question

I think it's just not getting all of the resources it's asking for. The docs say not to worry about it, the editor can only do so much. I get the one below. Unfortunately though, mine is not working on the device, but if yours is, I wouldn't worry about it too much.
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.GUILayoutUtility.DoGetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:264)
UnityEngine.GUILayoutUtility.GetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:257)
Facebook.FbSkinnedDialog.TwoButtonBar (System.String label, System.String cancelLabel)
Facebook.FeedDialog.UpdateDialog (Int32 windowID)
Facebook.FbSkinnedDialog.GeneralUpdateDialog (Int32 windowId)
UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUI.cs:1395)

Related

Unity3D New Input System: Is it really so hard to stop UI clickthroughs (or figure out if cursor is over a UI object)?

Even the official documentation has borderline insane recommendations to solve what is probably one of the most common UI/3D interaction issues:
If I click while the cursor is over a UI button, both the button (via the graphics raycaster) and the 3D world (via the physics raycaster) will receive the event.
The official manual:
https://docs.unity3d.com/Packages/com.unity.inputsystem#1.2/manual/UISupport.html#handling-ambiguities-for-pointer-type-input essentially says "how about you design your game so you don't need 3D and UI at the same time?".
I cannot believe this is not a solved problem. But everything I've tried failed. EventSystem.current.currentSelectedGameObject is sticky, not hover. PointerData is protected and thus not accessible (and one guy offered a workaround via deriving your own class from Standalone Input Module to get around that, but that workaround apparently doesn't work anymore). The old IsPointerOverGameObject throws a warning if you query it in the callback and is always true if you query it in Update().
That's all just mental. Please someone tell me there's a simple, obvious solution to this common, trivial problem that I'm just missing. The graphics raycaster certainly stores somewhere if it's over a UI element, right? Please?
I've looked into this a fair bit and in the end, the easiest solution seems to be to do what the manual says and put it in the Update function.
bool pointerOverUI = false;
void Update()
{
pointerOverUI = EventSystem.current.IsPointerOverGameObject();
}
Your frustration is well founded: there are NO examples of making UI work with NewInput which I've found. I can share a more robust version of the Raycaster workaround, from Youtube:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
/* Danndx 2021 (youtube.com/danndx)
From video: youtu.be/7h1cnGggY2M
thanks - delete me! :) */
public class SCR_UiInteraction : MonoBehaviour
{
public GameObject ui_canvas;
GraphicRaycaster ui_raycaster;
PointerEventData click_data;
List<RaycastResult> click_results;
void Start()
{
ui_raycaster = ui_canvas.GetComponent<GraphicRaycaster>();
click_data = new PointerEventData(EventSystem.current);
click_results = new List<RaycastResult>();
}
void Update()
{
// use isPressed if you wish to ray cast every frame:
//if(Mouse.current.leftButton.isPressed)
// use wasReleasedThisFrame if you wish to ray cast just once per click:
if(Mouse.current.leftButton.wasReleasedThisFrame)
{
GetUiElementsClicked();
}
}
void GetUiElementsClicked()
{
/** Get all the UI elements clicked, using the current mouse position and raycasting. **/
click_data.position = Mouse.current.position.ReadValue();
click_results.Clear();
ui_raycaster.Raycast(click_data, click_results);
foreach(RaycastResult result in click_results)
{
GameObject ui_element = result.gameObject;
Debug.Log(ui_element.name);
}
}
}
So, just drop into my "Menusscript.cs"?
But as a pattern, this is terrible for separating UI concerns. I'm currently rewiring EVERY separately-concerned PointerEventData click I had already working, and my question is, Why? I can't even find how it's supposed to work: to your point there IS no official guide at all around clicking UI, and it does NOT just drop-on-top.
Anyway, I haven't found anything yet which makes new input work easily on UI, and definitely not found how I'm going to sensibly separate Menuclicks from Activityclicks while keeping game & ui assemblies separate.
Good luck to us all.
Unity documentation for this issue with regard to Unity.InputSystem can be found at https://docs.unity3d.com/Packages/com.unity.inputsystem#1.3/manual/UISupport.html#handling-ambiguities-for-pointer-type-input.
IsPointerOverGameObject() can always return true if the extent of your canvas covers the camera's entire field of view.
For clarity, here is the solution which I found worked best (accumulated from several other posts across the web).
Attach this script to your UI Canvas object:
public class CanvasHitDetector : MonoBehaviour {
private GraphicRaycaster _graphicRaycaster;
private void Start()
{
// This instance is needed to compare between UI interactions and
// game interactions with the mouse.
_graphicRaycaster = GetComponent<GraphicRaycaster>();
}
public bool IsPointerOverUI()
{
// Obtain the current mouse position.
var mousePosition = Mouse.current.position.ReadValue();
// Create a pointer event data structure with the current mouse position.
var pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = mousePosition;
// Use the GraphicRaycaster instance to determine how many UI items
// the pointer event hits. If this value is greater-than zero, skip
// further processing.
var results = new List<RaycastResult>();
_graphicRaycaster.Raycast(pointerEventData, results);
return results.Count > 0;
}
}
In class containing the method which is handling the mouse clicks, obtain the reference to the Canvas UI either using GameObject.Find() or a public exposed variable, and call IsPointerOverUI() to filter clicks when over UI.
Reply to #Milad Qasemi's answer
From the docs you have attached in your answer, I have tried the following to check if the user clicked on a UI element or not.
// gets called in the Update method
if(Input.GetMouseButton(0) {
int layerMask = 1 << 5;
// raycast in the UI layer
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero, Mathf.Infinity, layerMask);
// if the ray hit any UI element, return
// don't handle player movement
if (hit.collider) { return; }
Debug.Log("Touched not on UI");
playerController.HandlePlayerMovement(x);
}
The raycast doesn't seem to detect collisions on UI elements. Below is a picture of the Graphics Raycaster component of the Canvas:
Reply to #Lowelltech
Your solution worked for me except that instead of Mouse I used Touchscreen
// Obtain the current touch position.
var pointerPosition = Touchscreen.current.position.ReadValue();
An InputSytem is a way to receive new inputs provided by Unity. You can't use existing scripts there, and you'll run into problems like the original questioner. Answers with code like "if(Input.GetMouseButton(0)" are invalid because they use the old system.

Can't get RunTransaction with Firebase in Unity to work

I'm working on a game in Unity, using Firebase for user and game data.
Everything is fine saving the game to Unity, but in Multiplayer I have the challenge to pair an open game to a unique player 2.
The flow is:
1. You look for a game with a state of "open"
2. If no game is found within X seconds, a new one is created with the state of "open"
I have a query that returns open games (those with state "open")
This query is added a Firebase eventhandler
public void OnButtonLookForOpenMPGames()
{
this.OpenFirebaseGamesAsHost = this.LiveGamereference.OrderByChild("State").EqualTo(WYMSettings.MP_GAME_STATE_OPEN_TO_PLAYER2)
.LimitToFirst(3);
this.OpenFirebaseGamesAsHost.ChildAdded += this.OnOpenMPGameFound;
}
This fires fine in the handler:
private void OnOpenMPGameFound(object sender, ChildChangedEventArgs args)
{
Debug.Log("Looking for open games");
if (args.DatabaseError != null)
{
// handle errors
}
else
{
Debug.Log("Open game found (it may be my own)");
// remove event listener because we got a hit
// it will fire as many times as it's true!
this.OpenFirebaseGamesAsHost.ChildAdded -= this.OnOpenMPGameFound;
if (args.Snapshot.Child("HostId").Value.ToString() != FirebaseAuth.DefaultInstance.CurrentUser.UserId)
{
Debug.Log("Other game than mine found open");
// this.AddDelayedUpdateAction(() =>
// {
// this.MPGameLockInTransaction(args.Snapshot.Reference);
// });
this.MPGameLockInTransaction(args.Snapshot.Reference);
}
}
}
The problem: The handler passes this on to the transaction function, but it fails with an inner exception (Internal Task Faulted) - I've tried many different variations, but can't figure this one out from the official Firebase example.
Problem code:
What I want to achieve is to lock only that game to those two players, the host and the players 2 in this example querying for open games. The State is an int, but here a string for clarity.
private void MPGameLockInTransaction(DatabaseReference mpreference)
{
mpreference.RunTransaction(mutableData =>
{
MultiPlayerGame transactionMPG = mutableData.Value as MultiPlayerGame;
if (transactionMPG == null)
{
return TransactionResult.Abort();
}
if (transactionMPG.State != "open")
{
// game is taken, abort
Debug.Log("transaction aborted");
return TransactionResult.Abort();
}
transactionMPG.State = "game started";
mutableData.Value = transactionMPG;
return TransactionResult.Success(mutableData);
}).ContinueWith(task =>
{
if (task.Exception != null)
{
Debug.Log("Transactionlock to game failed" + task.Exception.ToString());
// Look over again
// not implemented yet
}
else
{
Debug.Log("starting game immediately");
this.AddDelayedUpdateAction(() => this.StartMPGameImmediatelyFromSearch());
}
});
}
This is just a guess but it might be related to threading.
In newer .Net version ContinueWith might end on a thread where most of the Unity API may not be called (including Debug.Log).
Instead you could try and use ContinueWithOnMainThread from the extensions instead which was created exactly for this reason.
With the .NET 4.x runtime, continuations may often execute in the background, whilst this extension method pushes them onto the main thread.
The .NET 3.x runtime didn't have this issue as continuations were contained within the Parse library, which did this implicitly.

Unity OnMatchList inaccesible due to its protection level

I have seen that there are more answers to similar questions, but none of these helped me. I hope you can.
I have a Unity2D shooter game and I try to make a menu for UNET. I watched a youtube tutorial from Brackeys to make the menu (https://youtu.be/V4oRs26vAw8?list=PLPV2KyIb3jR5PhGqsO7G4PsbEC_Al-kPZ&t=896) and when he runs the project it shows me the error: "error CS0122: 'UnityEngine.Networking.Match.ListMatchResponse' is inaccessible due to its protection level. I found out that this might happen when you access for example a private variable from another function, but I access a function from Unity and I can not modify its type (I believe). Any ideas? Thank you.
public void OnMatchList(bool success, string extendedInfo, ListMatchResponse matchList)
{
status.text = "";
if (matchList == null)
{
status.text = "Couldn't get room list.";
return;
}
ClearRoomList();
foreach(MatchDesc match in matchList.matches)
{
GameObject _roomListItemGO = Instantiate(roomListItemPrefab);
_roomListItemGO.transform.SetParent(roomListParent);
// Have a component sit on the gameobject
// that will take care of setting up the name / amount of users.
// as well as setting up a callback function that will join the game.
roomList.Add(_roomListItemGO);
}
}
'MatchDesc' has been renamed to 'MatchInfoSnapshot'.
Just replace it and it should work fine.

UNITY An object reference is required to access non-static member `Outline.OutlineMode'

I'm trying to create an outline when you are near it, but i'm getting all the time the same error.
void Update () {
if (Input.GetKeyDown(KeyCode.E)){
var outline = gameObject.AddComponent<Outline>();
outline.OutlineMode = Outline.Mode.OutlineAll;
outline.OutlineColor = Color.yellow;
outline.OutlineWidth = 5f;
}
}
void OnTriggerStay(Collider other) {
if (Outline.OutlineMode == Outline.Mode.OutlineAll) {
Debug.Log("test");
}
}
If i press E it works, and if i change it to ontriggerstay works too, but im trying that it only applies one time, because im getting some errors if its on. I have to say that im using an asset, called quick outline
Srry for my very bad english and explanation and thank you
add the outline to your object in Awake() then set it to disabled.
then enable it in OnTriggerEnter() and disable it in OnTriggerExit()
this will keep you from making multiple copies, and it will only be active when you are in range of your trigger

Resetting after 3 seconds unity

I have a board manager in my game, that shows what is happening, for example, if I want to buy a car and you dont have the necessary money in this board appears a message saying "You dont have enough gold".
public void setTextMonitor (string mensaje) {
textScreen = mensaje;
}
public IEnumerator DoTheDance() {
yield return new WaitForSeconds(5); // Esperar 3 seconds
textScreen = "";
}
This is my code and it's working properly, when the board shows a message after 5 seconds it's deleted but the board doesn't shows new messages and I dont know why, probably because the couroutine doesn't let setTextMonitor method to work properly dunno.
If you have another idea or other method for doing this,
I'd be really grateful
For such behavior really easy to use LeanTween asset. It's free in asset store.
Code will be close to the following:
textScreen = "You have not enough of gold";
LeanTween.DelayedCall(5f,()=>{textScreen = "";});