parse-community / Parse-SDK-dotNET

Parse SDK for .NET, Xamarin, Unity.
http://parseplatform.org
Apache License 2.0
323 stars 260 forks source link

Unity 2018.2 Application.isWebPlayer error in ParseInitializeBehaviour... #294

Closed ghost closed 5 years ago

ghost commented 6 years ago

Unity 2018.2 has removed the UnityEngine.Application.isWebPlayer property which is causing a runtime error. This is the full error:

MissingMethodException: Method not found: 'UnityEngine.Application.get_isWebPlayer'.
Parse.ParseClient.Initialize (Configuration configuration)
Parse.ParseClient.Initialize (System.String applicationId, System.String dotnetKey, System.String serverURL)
Parse.ParseInitializeBehaviour.Initialize ()
Parse.ParseInitializeBehaviour.Awake ()
ghost commented 6 years ago

I'm happy to do a fix for this myself, but it appears that Parse.ParseInitializeBehaviour is no longer in the repository? Or it it being held elsewhere?

flovilmart commented 6 years ago

Is there any reference to the unity engine in this repository?

ghost commented 6 years ago

I know there used to be, but it looks like a lot has changed. I was going by the downloads available here, but these downloads and source seem ancient. I'm not sure what the new workflow is for unity.

flovilmart commented 6 years ago

I’m not sure either. To be honest, dotNet has been left out over the years, unfortunately as no new maintainer arised. If you’re using this framework, let me know what I can do

ghost commented 6 years ago

Thanks for the quick replies. Our project is still depending on Parse and it's important that we upgrade unity to 2018.2. I tried compiling the latest master, and it all compiled fine. But when I put the Parse.dll into the project, Unity can't detect the Parse namespace. I'm not super familiar with building dlls, but if I can get it working, I could easily fix it myself I think.

flovilmart commented 6 years ago

@thefanatr any idea?

flovilmart commented 6 years ago

I know everything was revamped a few months ago, but I’m not sure where things are

keerthik commented 6 years ago

I was going to work on a PR for this fix after our current project release sprint.

The folder with Unity-specific scripts appear to have been lost in master. From 1.7.0, ParseInitializeBehaviour and ParseInstallation.Unity.cs are present here. You can probably copy and use these files as is after the fix to address the Unity error, if anyone wants to address this before I have the time to...

flovilmart commented 6 years ago

@keerthik since this PR https://github.com/parse-community/Parse-SDK-dotNET/pull/284 I believe the project was refactored into 100% dotNet standard. I'm not sure what in means for Unity support. If you can provide guidance I'd love us to maintain the unity compatibility.

TheFanatr commented 6 years ago

Hi. I wrote a solution to this, explaining the issue and how to solve it, but I closed the tab and now it's gone. If only I could pay attention to what I am doing. TL;DR : Hang on a sec.

TheFanatr commented 6 years ago

Basically, the issue here is that the OP is using an old version of Parse which references an outdated UnityEngine SDK assembly, and specifically uses a property called isWebPlayer, which is supposed to return a value for whether or not the code is running in the Unity Web Player. Because the Unity Web Player no longer exists, the aforementioned property no longer exists in newer versions of the assembly. That is why there are errors in the Unity Editor. In order to use the a compiled copy of the master branch of this repository, the Unity Editor needs to be configured for .NET Standard 2.0 support. This can be done by opening the Unity Player Settings in the Inspector via Navigating through Edit > Project Settings > Player and scrolling down to the Configuration header in the Inspector, and changing the setting for Scripting Runtime Version to .NET 4.x Equivalent then restarting the Unity Editor, then changing the setting for Api Compatibility Level to .NET Standard 2.0 under the same header. This change should allow the Unity Editor to see the compiled Parse SDK and make it possible to be referenced in the game's source code.

flovilmart commented 6 years ago

@TheFanatr can we put that in the docs / readme somewhere? also can you confirm / deny the docs are still relevant: https://docs.parseplatform.org/unity/guide/

ghost commented 6 years ago

@TheFanatr So you're saying that I can keep the current (old) version I have, or should I use the latest commit on master? Following the steps you provided (with the old version) seems to give this weird error whenever I reference System.Threading.Tasks:

The type 'Task' exists in both 'Parse.Unity, Version=1.7.0.0, Culture=neutral, PublicKeyToken=null' and 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'

It seems like the .net tasks in the dll are conflicting with the tasks in unity?

TheFanatr commented 6 years ago

@brendanlk If you configure Unity for .NET Standard 2.0 support I would recommend you use the latest master branch, as the old Parse SDK contained .NET Framework libraries added post-framework-2.0 in order for the Parse codebase to work properly in Unity because in the default configuration it uses a .NET Framework 2.0 API subset, whereas Parse needs Framework 4.x I believe. These extra libraries are no longer needed as .NET Standard 2.0 already includes them. Just compile the SDK and add it to your assets.

TheFanatr commented 6 years ago

Basically, the Task API and some others from post-2.0 .NET Framework were integrated into the Unity-specific version of the Parse SDK because Unity didn't have them by default. In .NET Standard 2.0 API Subset mode, Unity includes all that by default. Basically, the code you write targets .NET Franework 4.6, but the project references some kind of .NET Standard 2.0 compatibility provision assembly.

TheFanatr commented 6 years ago

I'll try take a look at the docs and update them if needed later today.

ghost commented 6 years ago

@TheFanatr I have upgraded our unity project to .NET 4.x (Mono) and compiled the latest master. After fixing some compiler issues (on our end) we are getting this error:

Unloading broken assembly Assets/Plugins/Parse/Parse.dll, this assembly can cause crashes in the runtime

I'm not sure how unity knows that it will cause an issue. But when running the game and calling Parse.ParseUser.LogInAsync(), I'm getting this error:

TypeLoadException: Could not load type of field 'Parse.Common.Internal.StorageController:fileTask' (2) due to: Could not load file or assembly 'StandardStorage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. assembly:StandardStorage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null type: member:(null) signature: Parse.Core.Internal.ParseCorePlugins.get_InstallationIdController () (at :0) Parse.Core.Internal.ParseCorePlugins.get_CommandRunner () (at :0) Parse.Core.Internal.ParseCorePlugins.get_UserController () (at :0) Parse.ParseUser.get_UserController () (at :0) Parse.ParseUser.LogInAsync (System.String username, System.String password, System.Threading.CancellationToken cancellationToken) (at :0) Parse.ParseUser.LogInAsync (System.String username, System.String password) (at :0)

TheFanatr commented 6 years ago

Import a compiled copy of StandardStorage as well, along with all external dependencies, and it should work. Eventually, a Parse package can be added to the Unity Asset Store containing all the needed assemblies and resources to make life easier, but until then I believe you have to reference all of Parse's dependencies (recursive, of course) that are not part of .NET Standard 2.0's coverage and not referenced by Unity manually. I am currently attempting to make a CRUD testing app for the Parse .NET SDK in Unity in order to verify that it does fully work on the platform, but due to the lack of an closely-accessible internet connection, I haven't been able to work on it much. I will release it along with any fixes needed to Parse and/or dependencies I have control over within the next few days. I believe there may be another issue with saving data on special platforms and/or targets such as when using Parse with Unity targeting Unity WebGL or with Blazor, but I have yet to confirm either.

fsufyan commented 6 years ago

@TheFanatr Can you provide more details about the inclusion of those external dependence? I am stuck at "this assembly can cause crashes in the runtime"

Currently using Unity 2018.2.1 trying to upgrade an old Unity 5.6 Parse project. Your help is very appreciated

thibautvdu commented 6 years ago

Any input on this ? I tried several things, building it without the references to the depreciated functions, etc. with no luck. The functions (SignUpAsync, etc.) never call back.

ghost commented 5 years ago

I'm still having trouble getting this working too. Is it only @TheFanatr working on this?

TheFanatr commented 5 years ago

I don't know who else is working on this at the moment. I will look into getting a sample running, and will post it here.

flovilmart commented 5 years ago

@TheFanatr you're the reference person now! and a maintainer if you want to :)

TheFanatr commented 5 years ago

@flovilmart Ok, cool. Thanks.

To update everyone on the situation here, it would seem that because of the way that Unity is handling assembly generation for in-editor playtest builds, the needed family of properties within the value of the Microsoft.Extensions.PlatformAbstractions.PlatformService.Default.Application property are returning null, causing the Path.Combine operation to fail silently, making the execution crash when the null value result is passed to the constructor for FileInfo, which manages file storage in my modified version of Parse that no longer depends on StandardStorage. The current master branch of this repository would also likely not work because the same problem of not being able to find the name and version of the assembly would be present. I am unsure as to if StandardStorage would fix this issue, but it is essentially redundant nonetheless because .NET Standard 2.0 already contains APIs specifically included to handle platform-agnostic file operations. I have found a workaround and am attempting to implement a fix. You can see my progress on my fork of Parse-SDK-dotNET. After this, I will attempt to integrate a LiveQuery implementation, as well as supporting a server-side use case for the Parse .NET SDK via making alternative ParseUser interaction structures available as dependency injections (one class would have it implemented statically like it is now, and another would have it instantiable so that multiple user logins can be loaded concurrently based on the session token stored in the browser's local storage, for ASP.NET Core usage). That last suggestion was based on my personal need, for a project I am working on, so if I end up just not using Parse, it may not ever get implemented.

TheFanatr commented 5 years ago

It would seem that no matter what I do, if I try to reflectively extract metadata about the assembly, the operation will fail, and using the Unity-provided reflection utilities, the only result I get is the name Assembly-CSharp, which is the default scripting project name. After some searching, it would seem that some hard-coded values for the Unity Application's version, name, and company are embedded into the assembly, and they still seem to be inaccessible via reflection, but are accessible via the Unity Engine SDK's Application class. In order to accommodate this, and to fix any erroring within Unity-compiled projects when using the Parse .NET SDK, I will likely have the cache location be configurable, or at least make it possible to set the values for version and name that the caching system should prefer to use. If I only make the metadata values configurable, then I will likely change the path to be the simply the location of System.Environment.SpecialFolder.LocalApplicationData, with the file name app-1.0.0.0.pcache or cacheIdentifier.pcache with cacheIdentifier being a settable cache identification property, in order to basically completely eradicate storage path collisions with unrelated same-named programs that use the same caching folder structure.

The following is the Unity-specific code to successfully generate the persistent storage path that the Parse SDK cannot currently generate for Unity.

System.IO.Path.GetFullPath(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), UnityEngine.Application.productName, UnityEngine.Application.version));

Note that for this to work, the Unity Player must be configured for .NET Standard 2.0 support, otherwise all of the referenced types must be referenced manually if they are not included by your target .NET Framework API coverage.

TheFanatr commented 5 years ago

I also need to update the documentation on this, as it seems to be very outdated.

flovilmart commented 5 years ago

Thanks for the update! This is really appreciated.

TheFanatr commented 5 years ago

This is proving significantly more tedious than previously anticipated because ParseClient.Initialize(ParseClient.Configuration configuration) cannot be trusted to be the first time the persistent storage path needs to be used, so I have to come up with a default and once the actual one is initialized, I have to copy it's contents to the new path.

TobiasPott commented 5 years ago

Hi everyone, I'm a bit in a hurry at the moment but will prepare a pull request later this day or next week.

In my fork of this repository I've targeted the file access when using Parse inside a Unity application on mobile platforms like Android and iOS as we use Parse for one of our backend structure and the communication with it. You might take a look at it if you like: https://github.com/TobiasPott/Parse-SDK-dotNET

The problem in this case is the System.Environment.SpecialFolder.LocalApplicationData enumeration value which actually is supported on iOS or Android when running inside the Unity context but unfortunately pointing to file system locations an app fill never get access to for writing. Thus It is necessary to take folders not provided by the .NET runtime/system but by Unity which does so via the Application.persistentDataPath property.

I've modified the repository with a UNITY compiler flag and an additional project inside the solution to avoid too much hassle with separate source files but it requires a version of the UnityEngine.dll to be available to reference to (which is not included in my repository as I'm not sure if I can provide it without legal issues ^^).

At the moment I'm not quite sure which version of Unity started supporting .NET Standard 2.0 or .NET 4.5 but using Unity 2018.2 does work for me. I'll add more details on this as soon as I find the time compiling Parse against older Unity versions.

Kind regards and thanks for the .NET SDK =) It helps us a lot with the current project.

qruxtapose commented 5 years ago

Hi @TobiasPott

Thanks for providing your fork. I was actually able to build the project without UnityEngine.dll. Maybe there is something I'm missing here but nothing in the project looks to be Unity specific (and as such doesn't seem to work with Unity). Any ideas?

TobiasPott commented 5 years ago

Hi @qruxtapose Hmm, this is strange. It doesn't seem to have pushed the changes to the remote on github. I'll have a look at it tomorrow when I'm back in office. Sorry for that one =/

qruxtapose commented 5 years ago

@TobiasPott No problem at all! Thanks for looking into it

TobiasPott commented 5 years ago

Hm for unknown reason the website has eaten my comment from 2 min ago -.-

I'm back in office and checked my git. Missed the push to the remote last week and sorry for your inconvenience.

You may check the master branch for the changes I've mentioned last week.

If you are facing any problems with Unity versions prior 2018.2 don't hesitate to ask and I'll bump backward compatibility up a bit on my ToDo list.

TheFanatr commented 5 years ago

GitHub is acting up at the moment. I was going to post something important but apparently that's not an option right now because it might get swallowed. FYI: https://status.github.com/messages

TobiasPott commented 5 years ago

Yeah I've noticed that already and got a bit angry this morning -.- (related to another project)

I've discovered that caching the session is not working properly right now with my changes and currently digging into it for a fix. (hopefully github doesn't eat this one)

qruxtapose commented 5 years ago

I was able to build without much trouble (I had to install Microsoft.DotNet.PlatformAbstractions, Microsoft.Extensions.PlatformAbstractions and StandardStorage from Nuget). Imported the Parse library into my Unity project and it appears to be mostly work (save session caching). I'll try and poke around for a fix as well.

Edit:

In editor I can get through my usual user creation process. In android it appears to go through successfully but I get some errors.

MissingMethodException: Constructor on type 'Parse.Common.Internal.FlexibleListWrapper2[[System.Collections.Generic.IDictionary2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' not found.

TobiasPott commented 5 years ago

@qruxtapose Have you got it running in an iOS or Android build out of Unity? I did get some errors about a "broken assembly" which might cause errors at runtime when using the build from this Parse repository and didn't even get it to initialize on Android (built from Unity).

qruxtapose commented 5 years ago

@TobiasPott Yes. It's running in Android (built from Unity) but with errors. It does appear to initialize and I'm able to download the Parse.Config just fine. After that it fails my authentication process on Android where it succeeds in Unity editor.

TobiasPott commented 5 years ago

@qruxtapose got similar issues when using the official repository thus I sticked to @TheFanatr repository. Edit: But I'm not sure whether any changes there may have affected it or my issues originated from other problems.

I'm not yet that deep into Parse to understand the inner workings that good to help with the specific issues but I did some more adjustments on my forked repo to get Unity Editor support and fix caching as it did not work properly on my side..

hqMoura commented 5 years ago

There is a fix for this?

I still facing the same issue with the webPlayer exception.

TobiasPott commented 5 years ago

@hqMoura: What do you mean with "webPlayer" exception, the same as the OP mentioned? Are you using assemblies build from this repository or where did you get them from?

The latest commit in the master branch does not contain any references to Application.isWebPlayer from UnityEngine.dll anymore and thus should not give any exceptions due to a call to it. This is unless you use an older version or something from the 1.8.0 branch. As discussed above some issues exists when using the latest commit in this repository within Unity and @TheFanatr has forked it and I did a fork of that repository as I needed a working build for Unity 2018.2 You may take a look at these repositories. (This said, the Parse version in these repositories require your Unity project to support .NET Standard or .NET 4.6).

pprwght2 commented 5 years ago

@TobiasPott I recompiled your and @TheFanatr solutions

I can't seem to get past initalization ParseClient.Initialize(config);

NullReferenceException: Object reference not set to an instance of an object Parse.ParseClient+Configuration+VersionInformation..cctor ()

TobiasPott commented 5 years ago

@pprwght2 Could you please give us some more information about your setup? Which Unity version are you using and which of the output assemblies are you using? Are you using Parse inside the Editor (via Editor-script) or during runtime? Are you testing in play-mode (in-editor) or with a built application on a target platform?

Edit: Did you switch your project to use the ".NET 4.x Equivalent" in the "Other Settings" section of your projects player settings?

Edit: Another question which comes to my mind: could you try using Parse.dll within a .NET console application and use the initialization? I'm wondering if it is more a general thing with parse or with the Unity adjustments.

pprwght2 commented 5 years ago

@TobiasPott

Unity 2018.2.14f.1, compiled to release build and copied everything under VS Release dir to Assets/Parse, settings are se to to .NET 4.x Equivalent, API comp Level 4.x

pprwght2 commented 5 years ago

@TobiasPott

It's working In a .Net console application. In Unity it fails at ParseClient.Initialize(new ParseClient.Configuration ...

this is all at runtime in-editor mode

NullReferenceException: Object reference not set to an instance of an object Parse.ParseClient+Configuration+VersionInformation..cctor () (at Parse-SDK-dotNET-master/Parse/Public/ParseClient.cs:130) Rethrow as TypeInitializationException: The type initializer for 'VersionInformation' threw an exception. Parse.ParseClient.Initialize (Parse.ParseClient+Configuration configuration) (at /Parse-SDK-dotNET-master/Parse/Public/ParseClient.cs:240) test.cs+c__Iterator13.MoveNext () (at Assets/project/src/test.cs:6198) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at unity/build/Runtime/Export/Coroutines.cs:17) UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)

c__Iterator11:MoveNext() (at Assets/proj/src/test.cs:6174) UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
TobiasPott commented 5 years ago

Hm could you check if you copied the Parse.dll also? The output are actually explicit for each platform and Parse.dll is for .NET (outside Unity) Parse.Unity.dll is for Unity runtime (devices, and editor play-mode) Parse.Unity.Editor.dll is for editor scripting.

Remove the Parse.dll as it uses only .NET stuff which is not available in Unity as the way version and application information is gathered is not provided by Unity the way Parse assumes it. You can leave the Parse.Unity.Editor.dll when you never intend to use Parse from editor scripts. You may check the platform settings of the Parse.Unity.dll and Parse.Unity.Editor.dll (is required when having the editor dll in your project to avoid ambiguities.

Sorry for the delay, I've forgot to answer yesterday when in office =(

pprwght2 commented 5 years ago

Thanks for answer, using Parse.Unity.dll only, 2018.2.14f.1 runtime in-editor fails with

NullReferenceException: Object reference not set to an instance of an object Parse.ParseClient+Configuration+VersionInformation..cctor () (at <4e88660be348469a8ef9bebf9b56de11>:0) Rethrow as TypeInitializationException: The type initializer for 'VersionInformation' threw an exception. Parse.ParseClient.Initialize (Parse.ParseClient+Configuration configuration) (at <4e88660be348469a8ef9bebf9b56de11>:0) testParse.Start () (at Assets/testParse.cs:13)

It's a clean project, only with gameobject attached with C# in Start()

ParseClient.Initialize(new ParseClient.Configuration { ApplicationID = appIDString, MasterKey = appMasterKey, ServerURI = appServerURI });

TobiasPott commented 5 years ago

@pprwght2 Would you mind zipping and sending me your project so I can have a look at it? Remove all credentials and server information and send me a link as I can't reproduce this issue with a clean project =/ (you might use PM for the link)

TobiasPott commented 5 years ago

@pprwght2 There is actually an issue when building the Unity and Unity.Editor assemblies from the repository. The assembly in your project is quite different from the one resulting from my local repo. I'll need to get into this and check what is going wrong when building from a cloned remote repo.

Edit: In "Release" setup when building from VS the Parse.Unity and Parse.Unity.Editor projects lack compiler flags who take care of switching to the correct code. Add 'UNITY' to the Parse.Unity project as a compiler symbol Add 'UNITY_EDITOR; UNITY' to the Parse.Unity.Editor project as compiler symbols

I'm not quite sure if this is all and will take a look into this later this evening or tomorrow when I'm back in office.

pprwght2 commented 5 years ago

@TobiasPott It is working now! Setting compiler flag and copying UnityEngine.dll did it. One more question, I will now start integrating code into bigger project, you mentioned this: "I've discovered that caching the session is not working properly right now with my changes and currently digging into it for a fix. (hopefully github doesn't eat this one)". Would you recommend this repo for production use or is it better to wait for new updates? Thanks again!