0

Custom node attaches the same delegate to multiple graphs

Matthew Horton 7 months ago • updated 6 months ago 1

Hi, I'm trying to use custom nodes that inherit from EventUnit to trigger graphs flows from scripts. On StartListening, the node attaches an event to a static delegate dictionary depending on what kind of node it is, eg. a CardEffect node gets the CardInstance component from its graphReference and attaches its event to a dictionary of <CardInstance, CardEffect>. This way, from the CardInstance I can call the event of the CardEffect and trigger the bolt flow.

However it doesn't seem that the events are staying the same if I'm instantiating the same stateMachine multiple times. When attached, they have the correct reference to the card/GraphReference, but when the event is called it is referencing a different card/GraphReference completely. This happens when I instantiate multiples of the same Card. I also add the statemachine as a component after instantiation and attach the macro to it then, so this might be having a bad effect/causing this problem.

Its a bit tricky to explain and I'm definitely hacking my way into bolt to make these nodes work. I'll try to split it up a bit here: 

StartListening is called as the override for EventUnit:

 public override void StartListening(GraphStack stack)
        {
            var data = stack.GetElementData<data>(this);
            if (data.isListening) return;
            reference = stack.ToReference();
            refObject = reference.gameObject;

            if (OnStartListen != null) OnStartListen(stack);

            this.AttachHandler();
            data.handler = handler;
            data.isListening = true;
            base.StartListening(stack);
        }

AttachHandler is then called based on this graph reference:

 protected override void AttachHandler()
        {
            cardInst = reference.gameObject.GetComponent<CardInstance>();

            Action<CardArgs> handler = args =>
            {
                //Logging cardInst or reference here returns the wrong instance
                if (TestHandler(reference, args))
                    Trigger(reference, args);
            };

            //Logging cardInst or reference here returns the right instance
            StateMachineEvents.CardEffectInits[cardInst] = handler;
        }


Inside TestHandler or Trigger the reference will always be to the last Card graph that was created, so if I have created 'Card1' to 'Card5' and call the CardEffectInits[Card1], the attached handler will be the Card5 handler, so it will post the GraphReference as Card5.

I'm trying to use this to add type cast variables to the custom nodes, as this is intended to be a tool for designers to implement many cards. I'm not sure what the difference is between my implementation and the CustomEvent node, as I worked this solution out from that code. 

Bolt Version:
1.4.1
Unity Version:
2018.3
.NET Version:
4.x

Hi again, I've just tried to replace these custom nodes with the CustomTrigger node and this still happens:

- I instantiate multiple instances of a prefab, and add a StateMachine component to them after instantiation

- I call the CustomTrigger on one of the prefabs when it is activated, with a reference to its game object

- The trigger seems to be called on multiple objects or something else. It does nothing.

If I only create one instance of the prefab it seems to work fine, however I need to be able to create multiple instances of the same card with difference state machines attached to each one.