NodeCanvas Forums › Support › NodeCanvas 1.x – Avoid System.Reflection.Emit
Hi,
I’m on an old version of NodeCanvas (1.x, not sure exactly which version), and I’m trying to run the build on a platform where System.Reflection.Emit is unsupported.
In particular, it seems the Expression.Compile() method in the following code snippet (see below) is the one dependent on the Emit library.
Is there any way to work around this? I cannot update either Unity version (currently 2017.4.28) or NodeCanvas.
public static T BuildDelegate<T>(MethodInfo method, params object[] missingParamValues) {
var queueMissingParams = new Queue<object>(<wbr />missingParamValues);
var dgtMi = typeof(T).GetMethod(“Invoke”);
var dgtRet = dgtMi.ReturnType;
var dgtParams = dgtMi.GetParameters();
var paramsOfDelegate = dgtParams.Select(tp => Expression.Parameter(tp.<wbr />ParameterType, tp.Name)).ToArray();
var methodParams = method.GetParameters();
if (method.IsStatic)
{
var paramsToPass = methodParams.Select((p, i) => CreateParam(paramsOfDelegate, i, p, queueMissingParams)).ToArray()<wbr />;
var call = Expression.Call(method, paramsToPass);
var convertCall = Expression.Convert(call, typeof(object));
Expression<T> expr = null;
if (dgtRet == typeof(void)){
expr = Expression.Lambda<T>(call, paramsOfDelegate);
} else {
expr = Expression.Lambda<T>(<wbr />convertCall, paramsOfDelegate);
}
return expr.Compile();
}
else
{
var paramThis = Expression.Convert(<wbr />paramsOfDelegate[0], method.DeclaringType);
var paramsToPass = methodParams.Select((p, i) => CreateParam(paramsOfDelegate, i + 1, p, queueMissingParams)).ToArray()<wbr />;
var call = Expression.Call(paramThis, method, paramsToPass);
var convertCall = Expression.Convert(call, typeof(object));
Expression<T> expr = null;
if (dgtRet == typeof(void)){
expr = Expression.Lambda<T>(call, paramsOfDelegate);
} else {
expr = Expression.Lambda<T>(<wbr />convertCall, paramsOfDelegate);
}
return expr.Compile();
}
}
I figured out that I’m on nodeCanvas 1.5.9.
And I also noticed some Reflection wrappers in 2.9, maybe migrating these over to 1.5.9 could help me?
After some more research I think I understand the following:
– In IL2CPP (Unity’s scripting to CPP) System.Reflection.Emit is aggressively removed because injecting code is not allowed on the platforms where IL2CPP is used.
– nodeCanvas 1.5.9 does not necessarily need to inject code, but uses Expression.Compile() to look up a method.
– Unity has a quick fix where you can tell the IL2CPP to keep some of the Reflection code and fall back on a LambdaExpression to look up methods. However, this currently only supports looking up methods with a single string (no other parameters or values are allowed).
– nodeCanvas (and the scripts/nodes I have) require additional value types and parameters, which makes it incompatible with this fix, and Unity has no ETA on when they will implement support for more value types and parameters.
My options, then, are to either rescript the game with a different visual scripter, or wait for Unity to implement what I need.
I’m in part basing this on the discussion in this thread: https://forum.unity.com/threads/are-c-expression-trees-or-ilgenerator-allowed-on-ios.489498/
I just have two questions here that I would appreciate if someone could answer.
1) Is this compatibility “problem” fixed in later versions of nodeCanvas?
2) Is there some workaround for this that I’m missing?
Additional question:
3) I remained on nodeCanvas 1.5.9 because upgrading automatically to 2.x was not supported, but also because the dialogue tree was removed(?). My question is if there is equal functionality to the dialogue tree in 2.x.
Thanks,
– Markus
Hello and sorry for late reply due to summer vacation Marcus.
Version 1.x is honestly very old (like 3 years or so) and to a great degree I don’t remember a lot about how things were implemented since prety much everything has changed since then. 🙂
With that said, in version 2.x there is no expression.Compile usage anywhere. For AOT platforms like iOS, there are also specific reflection tasks (Execute Function, Get/Set Property etc) that are made to work with AOT and there is also a Preferred Types Editor that generates some classes required for “tricking” AOT compilers to work without complains. https://nodecanvas.paradoxnotion.com/documentation/?section=working-with-aot-platforms
So, while AOT platforms still impose problems, there are some new things that help work around them.
Furthermore, the Dialogue Trees are still there in version 2.x.
I would highly suggest to check the new version out since there are so many new and improved things versus version 1.x 🙂
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
Hey, thanks for the reply.
Upgrading to 2.x means I have to rescript the entire game, but if there is no alternative I would do it.
However, I figured I could work around this and just hard-code the method calls based on the method info instead. Since the game is basically done and I know what methods I am using – I can do it with just a couple of switch statements. It shouldn’t be too much trouble.
Thanks, – Markus