Hey to all,
My game uses a interlayer plugin(dll files in Plugins folder, coded with .NET3.5) which we use to communicate with our backend. Everythings works pretty much well in Editor. However, when I build it with IL2CPP(SRV: .NET 4.x equivalent, ACL: .NET Standart 2.0), I get NullReferenceException. I started to think that our interlayer plugin is not compatible with IL2CPP. Then, I go through the code try to detect some classes which I suspect(by taking into consideration Scripting Restrictions). Can someone( @JoshPeterson ) help me who knows IL2CPP, AOT, etc concepts. Sorry for including that much scripts, but I think that this thread may also help most plugin developers.
Here is the error:
09-26 20:52:17.049 4036 4115 E Unity : NullReferenceException: Object reference not set to an instance of an object.09-26 20:52:17.049 4036 4115 E Unity : at GameManager+<CheckServerStatus>d__14.MoveNext () [0x00000] in <00000000000000000000000000000000>:0
09-26 20:52:17.049 4036 4115 E Unity : at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00000] in <00000000000000000000000000000000>:0
09-26 20:52:17.049 4036 4115 E Unity : at GameManager+<InitializeGame>d__9.MoveNext () [0x00000] in <00000000000000000000000000000000>:0
09-26 20:52:17.049 4036 4115 E Unity : at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00000] in <00000000000000000000000000000000>:0
09-26 20:52:17.049 4036 4115 E Unity : at GameManager.Start () [0x00000] in <00000000000000000000000000000000>:0
09-26 20:52:17.049 4036 4115 E Unity : <InitializeGame>d__9:MoveNext()
09-26 20:52:17.049 4036 4115 E Unity : UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
09-26 20:52:17.049 4036 4115 E Unity : GameManager:Start()
09-26 20:52:17.049 4036 4115 E Unity :
09-26 20:52:17.049 4036 4115 E Unity : (Filename: currently not available on il2cpp Line: -1)
Here is the ChechServerStatus() function of GameManager where i get the error exactly at Container.Resolve()
public IEnumerator CheckServerStatus()
{
// I get NullReferenceException at Resolve function
Container.Resolve<IUserManager>().CheckServerStatus((ServerStatusResultModel model) =>
{
// Some code here
}
}
Here is the Container script
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace RedApple.GameFramework.contanier
{
/// <summary>
/// ref:https://www.codeproject.com/Articles/1075189/Lets-write-a-Tiny-IoC-Container-to-learn-and-for-f?msg=5194025
/// </summary>
public class Container : IContainer
{
Dictionary<Type, RegistrationModel> instanceRegistry = new Dictionary<Type, RegistrationModel>();
public void RegisterInstanceType<I, C>()
where I : class
where C : class
{
RegisterType<I, C>(REG_TYPE.INSTANCE);
}
public void RegisterSingletonType<I, C>()
where I : class
where C : class
{
RegisterType<I, C>(REG_TYPE.SINGLETON);
}
private void RegisterType<I, C>(REG_TYPE type)
{
if (instanceRegistry.ContainsKey(typeof(I)) == true)
{
instanceRegistry.Remove(typeof(I));
}
instanceRegistry.Add(
typeof(I),
new RegistrationModel
{
RegType = type,
ObjectType = typeof(C)
}
);
}
public I Resolve<I>()
{
return (I)Resolve(typeof(I));
}
private object Resolve(Type t)
{
object obj = null;
if (instanceRegistry.ContainsKey(t) == true)
{
RegistrationModel model = instanceRegistry[t];
if (model != null)
{
Type typeToCreate = model.ObjectType;
ConstructorInfo[] consInfo = typeToCreate.GetConstructors();
var dependentCtor = consInfo.FirstOrDefault(item => item.GetCustomAttributes(true).FirstOrDefault(att => att.GetType() == typeof(TinyDependencyAttribute)) != null);
if (dependentCtor == null)
{
// use the default constructor to create
obj = CreateInstance(model);
}
else
{
// We found a constructor with dependency attribute
ParameterInfo[] parameters = dependentCtor.GetParameters();
if (parameters.Count() == 0)
{
// Futile dependency attribute, use the default constructor only
obj = CreateInstance(model);
}
else
{
// valid dependency attribute, lets create the dependencies first and pass them in constructor
List<object> arguments = new List<object>();
foreach (var param in parameters)
{
Type type = param.ParameterType;
arguments.Add(this.Resolve(type));
}
obj = CreateInstance(model, arguments.ToArray());
}
}
}
}
return obj;
}
private object CreateInstance(RegistrationModel model, object[] arguments = null)
{
object returnedObj = null;
Type typeToCreate = model.ObjectType;
if (model.RegType == REG_TYPE.INSTANCE)
{
returnedObj = InstanceCreationService.GetInstance().GetNewObject(typeToCreate, arguments);
}
else if (model.RegType == REG_TYPE.SINGLETON)
{
returnedObj = SingletonCreationService.GetInstance().GetSingleton(typeToCreate, arguments);
}
return returnedObj;
}
}
}