RealityStop / Bolt.Addons.Community

A community-driven project for extending Unity Bolt
MIT License
251 stars 34 forks source link

Error with Defined Events in Builds #73

Open ron77950 opened 2 weeks ago

ron77950 commented 2 weeks ago

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\com.unity.visualscripting@1.8.0\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\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Flow\Framework\Events\GameObjectEventUnit.cs:96 
  at Unity.VisualScripting.GameObjectEventUnit`1[TArgs].StartListening (Unity.VisualScripting.GraphStack stack) [0x00001] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Flow\Framework\Events\GameObjectEventUnit.cs:101 
  at Unity.VisualScripting.FlowGraph.StartListening (Unity.VisualScripting.GraphStack stack) [0x00026] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Flow\FlowGraph.cs:48 
  at Unity.VisualScripting.SubgraphUnit.StartListening (Unity.VisualScripting.GraphStack stack) [0x0000d] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Flow\SubgraphUnit.cs:142 
  at Unity.VisualScripting.FlowGraph.StartListening (Unity.VisualScripting.GraphStack stack) [0x00026] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Flow\FlowGraph.cs:48 
  at Unity.VisualScripting.XGraphEventListener.StartListening (Unity.VisualScripting.IGraphEventListener listener, Unity.VisualScripting.GraphReference reference) [0x00009] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\Runtime\VisualScripting.Core\Listeners\IGraphEventListener.cs:18 
  at Unity.VisualScripting.ScriptMachine.OnEnable () [0x0000c] in [...]\Library\PackageCache\com.unity.visualscripting@1.8.0\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 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

This does seem to fix it, thanks!

ron77950 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

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.