0
Answered

How to send Event or set/get Variables from script?

YANG 3 years ago updated by Nabil Majid 1 year ago 19

I just found Bolt today and read some manual pages. Bolt can call other assets(or scripts)'s functions is great (advanced reflection magic). I'm wondering How to Call Bolt's CustomEvent or Set/Get Bolt's Variables from scripts? I can't find a manual about this. So BehaviorDesigner and Playmaker could only be called by Bolt but couldn't call Bolt. This prevents Bolt join my VisualScriptTeam cause it's a deaf player( for now :) ) and I want communications and teamwork.

Bolt Version:
Unity Version:
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):
+2
Pending Review

Hi Yang,

Bolt has an API, but it's not yet documented. There's plan for generating a full API documentation, as you can see in this suggestion:

http://support.ludiq.io/topics/208-full-automated-api-documentation/

In the mean time, you can trigger a custom event like this:

CustomEvent.Trigger("name", arg0, arg1, ...)

For variables, you can use similarly named classes, for example:

SceneVariables.Set("score", 100);

Get, Set and IsDefined methods are available.

Hi Lazio,

Thanks for your reply. Hope to read the API documentation soon. If the API documentation is a thick dictionary book hope could get some key API usages and examples in the manual page as well, cause I think many people using Visual Scripting Tools like me is not a programmer, I could read, modified, and write some simple scripts to bridge Assets, the logic is done with visual tools. Event and variables API is useful for writing a "ProxyBridge" script.

CustomEvent.Trigger() and SceneVariables.Set/Get() seems effect the whole scene. So CustomEvent Name should be different. If there is an event window to display all used custom event, there will be less mistakes of create a new custom event with a used name or trigger the wrong event with wrong name and mess up the logic by accident. String names challenge my typing skill and memory in both Bolt and C# :) 

Best Regards,

YANG

+1

Hi Yang,

Actually, I made a little mistake. CustomEvent.Trigger doesn't affect the whole scene. It takes the target game object as the first argument. For example,

CustomEvent.Trigger(player, "OnDamage", 25);

Furthermore, all other variable scopes are available by script if you don't want to target the whole scene.

For example, if you want to access an object variable on the player game object:

player.GetComponent<Variables>().Set("health", 50);

String names will remain for variable names for ease of use for non-programmers. However, there is an idea for strongly-typed event definitions that don't rely on strings here:

http://support.ludiq.io/topics/251-custom-event-definitions/

The API documentation will take the shape of a class reference, much like the Unity scripting reference. I will include a small section in the manual for script interaction, mostly for basic things like variables and events, but creating tutorials for advanced scripting extensions of Bolt is not on the list of priorities at the moment.

+1

Hi Lazio,

Cool! That will do :)

Sorry, I'm new in Bolt or may be I'm missing something but I can't get access to Scene Variable from C# script like that:

gameObject.GetComponent<Variables>().Set("health", 50);

"Variables" doesn't has a Set method ...

SceneVariables.Set("score", 100);

also didn't work for me...

I'm using Bold namespace, and

CustomEvent.Trigger();

works perfectly for me!


sorry for stupid question... but How to Set Scene Variable from C# script?

Sorry, my bad. Try:

SceneVariables.current.Set("score", 100);

I'll add a helper in a future version for scripting clarity. Something along the lines of:

BoltVariables.scene.Set("score", 100);

Is the reverse possible? Getting a variable that's in a C# script from with a Flow?

+3

Yes, any scripts you write, all public variables will gain access with Bolt. You can set private to be discoverable too. Once you save a script, you can find it in the fuzzy finder under your class as a get and set unit. If you create a method, all parameters show up on the unit as nodes.

Hi. I'm looking for a bit of help with pulling in a variable to Bolt from a script. I've read the above quite a few times and tried a load of stuff out but I just can't get it to work.

I've got a script called "test1" attached to, and enabled on, my character:


This is the code that's sat in my test 1 script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Data;
using System;
using Bolt;
public class test1 : MonoBehaviour {
    public GameObject HeightTest;
    void Start () {
        SceneVariables.current.Set("HeightTest", 83);
    }
    
    void Update () {
        
    }
}

I'm using SceneVariables.current.Set to set the value of the variable that I would like to pass across to Bolt.

But then when I go to add a unit in Bolt I can't see the script in the unit:


Then once I can see the script how do I pull the variable into Bolt? Using a Get Scene Variable unit type?


Many thanks in advance for any help that anyone can give.

+1

All you need to do is go up to Tools > Bolt > Update Unit Options.

Every time a new class is created, you need to add it into the database. It will hot reload just fine after that. You can set variables in a script without doing that, but if you want to interact at all with that script in Bolt, it must be added in. The listings in the fuzzy finder are stored in the Unit Options database.

so now how to get scene variables?

i found it ..

and there is no current and ... is there any introduction about the api?

How would one go about checking for the current state of a State Machine from a c# script? So something like:

var state = StateMachine.CurrentState(gameObject, "StateMachineName");

if(state.Name == "NameOfState")
{
  DoSomething();
}

Thanks

Okay I haven't tested this, but should work: After you get the state, you should be able to do a check by string. So  ' _currentState.graph.title '  would be what your looking for based on this:

public class StateMachineExt : MonoBehaviour
{

    public static StateMachine GetMacroMachine(GameObject target, StateMacro macro)
    {
        var machines = target.GetComponents<StateMachine>();
        StateMachine currentMachine = null;

        foreach(StateMachine machine in machines)
        {
            if (machine.nest.macro == macro)
            {
                currentMachine = machine;
                break;
            }
        }

        return currentMachine;
    }

    public static StateMachine GetEmbedMachine(GameObject target, string title)
    {
        var machines = target.GetComponents<StateMachine>();
        StateMachine currentMachine = null;

        foreach (StateMachine machine in machines)
        {
            if (machine.nest.embed.title == title)
            {
                currentMachine = machine;
                break;
            }
        }

        return currentMachine;
    }

    public static State GetCurrentState(StateMachine machine)
    {
        var index = 0;
        State _currentState = null;

        foreach (State state in machine.nest.embed.states) {
           if (machine.nest.instance.states[index].isActive)
            {
                _currentState = (State)machine.nest.instance.states[index];
                break;
            }
            index++;
        }

        return _currentState;
    }
}


That is way more than I was hoping for! But in using  _currentState.graph.title I get the title of the over all graph (ie EnemyState) not the title of the current state graph the object is in (ie Walking). I am sure I could solve the problem with the head start you gave me with this extension, but I can't get the State object to serialize with Json.NET (the version from the asset store). Doing the following causes the script to break out of the function.

var stateMachine = StateMachineExt.GetEmbedMachine(gameObject, "StateMachineName");
var serializedStateMachine = JsonConvert.SerializeObject(stateMachine);

So if I were to run say a Debug.Log() or CustomEvent.Trigger() after those lines in the same function it would never get called. If I put in a breakpoint before the JsonConvert.SerializeObject() line and run the JsonConvert.SerializeObject(stateMachine) in the Immediate Window I get back:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected with type 'Bolt.ControlConnection'. Path 'nest.embed.lastTransition.nest.embed.units[0].trigger.validConnections[0].source.validConnections'.

Not really sure how to get around this and get the object serialized, but it would help a lot to be able to get that data. It would be a fishing pole instead of a fish. Is there a built in way to get serialized objects out of Bolt? I imagine that there would be something like that with all the saving features it offers. But I haven't gotten to the point of using any of those features yet.

With all that being said, is there a better pattern for getting the current state of a Bolt State Graphs in a script?

Thanks!


This thread is getting very far from the original question (which has been answered), and I would suggest starting another.

Accessing active state data is not something built-in to Bolt because states don't have unique identifiers per se — they're language constructs. You could very well have two or more states with the same nested graph title, for example, nothing prevents it. The suggested workaround is to set a variable of your choosing upon entering the state (it only takes one node!).

If you insist on getting the data from the (not necessarily stable) API, you'll want to use state.nest.graph.title, not state.graph.title.

Sorry about that, what I was asking definitely went a little sideways. I will re-ask about the serialization in a new topic. But with what you have given me here and the help from JasonJonesLASM I should be able to do what I need. Thanks!

Is it possible to comunicate from an app to another app? Example i have a buttom in my app when i press the buttom, the other app needs to be open already, then appears a buttom to confirm my action in that other app. Is possible with playmaker?