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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Been using VS for a year now, need a few inputs to get things running better

Discussion in 'Visual Scripting' started by genryuu111, Jun 18, 2023.

  1. genryuu111

    genryuu111

    Joined:
    Aug 29, 2019
    Posts:
    6
    Hello! First time posting here.

    I started one year ago my journey with Unity straight with Visual Scripting.
    I find it an amazing tool for the things it can do that you can't do with normal c#, and it allowed me to come this far. I think that I wouldn't have been able to get so much done if I had to learn "normal" coding from the start.

    But, I have a few issues, and they mostly come from the fact that I find the documentation pretty lacking, and overall, the amount of help and tutorials that focus on Visual Scripting that are not for very simple stuff is very limited.

    So, here we go:

    1- Can anybody recommend any resource where I could learn how to code better, best practices, tricks, that focus on visual scripting?

    2- One thing I really struggle with is that, it seems, all debugging functions do not work well when using visual scripting. The profiler doesn't show anything that can help me find where a problem is.
    The reporting system also is not helpful unless you're testing within Unity. Clicking on the error will highlight the problematic node and then you can find your problem with nodes in red, but that can't be done outside of Unity.
    I have an "Ingame Debug Console" I got from the assets store, and while it will report exceptions, there is no way for me to know anything specific about them. I'll se the error, but if I don't know where in my project it occurs, it's of no use.
    Same thing for "Crash and exception reporting" function in Unity Gaming Services. I'm getting reports but I have no way to use them to pinpoint my issues.
    So, is there any other tool I could use instead? Any way around this issue?

    I may add more questions when they come to mind, but the 2nd point is really impacting my ability to reliably get rid of bugs, the biggest issue I'm having right now.
     
  2. PanthenEye

    PanthenEye

    Joined:
    Oct 14, 2013
    Posts:
    1,790
    C# can do everything visual scripting does and a lot more, just not with nodes.
    Unity Visual Scripting automatically generates 99% of nodes straight from Unity's C# scripting API. For every public Unity property, struct and method there exists a node with additional node variants for method overrides. So Visual Scripting is literally C# but... visualized. Hence any general C# programming advice applies.

    There are a few differences - Graphs don't have the concept of namespaces which you see as categories in Fuzzy Finder. Graphs also can't do inheritance but basically are Monobehaviour alternatives. The rest is pretty much identical besides the few custom implemented nodes like Timer, Cooldown, Sequence and some others that only exist in Visual Scripting. Graphs also do not have methods, but asset SubGrahps can be roughly equated to a method which is a piece of reusable logic.
    Because that part of the tool is poorly designed.
    Profiler is for determining cause of poor performance, it's not an error debugging tool.
    Outside Unity you read target platform log files. C# errors and Visual Scripting errors have largely the same causes, so go watch any Unity debugging tutorial and how to fix common Unity errors such as Missing Reference Exception and others.
    You can get a free in-game console by ticking in the Development Build checkbox in build settings. And you need to learn to read the stack trace of Exceptions which give more information about them. In case of Visual Scripting this probably has limited application though as you'd likely get information about some random graph asset and it's GUID which can only be read by opening the graph asset in a text editor. And if you're using an embed graph, then you have no chance really. Visual Scripting is hard to debug and there's nothing much anyone can do until they improve this.
    Yes, C#. You get a full stack trace that points to scripts that trigger the logic and the exact code line that produces the error instead of random graph GUID that's unusable.
     
    Ryiah likes this.
  3. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,184
    You have it backwards. Like @PanthenEye mentioned everything you can do in VS can be done in C# and it makes sense as if you think about it it's written in C#. If it couldn't be done in C# you wouldn't be able to do it in VS either.

    In fact not only can you do it in C# but you're likely going to be able to use less code since C# has a lot of little things it allows you to do to get more work done with less code (we call this syntactical sugar) and it will have higher performance as VS is interpreted while C# is compiled.
     
    Last edited: Jun 18, 2023
  4. genryuu111

    genryuu111

    Joined:
    Aug 29, 2019
    Posts:
    6
    While I understand what both of you say, in theory, that doesn't apply to everyone's brain.
    I've tried coding a few times, but it just doesn't click with me. There is a reason visual scripting tools exist, outside of unity too, and it's not just "laziness".

    And to name one thing you can do in visual scripting that you can't in C# is that I can modify code while it's running.

    While I may reconsider visual scripting for a future project (or at this point, even unity as an engine), my current one is just too big at this point to just convert all to C# (not to mention, LEARNING C#), as a solo developer.

    And I stay strong that I would have not come to this point if I had to learn C#.

    My question was, is there a way to alleviate these issues? And I guess the answer was no.

    This only applies if you already understand C#. I don't. I tried. I failed many times. While I understand the logic behind programming, I can't translate stuff from C# to visual scripting.

    That, I agree with.

    It's still a tool used to solve problems with your code, sorry I used the wrong terminology, the core of the question remains.

    I can see the error itself, but I can't know WHERE in the code it is. I don't know what object it's associated with. Why is it that I can click on an error within unity and it will know what object and what node causes the problem, but it can't tell me a node type or even just the object name otherwise?

    I'm basically only using embedded graphs, so I guess that's a no for me then.
    To understand more clearly, I see there's a way to convert from embedded to graph. It may be time consuming but reading further I saw it's generally better to go with graphs. In the case I converted, how would this help me with debugging, more specifically?
    Hard to debug, I can live with that. But in my current situation it feels IMPOSSIBLE to debug.
     
  5. PanthenEye

    PanthenEye

    Joined:
    Oct 14, 2013
    Posts:
    1,790
    I get where you're coming from. I was once in your position 5 years ago. I had the same limiting belief that I just can't text code while I can do anything with Visual Scripting (Bolt at the time) until I hit hard walls with project architecture and debugging issues similar to yours. So I had no choice but to pick up C# and I've never looked back.
    This is indeed very useful for Unity newbies and for rapid prototyping but project architecture limitations and debugging issues kinda outweigh the utility of Live editing once you know how to get things to work. Visual Scripting is great for learning, but not so great for shipping a bug free product.
    It doesn't have to be all or nothing. Visual Scripting can automatically generate nodes for C# scripts, even your own via Node Options. So you can translate the more problematic parts with debugging issues to C#. Then generate nodes for those scripts and replace VS nodes with reflected C# nodes which should have a more detailed stack trace that's more usable. There's also a simple Custom Event API so you can trigger a custom event in a graph from a C# script. There are various ways for both to work in tandem. Visual Scripting is not designed to be a full C# replacement, it never will be that.

    Here's a simple example:

    I'm calling Camera.Reset() method both with UVS default node and my own SetCamera.Reset node that's generated from my C# script. They do the same exact thing and access the same exact Unity Scripting API.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SetCamera : MonoBehaviour
    4. {
    5.     public void Reset(Camera cam)
    6.     {
    7.         cam.Reset();
    8.     }
    9. }
    10.  


    I get an error because Camera component doesn't exist on the object the graph is on and I haven't specified a different input.

    Here's full stack trace from Visual Scripting Node. It tells you what the problem is and the GameObject name because it's a missing component (perhaps not the best example). But you don't get any information about the graph or the node.

    Code (CSharp):
    1. MissingComponentException: There is no 'Camera' attached to the "GameObject" game object, but a script is trying to access it.
    2. You probably need to add a Camera to the game object "GameObject". Or your script needs to check if the component is attached before using it.
    3. Unity.VisualScripting.InstanceActionInvoker`1[TTarget].InvokeUnsafe (System.Object target) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_0.cs:50)
    4. Unity.VisualScripting.InstanceActionInvoker`1[TTarget].Invoke (System.Object target) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_0.cs:31)
    5. Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    6. Unity.VisualScripting.InstanceActionInvoker`1[TTarget].Invoke (System.Object target) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_0.cs:39)
    7. Unity.VisualScripting.Member.Invoke (System.Object target) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Member.cs:930)
    8. Unity.VisualScripting.InvokeMember.Invoke (System.Object target, Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Codebase/InvokeMember.cs:308)
    9. Unity.VisualScripting.InvokeMember.Enter (Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Codebase/InvokeMember.cs:404)
    10. Unity.VisualScripting.Flow.InvokeDelegate (Unity.VisualScripting.ControlInput input) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:456)
    11. Unity.VisualScripting.Flow.Invoke (Unity.VisualScripting.ControlOutput output) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:347)
    12. Unity.VisualScripting.Flow.Run (Unity.VisualScripting.ControlOutput port) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:240)
    13. Unity.VisualScripting.EventUnit`1[TArgs].Run (Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:182)
    14. Unity.VisualScripting.EventUnit`1[TArgs].Trigger (Unity.VisualScripting.GraphReference reference, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:154)
    15. Unity.VisualScripting.EventUnit`1+<>c__DisplayClass14_0[TArgs].<StartListening>b__0 (TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:67)
    16. Unity.VisualScripting.EventBus.Trigger[TArgs] (Unity.VisualScripting.EventHook hook, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventBus.cs:71)
    17. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].TriggerRegisteredEvent[TArgs] (Unity.VisualScripting.EventHook hook, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:35)
    18. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].TriggerEvent (System.String name) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:13)
    19. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].Start () (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:62)
    Here's full stack trace for my C# script node. It's less descriptive, but it tells exactly where to find the problem. The error causing location is Assets/SetCamera C# script, line 7 that calls Reset() method. From this you know which node (SetCamera.Reset) is causing the problem and in which C# script. You can then use Node Finder to locate the node in all your graphs. Best of all, this will show up in log files outside Unity so you can then effectively debug.

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. SetCamera.Reset (UnityEngine.Camera cam) (at Assets/SetCamera.cs:7)
    3. Unity.VisualScripting.InstanceActionInvoker`2[TTarget,TParam0].InvokeUnsafe (System.Object target, System.Object arg0) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_1.cs:51)
    4. Unity.VisualScripting.InstanceActionInvoker`2[TTarget,TParam0].Invoke (System.Object target, System.Object arg0) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_1.cs:32)
    5. Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
    6. Unity.VisualScripting.InstanceActionInvoker`2[TTarget,TParam0].Invoke (System.Object target, System.Object arg0) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Optimization/InstanceActionInvoker_1.cs:40)
    7. Unity.VisualScripting.Member.Invoke (System.Object target, System.Object arg0) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Reflection/Member.cs:951)
    8. Unity.VisualScripting.InvokeMember.Invoke (System.Object target, Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Codebase/InvokeMember.cs:312)
    9. Unity.VisualScripting.InvokeMember.Enter (Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Codebase/InvokeMember.cs:404)
    10. Unity.VisualScripting.Flow.InvokeDelegate (Unity.VisualScripting.ControlInput input) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:456)
    11. Unity.VisualScripting.Flow.Invoke (Unity.VisualScripting.ControlOutput output) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:347)
    12. Unity.VisualScripting.Flow.Run (Unity.VisualScripting.ControlOutput port) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Flow.cs:240)
    13. Unity.VisualScripting.EventUnit`1[TArgs].Run (Unity.VisualScripting.Flow flow) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:182)
    14. Unity.VisualScripting.EventUnit`1[TArgs].Trigger (Unity.VisualScripting.GraphReference reference, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:154)
    15. Unity.VisualScripting.EventUnit`1+<>c__DisplayClass14_0[TArgs].<StartListening>b__0 (TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Flow/Framework/Events/EventUnit.cs:67)
    16. Unity.VisualScripting.EventBus.Trigger[TArgs] (Unity.VisualScripting.EventHook hook, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventBus.cs:71)
    17. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].TriggerRegisteredEvent[TArgs] (Unity.VisualScripting.EventHook hook, TArgs args) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:35)
    18. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].TriggerEvent (System.String name) (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:13)
    19. Unity.VisualScripting.EventMachine`2[TGraph,TMacro].Start () (at ./Library/PackageCache/com.unity.visualscripting@1.8.0/Runtime/VisualScripting.Core/Events/EventMachine.cs:62)
    This might be partly a tooling issue. Have you tried Rider IDE? It's paid but it has deep Unity integration and does a lot for you automatically like adding namespaces, enforcing code formatting, providing code snippets for stuff like for loop which you don't have to type out manually, etc. Give the free trial a go.
    There's no way to know as far as I'm aware besides using C# reflected nodes like outlined in the example above. Or fully custom implemented C# nodes. But custom nodes are poorly documented and hard to implement for a beginner.
    Converting wouldn't really help much and you'd lose all scene references. Asset graphs can't reference stuff from Hierarchy directly like embeds. If you're sticking with pure VS, it's indeed hard to debug. Hence why I was forced to pick up C# so the project wouldn't have to die. Once I put in the effort, it was well worth it in the end and C# opened a lot of doors that are inaccessible for Visual Scripting alone.

    EDIT:

    You could also try the Try Catch node that'll try to execute a piece of logic and if there's an exception, it won't hardlock the game:

    You can then customize what it prints to console and log file in case of an exception.
     
    Last edited: Jun 19, 2023
    CiroContns likes this.
  6. genryuu111

    genryuu111

    Joined:
    Aug 29, 2019
    Posts:
    6
    Thank you very much, this reply was very insightful.

    I've been exploring the last thing you proposed, but my problem is that I'm heavily using coroutines, and it seems like the try catch node doesn't work with coroutines. Do you have any advice about that?
    This, if I managed to make it work, would help me quite a lot.

    I'm going to try to convert a graph into C# (never done that). As for custom nodes, yeah, quite badly documented BUT I've managed to make some already (to circumvent some of the things lacking in visual scripting).

    I may think about that, thanks.
    Right now I'd like to clean up my project to be able to have it more tested, tried, and hopefully starting a kickstarter and/or finding a publisher. I may think about converting after things settle, right now I don't really have the possibility to halt the project for months to convert everything.

    You're being very helpful, thank you!
     
  7. PanthenEye

    PanthenEye

    Joined:
    Oct 14, 2013
    Posts:
    1,790
    Indeed, this limitation is inherent to the implementation. There are no known workarounds as far as I'm aware. Probably can be solved with a custom node, but I'm not familiar with the internal coroutine logic. This would require diving into the source code to figure out how it handles automatic coroutine creation and disposal.
    Yea, you don't need to convert everything, we didn't either. Just rewrite some of the parts that are producing hard to debug issues.
     
  8. genryuu111

    genryuu111

    Joined:
    Aug 29, 2019
    Posts:
    6
    Thank you very much, that's probably what I'm going to do.
    Honestly, I've gotten better at coding and the issues I'm having now are caused by parts of code that were made a long time ago at this point.
    Thanks!
     
    CiroContns likes this.