Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to trigger ControlOutput correctly? for multiple instances of the same graph.

Discussion in 'Visual Scripting' started by lloydhooson, Jun 12, 2023.

  1. lloydhooson

    lloydhooson

    Joined:
    Apr 7, 2008
    Posts:
    77
    Hi, I have a unit that should except a normal (non coroutine input), and have 2 outputs, first a normal and second that is a coroutine, this all works correctly. Until you have two or more instances of the same graph in the scene, then the last graph to start is the only one to continue with the events, this last graph receives multiple events.

    FYI, this is the most simple example of this I have found, as I am using similar setup for many units, and I have now discovered that they all do not work with multiple instances of the same graph.

    Attaching the examples provided, a transform should move up every second by 0.1 in the Y, which works fine until you duplicate the graph and there are two transforms and two graphs then all moving occurs on the last graph in the hierarchy.

    attached is the image of the graph.
    here is the code for the unit:

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using Unity.VisualScripting;
    5.  
    6. [UnitCategory("Custom")]
    7. [UnitTitle("Coroutine Convertor Node")]
    8. public class CoroutineConverterNode : Unit
    9. {
    10.     [DoNotSerialize] public ControlInput input { get; private set; }
    11.     [DoNotSerialize] public ControlOutput output { get; private set; }
    12.     [DoNotSerialize] public ControlOutput outputCoroutine { get; private set; }
    13.     [DoNotSerialize] private Action onCoroutine = delegate { };
    14.  
    15.     protected override void Definition()
    16.     {
    17.         input = ControlInput("In", InputFlow);
    18.         output = ControlOutput("Out");
    19.         outputCoroutine = ControlOutput("Out Coroutine");
    20.     }
    21.  
    22.     protected virtual ControlOutput InputFlow(Flow flow)
    23.     {
    24.         GraphReference graphReference = flow.stack.AsReference();
    25.  
    26.         if (outputCoroutine.hasAnyConnection)
    27.         {
    28.             onCoroutine = delegate
    29.             {
    30.                 Flow.New(graphReference).StartCoroutine(outputCoroutine);
    31.             };
    32.         }
    33.  
    34.         CoroutineRunner.instance.StartCoroutine(RunCoroutine(() =>
    35.         {
    36.             onCoroutine();
    37.         }));
    38.  
    39.         return output;
    40.     }
    41.    
    42.     IEnumerator RunCoroutine(Action action)
    43.     {
    44.         yield return null;
    45.        
    46.         if (action != null)
    47.         {
    48.             action();
    49.         }
    50.     }
    51. }
    52.  

    Graph example: moveablock.png


    I'm obviously haven't got this working correctly, I believe that its due to the Flow.new and the graph reference. But I cant find another way of triggering control outputs.

    Thanks.
     
  2. lloydhooson

    lloydhooson

    Joined:
    Apr 7, 2008
    Posts:
    77
    fyi for anyone that comes across this and wants to trigger coroutines

    Code (CSharp):
    1.  protected override ControlOutput InputFlow(Flow flow)
    2.     {
    3.         GraphReference graphReference = flow.stack.AsReference();
    4.  
    5.         if (outputCoroutine.hasAnyConnection)
    6.         {
    7.             CoroutineRunner.instance.StartCoroutine(RunOutputCoroutine(graphReference));
    8.         }
    9.        
    10.         return output;
    11.     }
    12.  
    13.     IEnumerator RunOutputCoroutine(GraphReference graphReference)
    14.     {
    15.         yield return null;
    16.         Flow.New(graphReference).StartCoroutine(outputCoroutine);
    17.     }
    18.  
    19.  
     
  3. lloydhooson

    lloydhooson

    Joined:
    Apr 7, 2008
    Posts:
    77
    Things to note to anyone making there own custom units
    Do not have any any fields in the unit (these keep the value of the previous triggered unit (this makes no sense why this would ever be needed and shouldn't never be the case but hey ho) ), you cannot use the flow, for getting events then triggering use graphReference, use functions within function(I hate these) as you cannot use unit scope variables, this is the only way.
    basically good luck to whoever wants to create there own nodes.
     
  4. S2NX7

    S2NX7

    Joined:
    Aug 17, 2021
    Posts:
    28
    Thanks i needed this
     
  5. S2NX7

    S2NX7

    Joined:
    Aug 17, 2021
    Posts:
    28
    this worked for me fine even when using multiple :

    Code (CSharp):
    1.  
    2. using Unity.VisualScripting;
    3. using UnityEngine;
    4.  
    5. [UnitTitle("FlowToCoroutine")]//Unit title
    6. [TypeIcon(typeof(Flow))]//Unit icon
    7. public class FlowToCoroutine : Unit
    8. {
    9.  
    10.     [DoNotSerialize]
    11.     public ControlInput In;
    12.     [DoNotSerialize]
    13.     public ControlOutput Converted;
    14.     [DoNotSerialize]
    15.     public ControlOutput _flow;
    16.  
    17.     protected override void Definition()
    18.     {
    19.         In = ControlInput("In", Convert);
    20.         Converted = ControlOutput("Converted");
    21.         _flow = ControlOutput("Flow");
    22.  
    23.         Succession(In, Converted);
    24.         Succession(In, _flow);
    25.     }
    26.  
    27.     private ControlOutput Convert(Flow flow)
    28.     {
    29.         var GraphRef = flow.stack.ToReference();
    30.  
    31.         if (flow.isCoroutine)
    32.         {
    33.             Debug.LogWarning("FlowToCoroutine node is used to convert a normal flow to a Coroutine flow there is no point in using it in a Coroutine flow", flow.stack.gameObject);
    34.             return Converted;
    35.         }
    36.         else
    37.         {
    38.             var Convertedflow = Flow.New(GraphRef);
    39.             Convertedflow.StartCoroutine(Converted);
    40.             return _flow;
    41.         }
    42.     }
    43. }
    44.  
    Hopefully this is what you meant
     
    Last edited: Jul 19, 2023