Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with Defined Events in Builds #73

Open
ron77950 opened this issue Sep 30, 2024 · 9 comments
Open

Error with Defined Events in Builds #73

ron77950 opened this issue Sep 30, 2024 · 9 comments

Comments

@ron77950
Copy link

ron77950 commented Sep 30, 2024

I recently updated to the newest release in my project and all of my graphs using Defined Events started throwing errors in build only (they work when played in editor still).

Here's more information as well: I tried release 3.1.2 and it still worked normally so the bug is in release 3.2, the project is in Unity Editor 2021.3.29f1, and here's the error stack.

ArgumentNullException: Value cannot be null.
Parameter name: type
  at System.Reflection.IntrospectionExtensions.GetTypeInfo (System.Type type) [0x00009] in <47fc8c70fa834cbf8141d7c1a7589125>:0 
  at Unity.VisualScripting.Community.DefinedEventNode.ConstructHook (UnityEngine.GameObject target, System.Type eventType) [0x0000a] in [...]\Library\PackageCache\dev.bolt.addons@9da87745de\Runtime\Events\Nodes\DefinedEventNode.cs:167 
  at Unity.VisualScripting.Community.DefinedEventNode.GetHook (Unity.VisualScripting.GraphReference reference) [0x00009] in [...]\Library\PackageCache\dev.bolt.addons@9da87745de\Runtime\Events\Nodes\DefinedEventNode.cs:160 
  at Unity.VisualScripting.EventUnit`1[TArgs].StartListening (Unity.VisualScripting.GraphStack stack) [0x0003a] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\Framework\Events\EventUnit.cs:66 
  at Unity.VisualScripting.GameObjectEventUnit`1[TArgs].StartListening (Unity.VisualScripting.GraphStack stack, System.Boolean updateTarget) [0x0005a] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\Framework\Events\GameObjectEventUnit.cs:96 
  at Unity.VisualScripting.GameObjectEventUnit`1[TArgs].StartListening (Unity.VisualScripting.GraphStack stack) [0x00001] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\Framework\Events\GameObjectEventUnit.cs:101 
  at Unity.VisualScripting.FlowGraph.StartListening (Unity.VisualScripting.GraphStack stack) [0x00026] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\FlowGraph.cs:48 
  at Unity.VisualScripting.SubgraphUnit.StartListening (Unity.VisualScripting.GraphStack stack) [0x0000d] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\SubgraphUnit.cs:142 
  at Unity.VisualScripting.FlowGraph.StartListening (Unity.VisualScripting.GraphStack stack) [0x00026] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\FlowGraph.cs:48 
  at Unity.VisualScripting.XGraphEventListener.StartListening (Unity.VisualScripting.IGraphEventListener listener, Unity.VisualScripting.GraphReference reference) [0x00009] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Core\Listeners\IGraphEventListener.cs:18 
  at Unity.VisualScripting.ScriptMachine.OnEnable () [0x0000c] in [...]\Library\PackageCache\[email protected]\Runtime\VisualScripting.Flow\ScriptMachine.cs:22 

My best guess on this cause of the problem is the eventType being left null after it's being replaced with NeweventType on the Defined Event node in the new version. Here's the json that changed in my ScriptGraphAsset for reference (I replaced my custom event class namespace with -mycustomeventclass-):

Old

{"eventType":"-mycustomeventclass-","coroutine":false,"defaultValues":{"target":null},"position":{"x":-617.0,"y":-92.0},"guid":"88296867-6217-4075-b0a7-a1158a9f6964","$version":"A","$type":"Unity.VisualScripting.Community.DefinedEventNode","$id":"9"}

New

{"eventType":null,"NeweventType":{"type":"-mycustomeventclass-"},"coroutine":false,"defaultValues":{"target":null},"position":{"x":-625.0,"y":-92.0},"guid":"49596e6c-1502-4e2f-9314-b6fd01d75124","$version":"A","$type":"Unity.VisualScripting.Community.DefinedEventNode","$id":"18"}

P.S. I think you need to add "com.unity.nuget.newtonsoft-json": "3.2.1" to the package dependencies in the newest version as it's used in the MethodDeclaration.cs. Just something I ran into while testing.

@S2NX7
Copy link
Collaborator

S2NX7 commented Oct 9, 2024

I recently updated to the newest release in my project and all of my graphs using Defined Events started throwing errors in build only (they work when played in editor still).

Here's more information as well: I tried release 3.1.2 and it still worked normally so the bug is in release 3.2, the project is in Unity Editor 2021.3.29f1, and here's the error stack.

Oh ok I will fix this thanks!

P.S. I think you need to add "com.unity.nuget.newtonsoft-json": "3.2.1" to the package dependencies in the newest version as it's used in the MethodDeclaration.cs. Just something I ran into while testing.

In the newest version i am working on does not use Newtonsoft anymore so it will not be needed.

@S2NX7
Copy link
Collaborator

S2NX7 commented Oct 9, 2024

Can you replace the DefinedEventNode script with this:

using Unity.VisualScripting.Community.Utility;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace Unity.VisualScripting.Community
{
    /// <summary>
    /// Listens for an event by type, rather than by name.  In other respects, it acts similar to the built-in Custom Unit
    /// </summary>
    [UnitCategory("Events/Community")]
    [UnitTitle("Defined Event")]
    [RenamedFrom("Bolt.Addons.Community.DefinedEvents.Units.DefinedEvent")]
    [RenamedFrom("Bolt.Addons.Community.DefinedEvents.Units.DefinedEventUnit")]
    public class DefinedEventNode : GameObjectEventUnit<DefinedEventArgs>, IDefinedEventNode
    {
        const string EventName = "OnDefinedEvent";

        #region Previous Event Type Handling (for backward compatibility)
        [SerializeAs(nameof(eventType))]
        private System.Type _eventType;
        

        [DoNotSerialize]
        //[InspectableIf(nameof(IsNotRestricted))]
        public System.Type eventType
        {
            get {
                return _eventType; }
            set
            {
                _eventType = value;
            }
        }

        [DoNotSerialize]
        //[UnitHeaderInspectable]
        //[InspectableIf(nameof(IsRestricted))]
        public System.Type restrictedEventType
        {
            get
            {
                return _eventType;
            }
            set
            {
                _eventType = value;
            }
        }

        #endregion

        #region New Event Type Handling
        [SerializeAs(nameof(NeweventType))]
        private IDefinedEventType New_eventType;

        [DoNotSerialize]
        public IDefinedEventType NeweventType
        {
            get { return New_eventType; }
            set { New_eventType = value; }
        }

        [DoNotSerialize]
        [UnitHeaderInspectable]
        [InspectableIf(nameof(IsRestricted))]
        public IDefinedEventType NewrestrictedEventType
        {
            get { return New_eventType; }
            set { New_eventType = value; }
        }

        public bool IsRestricted
        {
            get { return CommunityOptionFetcher.DefinedEvent_RestrictEventTypes; }
        }

        public bool IsNotRestricted
        {
            get { return !IsRestricted; }
        }
#endregion

        [DoNotSerialize]
        public List<ValueOutput> outputPorts { get; } = new List<ValueOutput>();

        [DoNotSerialize]
        private ReflectedInfo Info;

        public override Type MessageListenerType => null;

        protected override string hookName => EventName;

        protected override bool ShouldTrigger(Flow flow, DefinedEventArgs args)
        {
            return args.eventData.GetType() == NeweventType.type;
        }

        protected override void Definition()
        {
            base.Definition();

            // For backward compatibility, convert the Type to IDefinedEventType
            if (restrictedEventType != null)
            {
                NewrestrictedEventType = new IDefinedEventType(restrictedEventType);
                restrictedEventType = null;
            }

            if (NewrestrictedEventType == null)
            {
                NewrestrictedEventType = new IDefinedEventType();
            }

            BuildFromInfo();
        }

        private void BuildFromInfo()
        {
            outputPorts.Clear();
            if (NeweventType.type == null)
                return;

            Info = ReflectedInfo.For(NeweventType.type);
            foreach (var field in Info.reflectedFields)
            {
                outputPorts.Add(ValueOutput(field.Value.FieldType, field.Value.Name));
            }


            foreach (var property in Info.reflectedProperties)
            {
                outputPorts.Add(ValueOutput(property.Value.PropertyType, property.Value.Name));
            }
        }

        protected override void AssignArguments(Flow flow, DefinedEventArgs args)
        {
            for (var i = 0; i < outputPorts.Count; i++)
            {
                var outputPort = outputPorts[i];
                var key = outputPort.key;
                if (Info.reflectedFields.ContainsKey(key))
                {
                    var reflectedField = Info.reflectedFields[key];
                    flow.SetValue(outputPort, reflectedField.GetValue(args.eventData));
                }
                else if (Info.reflectedProperties.ContainsKey(key))
                {
                    var reflectedProperty = Info.reflectedProperties[key];
                    flow.SetValue(outputPort, reflectedProperty.GetValue(args.eventData));
                }
            } 
        }
        public override EventHook GetHook(GraphReference reference)
        {
            var refData = reference.GetElementData<Data>(this);
            return ConstructHook(refData.target, New_eventType.type);
        }

        private static EventHook ConstructHook(GameObject target, Type eventType)
        {
            EventHook hook;
            if (DefinedEventSupport.IsOptimized())
                hook = new EventHook(EventName, target, eventType.GetTypeInfo().FullName);
            else
                hook = new EventHook(EventName, target);
            return hook;
        }


        public static void Trigger(GameObject target,object eventData)
        {
            var eventHook = ConstructHook(target, eventData.GetType());
            EventBus.Trigger(eventHook, new DefinedEventArgs(eventData));
        }

        

        public static IDisposable RegisterListener<T>(GameObject target, Action<T> onEvent) 
        {
            var eventHook = ConstructHook(target, typeof(T));
            Action<DefinedEventArgs> action = (x) => {
                if (x.eventData.GetType() == typeof(T))
                    onEvent((T)x.eventData);
            };
            EventBus.Register<DefinedEventArgs>(eventHook, action);

            return Disposable.Create(() => { EventBus.Unregister(eventHook, action); });
        }
    }
}

This should fix the error.

@ron77950
Copy link
Author

ron77950 commented Oct 9, 2024

This does seem to fix it, thanks!

@ron77950
Copy link
Author

ron77950 commented Oct 9, 2024

Any chance this fix will be added to the github relatively soon, so I can use the git url to add the package in my project again?

@S2NX7
Copy link
Collaborator

S2NX7 commented Oct 9, 2024

Any chance this fix will be added to the github relatively soon, so I can use the git url to add the package in my project again?

Mmm not sure because the C# Generators might take awhile to finish, If you do really need it i can add the fix by its self now.

@ron77950
Copy link
Author

ron77950 commented Oct 9, 2024

Any chance this fix will be added to the github relatively soon, so I can use the git url to add the package in my project again?

Mmm not sure because the C# Generators might take awhile to finish, If you do really need it i can add the fix by its self now.

It doesn't have to be really soon. I just wondered if it's something I could get within the next week or 2 or if it'd be months.

@rktvr
Copy link

rktvr commented Nov 17, 2024

the same issue with the newtonsoft namespace exists in the methoddeclaration script

@S2NX7
Copy link
Collaborator

S2NX7 commented Nov 17, 2024

the same issue with the newtonsoft namespace exists in the methoddeclaration script

You can replace the script with this:

using Unity.VisualScripting;
using System;
using UnityEngine;
using System.Collections.Generic;
using Unity.VisualScripting.Community.Utility;
using Unity.VisualScripting.Community.Libraries.CSharp;
using System.Reflection;

namespace Unity.VisualScripting.Community
{
    [Serializable]
    [Inspectable]
    [TypeIcon(typeof(Method))]
    [RenamedFrom("Bolt.Addons.Community.Code.MethodDeclaration")]
    public abstract class MethodDeclaration : Macro<FlowGraph>
    {
        [Inspectable]
        public string methodName;

        [Inspectable]
        [TypeFilter(Abstract = true, Classes = true, Enums = true, Generic = false, Interfaces = true,
            Nested = true, NonPublic = false, NonSerializable = true, Object = true, Obsolete = false, OpenConstructedGeneric = false,
            Primitives = true, Public = true, Reference = true, Sealed = true, Static = false, Structs = true, Value = true)]
        public Type returnType = typeof(Libraries.CSharp.Void);

        [SerializeField]
        [HideInInspector]
        private string qualifiedReturnTypeName;

        public int genericParameterCount = 0;

        public ValueTuple<int, List<Type>> genericParameterConstraints = new ValueTuple<int, List<Type>>();
        public ValueTuple<int, List<GenericParameterAttributes>> genericParameterAttributes = new ValueTuple<int, List<GenericParameterAttributes>>();

        /// <summary>
        /// Left this to not overwrite current methodParameters
        /// and instead get the parameters from this and move it to the serializtion variable
        /// </summary>
        [SerializeField]
        [HideInInspector]
        private string serializedParams;

        [SerializeField]
        [HideInInspector]
        private SerializationData serialization;

        [Inspectable]
        public ClassAsset classAsset;

        [Inspectable]
        public StructAsset structAsset;

        [Serialize]
        [InspectorWide]
        public List<TypeParam> parameters = new List<TypeParam>();

        [Serialize]
        public List<AttributeDeclaration> attributes = new List<AttributeDeclaration>();

        public AccessModifier scope = AccessModifier.Public;

        public MethodModifier modifier = MethodModifier.None;

        public Action OnSerialized;
#if UNITY_EDITOR
        public bool opened;
        public bool parametersOpened;
        public bool attributesOpened;
#endif

        public override FlowGraph DefaultGraph()
        {
            return new FlowGraph();
        }

        protected override void OnAfterDeserialize()
        {
            base.OnAfterDeserialize();

            if (!(string.IsNullOrWhiteSpace(qualifiedReturnTypeName) || string.IsNullOrEmpty(qualifiedReturnTypeName)))
            {
                returnType = Type.GetType(qualifiedReturnTypeName);
            }

            foreach (var param in parameters)
            {
                param.OnAfterDeserialize();
            }

            OnSerialized?.Invoke();
        }

        protected override void OnBeforeSerialize()
        {
            base.OnBeforeSerialize();

            if (returnType == null)
            {
                qualifiedReturnTypeName = string.Empty;
                return;
            }

            qualifiedReturnTypeName = returnType.AssemblyQualifiedName;
            foreach (var param in parameters)
            {
                param.OnBeforeSerialize();
            }
        }
    }
    /// <summary>
    /// This is a empty class used for the typeIcon
    /// it does not have any functionality
    /// </summary>
    public class Method
    {
    }
}

if it gives you more errors then send them

@rktvr
Copy link

rktvr commented Nov 17, 2024

nice, that fixes it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants