I have a modding system, I programmatically create an assetbundle, and a DLL(s) based on the assets/scripts in a certain scene. This works fine for Windows, but I can’t get the DLL to work for Android (builds the bundle fine though) - code below
private void DoScriptOnlyBuild(string destination, IEnumerable<string> managedAssemblyNames, string bundleName, bool ecsOrBurst)
{
var bpo = new BuildPlayerOptions()
{
locationPathName = Path.Combine(destination, "__build", "plugin"),
target = _environmentType == EnvironmentType.Windows ? BuildTarget.StandaloneWindows64 : BuildTarget.Android,
options = ecsOrBurst ? BuildOptions.DetailedBuildReport : BuildOptions.DetailedBuildReport,
subtarget = (int)MobileTextureSubtarget.Generic, //Tried this too, didn't work
};
Debug.Log($"Prepare to build..");
//This should create a bunch of DLLs, we then cherry pick the ones we need for the mod using the managedAssemblyNames list
BuildReport report = BuildPipeline.BuildPlayer(bpo); //Doesn't generate DLL!
While, on Windows, this creates a DLL perfectly fine, this doesn’t seem to happen when targeting android. There are no logs in the console (except for a warning about not being able to parse XML with no further info, but people on the forums say they get this even on healthy builds) The build report tells me nothing useful.
I’m also able to build the entire project to android just fine via the standard unity build button, this of course creates an APK though rather than a bundle/dll
Android code needs to be in the bundle and digitally signed before it can be executed, unless of course you root your Android device.
Usually for code-side changes either a new binary is sent or else a scripting language (such as Lua) is used. Then the scripts are just text files included as part of your updated binaries.
If you go the Lua route, I found the Moonsharp Lua distro to be pretty simple to set up.
For Android and Apple there are rules about what you can and cannot change by late-game modding of code. I am not a lawyer but the details are in the ToS for each. What it seems is that if your changes are not in violation of any other ToS and are not used in a malicious way to bypass the normal app review process, you may be okay.
We have an existing system for windows, so we really do need to be able to stick to c# scripts embedded in unity in the typical way - I know downloading and executing custom code is certainly possible, a good example would be Contractors on the quest, there’s a whole mod browser in-app, which pulls in assets and code in the form of entirely different game modes, so it must be possible.
Nothing says you can’t interpret C# code on the fly too… it’s a heavier lift than a scripting language like Lua, and gets heavier the more you want to do.
If they ARE allowing you to mod it with C#, then they must also be including some way of either interpreting or compiling that on device, as the C# compiler does not get built into the target game.
Yeah ok, the more I look into this the more it does seem like a no-go.
Is it possible to have my main app download and run an entire APK? That way, I could still have a mod browser in the main app, that downloads mods in the form of entirely separate programs, and then starts them, passing certain launch args?
Whatever com.foo.game bundle identifier you are using maps to exactly one APK, or AAB in the case of things nowadays.
There are ways to get particular programs to interoperate with other specific programs but:
this is all on a very onesey-twosey kinda basis
I think all contemplated interoperation has to be known in advance by both programs (not sure)
the contemplated interoperation is limited (I think one can launch the other basically)
each one is installed as a separate program
all the setup and testing would be outside of “main Unity,” except perhaps gradle-y stuff
I have never looked into what it would involve.
I’m not even sure what level of modding (rooting? regular developer?) you would need in your android if you wanted to begin testing what is possible with that approach, as this is not a modding forum and such talk is verboten.
As long as I can get my main app to launch the other APKs, that’ll do fine. Struggling to even get this working though, I’ve tried the code below
public void LaunchApp()
{
Debug.Log("Try launch app 1");
string packageName = "com.ImperialCollegeLondon.VE2Hub24"; //This is definitely the name of the package I want to launch, works fine launching from side quest or from the headset's menu
var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
var packageManager = currentActivity.Call<AndroidJavaObject>("getPackageManager");
var launchIntent = packageManager.Call<AndroidJavaObject>("getLaunchIntentForPackage", packageName);
currentActivity.Call("startActivity", launchIntent);
}
From what I can find on the forums, this is the way to do it, and yet I get the following error
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.migrateExtraStreamToClipData(android.content.Context)' on a null object reference<br>java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.migrateExtraStreamToClipData(android.content.Context)' on a null object reference<br> at android.app.Instrumentation.execStartActivity(Instrumentation.java:1756)<br> at android.app.Activity.startActivityForResult(Activity.java:5411)<br> at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:728)<br> at android.app.Activity.startActivityForResult(Activity.java:5369)<br> at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:709)<br> at android.app.Activity.startActivity(Activity.java:5755)<br> at android.app.Activity.startActivity(Activity.java:5708)<br> at UnityEngine.AndroidJNISafe.CheckException ()
My manifest file looks fine, I’ve got my main activity configured with
Unfortunately googling this problem is getting me anywhere, doesn’t help that half the discussions seem to be from about 10 years ago…
Maybe more of an Android problem (have posted on their forums too) but also posting here on the off-chance… it’s a problem I’m running into during my Unity development after all, maybe other Unity devs have/will have run into it too, or maybe there’s some unity-specific things at play