Skip to content

Commit 0257eb1

Browse files
authored
Initial Readme.md
1 parent 5b36eb3 commit 0257eb1

1 file changed

Lines changed: 127 additions & 1 deletion

File tree

README.md

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,128 @@
11
# UnityNativeTool
2-
Tool that allows manipulating native libraries at runtime in Unity3d
2+
Tool designed mainly to solve old problem with unloading native plugins without reopening Unity editor, with vary little changes to code base and low overhead. It enables to replace plugin files between game executions or even while playing.
3+
Doing so involves mocking original native method calls with these made to manually loaded libraries by P/Invokes. Although works in builded game, it's intended to use in edtior.
4+
5+
## Requirements and dependencies
6+
- Windows or Linux
7+
- [Harmony](https://github.com/pardeike/Harmony) (already included in release package)
8+
- Api Compatibility Level >= .NET 4.x
9+
10+
## Limitations
11+
- All `[DllImport]` properties except for `dllName` and `EntryPoint` are not supported
12+
- All marshaling attributes such as `[MarshalAs]` or `[In]` are not supported
13+
- Multithreading is not supported (native calls from any but Unity main thread)
14+
15+
## Preformance
16+
Tested on old gaming laptop, Windows 10, 2 plugins with 10 functions each. Target function is simple addition of 2 floats and was called 1000000 times.
17+
18+
| Test case | Avarage time |
19+
| --- |:---:|
20+
| Without using this tool | ~70ms |
21+
| Lazy mode | ~135ms |
22+
| Preload mode | ~105ms |
23+
24+
## Instalation
25+
1. Download and add unity package from releases.
26+
27+
2. Set _Api Compatibility Level_ to .NET 4.x or above.
28+
Edit > Project Settings > Player > Other Settings > Api Compatibility Level
29+
30+
3. Set execution order of script `DllManipulator` to be the lowest of all scripts in game (at least of scripts that use native functions), e.g -10000.
31+
Edit > Project Settings > Script Execution Order
32+
33+
4. One game object in the scene needs to have `DllManipulator` script on it. By default this script has `DontDestroayOnLoad(gameObject)` call, and deletes itself when dupliacate is found. You can simply disable that object if you don't want this tool to run.
34+
35+
## Usage
36+
To native function to be mocked, both function declaration (extern method with `[DllImport]` attribute) and method which calls that function need to be suitably tagged with use of attributes below, alternatively `DllManipulator` options can be used.
37+
38+
All plugins under controll of this tool will be unloaded once game stops. To unload/reloaded them manually use `DllManipulator` script in editor.
39+
40+
#### __Attributes__
41+
* `[MockNativeDeclarations]` - Tags all native functions within type with this attribute.
42+
* `[MockNativeDeclaration]` - Tags native function with this attribute.
43+
* `[MockNativeCalls]` - Tags calls to native functions made in all methods within type with this attribute.
44+
* `[DisableMocking]` - Disables mocking of native function with this attribute.
45+
46+
#### __Options__
47+
These options are editable via `DllManipulator` script.
48+
* __DLL path pattern__ - Path at which mocked plugin files are located. Default is *Assets/Plugins/\__NameOfPlugin[.dll|.so]*. Can be the same as path that Unity uses for plugins.
49+
* __DLL loading mode__ - Specifies how DLLs and functions will be loaded.
50+
+ _Lazy_ - All DLLs and functions are loaded as they're first called. This allows them to be easily unloaded and loaded within game execution.
51+
+ _Preloaded_ - Slight preformance benefit over _Lazy_ mode. All DLLs and functions are loaded at startup. Calls to unloaded DLLs lead to crash, so mid-execution it's safest to manipulate DLLs if game is paused.
52+
* __[Linux only] dlopen flags__ - Flags used in dlopen() P/Invoke on Linux systems. Has minor meaning unless library is large.
53+
* __Mock all native functions__ - If true, all native functions in current assembly will be mocked.
54+
* __Mock native calls in all types__ - If true, calls of native funcions in all methods in current assembly will be mocked. This however can cause significant preformance issues at startup in big code base.
55+
56+
## Examples
57+
58+
```C#
59+
using System.Runtime.InteropServices;
60+
using UnityEngine;
61+
using DllManipulator;
62+
63+
[MockNativeDeclarations]
64+
class NativeFunctionsHolder
65+
{
66+
[DllImport("MyNativePlugin")]
67+
public static extern int BigThought();
68+
69+
[DllImport("MyNativePlugin", EntryPoint="complex_calc")]
70+
public static extern System.IntPtr ComplexCalc(float param1, Vector3 param2);
71+
72+
[DisableMocking]
73+
[DllImport("MyNativePlugin")]
74+
public static extern void IWontBeMocked(bool ohReally);
75+
}
76+
77+
class SomeMoreNatives
78+
{
79+
[MockNativeDeclaration]
80+
[DllImport("MyNativePlugin")]
81+
public static extern void HereIAm(string where);
82+
83+
[DllImport("MyNativePlugin")]
84+
public static extern bool WillIBeMocked();
85+
}
86+
87+
[MockNativeCalls]
88+
class FunctionsInvoker : MonoBehaviour
89+
{
90+
void Start()
91+
{
92+
int answear = NativeFunctionsHolder.BigThought(); //This call will be mocked
93+
var calc = NativeFunctionsHolder.ComplexCalc(2, Vector3.up); //So will this
94+
NativeFunctionsHolder.IWontBeMocked(true); //As it says
95+
}
96+
97+
void Update()
98+
{
99+
SomeMoreNatives.HereIAm("Wherever"); //This mocked too
100+
bool res = SomeMoreNatives.WillIBeMocked(); //Mocked only if "Mock all native functions" option is true
101+
MyOwnNative(); //As above
102+
}
103+
104+
[DllImport("MyNativePlugin")]
105+
private static extern void MyOwnNative();
106+
}
107+
108+
[MockNativeDeclarations]
109+
[MockNativeCalls]
110+
class AllInOne : MonoBehaviour
111+
{
112+
void Start()
113+
{
114+
MyVeryOwnNative(); //Mocked
115+
}
116+
117+
[DllImport("MyNativePlugin")]
118+
private static extern void MyVeryOwnNative();
119+
}
120+
```
121+
122+
## Planed features
123+
- Window editor
124+
- Native calls inlining
125+
- Pausing on dll/function load error, allowing to fix depencency without restarting game
126+
- Thread safety
127+
- Mac support
128+
- Possibly break depencency on Harmony

0 commit comments

Comments
 (0)