[CodeGen] Invaild IL instruction if compiled in Release mode.
General Unity version: 2022.3.17 Fish-Networking version: 3.11.17R
Description
FishNet generated invalid IL. This particular case is only reproducible with debug mode disabled.
Replication
-
Get the reproducible test scripts Scripts.zip
-
Make sure unity is in Release mode
-
Attach "ProblematicBehaviour" on a GameObject.
-
Run scene.
Expected behavior No invalid instruction errors or crashing.
Screenshots
Here's a screenshot of dnSpy looking at the invalid method.
Can you please narrow down what line specifically is causing the error? I noticed you had a bunch of fields were are presumably not needed?
Please remove anything not related to the error and re-upload.
Can you please narrow down what line specifically is causing the error? I noticed you had a bunch of fields were are presumably not needed?
Please remove anything not related to the error and re-upload.
I can try stripping it down a little bit more but I can't guarantee that I would be able to reproduce it. This is a piece of production code isolated out so it looks a bit messy. Removing any parts of the problematic method fixes it so I can't actually identify a single line that is causing this exact problem.
using FishNet.Object;
using FishNet.Object.Synchronizing;
public class SomeReference
{
public bool RefMethodReturningBool() => true;
public void RefMethodTakingABool(bool arg) { }
}
public class ProblematicBehaviour : NetworkBehaviour
{
private SomeReference _reference;
private float _someFloat;
private bool _someBool;
[SyncVar] private float _someSyncVarFloat;
private void Awake()
{
ProblematicMethod();
}
private void ProblematicMethod()
{
if (IsServer)
{
var returnedBool = _reference.RefMethodReturningBool();
if (returnedBool) _someSyncVarFloat -= 1.0f;
if (_someBool && _someSyncVarFloat <= _someFloat)
{
_someBool = false;
_someSyncVarFloat += _someFloat;
}
if (_someSyncVarFloat < 0 && !_someBool)
{
_someBool = true;
_reference.RefMethodTakingABool(false);
MethodTakingABool(false);
}
}
}
private void MethodTakingABool(bool state) { }
}
This is as small as I can strip. Removing any line fixes the invalid IL.
I don't want to spam issues, but we've ran into another set of code that behave similarly. But this time only in Debug mode.
using System;
using System.Collections;
using System.Collections.Generic;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using Random = UnityEngine.Random;
public enum SomeEnum { A, B }
[Serializable]
public struct SomeStruct
{
public SomeEnum SomeEnum;
}
public class SomeReference
{
public SomeStruct AStruct { get; }
public void SomeMethod() { }
}
public class ProblematicBehaviour2 : NetworkBehaviour
{
[SyncVar]
private uint _someSyncVarUInt;
private List<SomeReference> _someReferences;
private SomeReference GetSomeOtherReference() => null;
private IEnumerator SomeCoroutine()
{
yield break;
}
protected void Awake()
{
ProblematicOnChangedMethod(false, true, true);
}
private void ProblematicOnChangedMethod(bool prev, bool next, bool asServer)
{
if (next == prev) return;
if (next)
{
if (asServer)
{
_someSyncVarUInt = 0;
var i = Random.Range(0, _someReferences.Count);
_someReferences[i].SomeMethod();
return;
}
var player = GetSomeOtherReference();
if (player.AStruct.SomeEnum != SomeEnum.B) return;
StartCoroutine(SomeCoroutine());
}
else
{
if (asServer)
{
_someSyncVarUInt = 0;
return;
}
}
}
}
Scripts + Test Scene Scripts2.zip
Again, I've tried my best to minimize the code (that is, removing any line in the problematic method fixes itself again.)
I assume you mean release vs development(Debug)? Thank you for the information I'll take a look at this asap.
I assume you mean release vs development(Debug)? Thank you for the information I'll take a look at this asap.
I mean in-editor debug toggle where you enable debugger connection as shown in the screenshot of the post (located at the bottom right corner of an editor window). Not development build vs regular build. Although, I didn't test any build behaviors. Build might be invalid anyway since IL2CPP need valid IL to begin with.
I see that [SyncVar] is a common denominator in both of these cases.
I also see in the first screenshot of CIL that an instruction exists (bgt.un.s) and that the two operands on the stack are both floats. This looks like invalid CIL because that instruction (according to the docs on wikipedia) is supposed to be used only on UNsigned integers.
I think the bgt.un.s instruction can be used on floats, but it's for NaN checks rather than ordering.
It appears as though the weaver thinks the value of the syncvar is uint and not a single.
I could be way off the mark, though. CIL is arcane knowledge.
I took another run at this in V4 and was not able to reproduce. V4 doesn't use the old SyncVar codegen so that is probably why.
There's no plans to provide more updates to V3 given V4 is in stable. If do you manage to somehow get this error in V4(which should not be possible with the changes) please make a new issue and I'll give it high priority.
Hi, do you do paid commissions for patching v3 by any chance? We are shipping a game in V3 in two weeks and the team has already been crunching and I'm afraid of switching to V4 would put additional pressure on the team at this exact moment.
We can workaround the bug for the time begin. so it is ok if it is not possible.