Unity's IPreprocessBuildWithReport.OnPreprocessBuild throws an error - unity3d

I got a tiny script that creates a text file in Resources folder before building that needs to be included in the build. So I wrote this script using Unity's IPreprocessBuildWithReport:
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using System.IO;
class MyCustomBuildProcessor : IPreprocessBuildWithReport
{
public int callbackOrder { get { return 0; } }
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
File.WriteAllText(
Application.dataPath + "/Resources/version.txt",
string.Format("{0}", PlayerSettings.Android.bundleVersionCode));
AssetDatabase.Refresh();
}
}
Note the AssetDatabase.Refresh(); statement at the end. It makes sure Unity becomes aware of the change and includes the updated file in the build. Now, whenever time I change the bundleVersionCode and press build, Unity updates the file as expected but the build fails with this pretty generic error:
However, if I try to build the second time with the same bundleVersionCode than no file changes occur and the build succeeds.
So I guess the AssetDatabase.Refresh() doesn't really work in OnPreprocessBuild(), or am I doing something obviously stupid again? Can anyone suggest a workaround?
EDIT:
Please ignore the first two errors, just Unity doesn't like me when I'm excluding files from build by the ~ postfix.

Related

The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' FIX

Can someone please help me with this, am trying to use OpenFileDialog class from System.Windows.Forms to open a file dialog and read the selected file. Then, this error showed up. I've referenced it but still the same, below is the code.
`using UnityEngine
using UnityEngine.UI
using System.Windows.Forms;
public class OpenFileButtonScript : MonoBehaviour
{
public TextFieldScript textFieldScript;
public void OpenFile()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
string text = System.IO.File.ReadAllText(filePath);
textFieldScript.inputField.text = text;
}
}
}`
It may look like you have access to all of the native Window system libraries, but it just looks like it. In actuality, a lot of the time you're simply given stubs, or shims, that look like the full Window libraries, because there's a certain element that Unity wants to use from those namespaces. If you think about it, the code you present above, what do you think it should do on Android or Nintendo devices? The simple answer is, it simply won't work.
Generally in cases like this, you have to gain access to the native operating system, and perform those calls directly. For example, there is a file browser asset on the Asset Store, that does this for you. It's not free, because the process isn't trivial.
Depending on how much effort you want to put in, you CAN read files from the local file stores (to varying degrees based on platform). It's possible to read the list of files in a location, and use either uGUI or UIToolkit to create your own File Open Dialogue box. Again, this isn't a trivial task either. So you have to be sure that you'd want to go down that path.

Unity google-play-core review issue

I added the google play core package as instructed in the repo, and added the code according to the documentation here
I receive the following error: CS0246: The type or namespace name 'PlayAsyncOperation<,>' could not be found (are you missing a using directive or an assembly reference?)
This error shows at _reviewManager.RequestReviewFlow(); and _reviewManager.LaunchReviewFlow(_playReviewInfo)
Any idea what could be the issue?
My full code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Google.Play.Review;
public class ReviewCodes : MonoBehaviour
{
private ReviewManager _reviewManager;
private PlayReviewInfo _playReviewInfo;
// Start is called before the first frame update
void Start()
{
StartCoroutine(RequestReviews());
}
// Update is called once per frame
void Update()
{
}
IEnumerator RequestReviews()
{
// Create instance of ReviewManager
_reviewManager = new ReviewManager();
var requestFlowOperation = _reviewManager.RequestReviewFlow();
yield return requestFlowOperation;
if (requestFlowOperation.Error != ReviewErrorCode.NoError)
{
// Log error. For example, using requestFlowOperation.Error.ToString().
yield break;
}
_playReviewInfo = requestFlowOperation.GetResult();
var launchFlowOperation = _reviewManager.LaunchReviewFlow(_playReviewInfo);
yield return launchFlowOperation;
_playReviewInfo = null; // Reset the object
if (launchFlowOperation.Error != ReviewErrorCode.NoError)
{
// Log error. For example, using requestFlowOperation.Error.ToString().
yield break;
}
// The flow has finished. The API does not indicate whether the user
// reviewed or not, or even whether the review dialog was shown. Thus, no
// matter the result, we continue our app flow.
}
}
"are you missing a using directive or an assembly reference?"
These are following situation which causes a compiler error:
Check if the name of the type or namespace is correct, as most of the time you can get this error when the compiler cannot find that namespace.
Check if you have added the reference to the assembly that contains the namespace. Ex: Your code can be in "using XYZ;"
but if your project does not reference assembly then you can get a CS0246 error.
Try: using Google.Play.Common;
the order might be your problem. You also not only have to import the Google Core Package. You also have to import the Google Review Plugin. The core plugin overrides assemblies and files which then can't be used by the review assembly.
Step-by-Step solution:
Import google-play-plugins-1.7.0.unitypackage
Import com.google.play.review-1.7.0.unitypackage
Make sure to restart your IDE or reload the code in your IDE after this steps.
In older versions in unity there was an option to download this packages with the help of the unity package manager. Now you have to use the official github repository from Google. See Downloading the plugins or just use the official provided .unitypackages from Google

MRTKv2 'Interactable' script for dynamically added gameobjects

So I want to be able to use the 'Interactable' script in MRTKv2 for some of my gameobjects. I've had success when attaching the 'Interactable' and 'NearInteractionTouchable' script to the corresponding gameobject, but not when attempting to add the same functionality dynamically in the script.
Since the 'Microsoft.MixedReality.Toolkit.UI' isn't currently defined, I know I can't reference the 'Interactable' script in the script directly, but in using the 'IMixedRealityFocusHandler', 'IMixedRealityPointerHandler', 'IMixedRealityTouchHandler', and 'IMixedRealityInputHandler' interfaces instead I still haven't had success in receiving any input.
The namespaces currently defined by MRTKv2
All of the namespaces in MRTKv2
Event mapping from HL1 to HL2
Any ideas on a step that I'm missing to recreate the functionality of the 'Interactable' script that can be attached to gameobjects dynamically?
Interactable does exist in the MRTK namespace under using Microsoft.MixedReality.Toolkit.UI; perhaps you are missing references to your projects? The following code works for me, using the latest mrtk_development:
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.UI;
using UnityEngine;
public class AddInteractableTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
gameObject.AddComponent<Interactable>();
gameObject.AddComponent<NearInteractionTouchable>();
}
}

Can you help me detect missing directive (extension method not found)

I am starting to play with rx extension for .NET and downloaded some sources.
Basic examples works fine, however there is a function causing an error apparently because an extension method is not declared (should be imported with some directive)
The line of code causing the error is the 2nd one (list.Run) in the commented source (I commented to be able to compile):
/*
protected static void WriteListToConsole<T>(IEnumerable<T> list, string name) {
list.Run(
value => Console.WriteLine("{0} : {1}", name, value),
() => Console.WriteLine("{0} Completed", name));
}
*/
it looks like Rx defines somewhere an ext. method Run to IEnumerable but I am not importing it.
I installed Rx v2.0.3 SDK.msi , added references in my project to all System.Reactive.* I found and used:
using System;
using System.Reactive.Subjects;
using System.Reactive.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
I also tried use the Nuget rx.main and ix.main packages in my project but the error is always there.
Searching on google IEnumerable + Run gives me no info.
Any help appreciated.
Thanks
Hi I think that is a very old sample you are looking at.
This is now replaced with the extension method ForEach which can be found in the System.Linq namespace in the System.Interactive dll (IX-Main nuget I think).
You will also note that the OnCompleted function parameter is gone, cause well it was a silly idea. The new code should look like:
protected static void WriteListToConsole<T>(IEnumerable<T> list, string name)
{
list.ForEach(value => Console.WriteLine("{0} : {1}", name, value));
Console.WriteLine("{0} Completed", name);
}

NUnit extension

Hi All i have a question regarding NUnit Extension (2.5.10).
What i am trying to do is write some additional test info to the
database. For that i have created NUnit extension using Event
Listeners.
The problem i am experiencing is that public void
TestFinished(TestResult result) method is being called twice at
runtime. And my code which writes to the database is in this method
and that leaves me with duplicate entries in the database. The
question is: Is that the expected behaviour? Can i do something about
it?
The extension code is below. Thanks.
using System;
using NUnit.Core;
using NUnit.Core.Extensibility;
namespace NuinitExtension
{
[NUnitAddinAttribute(Type = ExtensionType.Core,
Name = "Database Addin",
Description = "Writes test results to the database.")]
public class MyNunitExtension : IAddin, EventListener
{
public bool Install(IExtensionHost host)
{
IExtensionPoint listeners = host.GetExtensionPoint("EventListeners");
if (listeners == null)
return false;
listeners.Install(this);
return true;
}
public void RunStarted(string name, int testCount){}
public void RunFinished(TestResult result){}
public void RunFinished(Exception exception){}
public void TestStarted(TestName testName){}
public void TestFinished(TestResult result)
{
// this is just sample data
SqlHelper.SqlConnectAndWRiteToDatabase("test", test",
2.0, DateTime.Now);
}
public void SuiteStarted(TestName testName){}
public void SuiteFinished(TestResult result){}
public void UnhandledException(Exception exception){}
public void TestOutput(TestOutput testOutput){}
}
}
I have managed to fix the issue by simply removing my extension
assembly from NUnit 2.5.10\bin\net-2.0\addins folder. At the moment
everything works as expected but i am not sure how. I thought that you
have to have the extension/addin assembly inside the addins folder.
I am running tests by opening a solution via NUnit.exe. My extension
project is part of the solution i am testing. I have also raised this issue with NUnit guys and got the following explanation:
Most likely, your addin was being loaded twice. In order to make it easier to test addins, NUnit searches each test assembly for addins to be loaded, in addition to searching the addins directory. Normally, when you are confident that your addin works, you should remove it from the test assembly and install it in the addins folder. This makes it available to all tests that are run using NUnit. OTOH, if you really only want the addin to apply for a certain project, then you can leave it in the test assembly and not install it as a permanent addin.
http://groups.google.com/group/nunit-discuss/browse_thread/thread/c9329129fd803cb2/47672f15e7cc05d1#47672f15e7cc05d1
Not sure this answer is strictly relevant but might be useful.
I was having a play around with the NUnit library recently to read NUnit tests in so they could easily be transfered over to our own in-house acceptance testing framework.
It turns out we probably wont stick with this but thought it might be useful to share my experiences figuring out how to use the NUnit code:
It is different in that it doesn't get run by the NUnit console or Gui Runner but just by our own console app.
public class NUnitTestReader
{
private TestHarness _testHarness;
public void AddTestsTo(TestHarness testHarness)
{
_testHarness = testHarness;
var package = new TestPackage(Assembly.GetExecutingAssembly().Location){AutoBinPath = true};
CoreExtensions.Host.InitializeService();
var testSuiteBuilder = new TestSuiteBuilder();
var suite = testSuiteBuilder.Build(package);
AddTestsFrom(suite);
}
private void AddTestsFrom(Test node)
{
if (!node.IsSuite)
AddTest(node);
else
{
foreach (Test test in node.Tests)
AddTestsFrom(test);
}
}
private void AddTest(Test node)
{
_testHarness.AddTest(new WrappedNUnitTest(node, TestFilter.Empty));
}
}
The above reads NUnit tests in from the current assembly wraps them up and then adds them to our inhouse test harness. I haven't included these classes but they're not really important to understanding how the NUnit code works.
The really useful bit of information here is the static to "InitialiseService" this took quite a bit of figuring out but is necessary to get the basic set of test readers loaded in NUnit. You need to be a bit careful when looking at the tests in NUnit aswell as it includes failing tests (which I assume dont work because of the number of statics involved) - so what looks like useful documentation is actually misleading.
Aside from that you can then run the tests by implementing EventListener. I was interested in getting a one to one mapping between our tests and NUnit tests so each test is run on it's own. To achieve this you just need to implement TestStarted and TestFinished to do logging:
public void TestStarted(TestName testName)
{
}
public void TestFinished(TestResult result)
{
string text;
if (result.IsFailure)
text = "Failure";
else if (result.IsError)
text = "Error";
else
return;
using (var block = CreateLogBlock(text))
{
LogFailureTo(block);
block.LogString(result.Message);
}
}
There are a couple of problems with this approach: Inherited Test base classes from other assemblies with SetUp methods that delegate to ones in the current assembly dont get called. It also has problems with TestFixtureSetup methods which are only called in NUnit when TestSuites are Run (as opposed to running test methods on their own).
These both seem to be problems with NUnit although if you dont want to construct wrapped tests individually I think you could just put in a call to suite.Run with the appropriate parameters and this will fix the latter problem