Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Assign Property Binder targets via script

Discussion in 'Visual Effect Graph' started by Livealot, Apr 14, 2021.

  1. Livealot

    Livealot

    Joined:
    Sep 2, 2013
    Posts:
    228
    Property binders work great when everything you need is in the scene already and you can manually connect stuff in the Inspector.

    But when everything is spawned at runtime, I need to assign targets to the property binders via script.

    I can't find the right references for that, and the docs only talk about writing a custom property binder as a class.

    I can see the list of binders, but can't drill in further.

    Code (CSharp):
    1. List<VFXBinderBase> currentBindings = myVFX.GetComponent<VFXPropertyBinder>().m_Bindings;
     
  2. Livealot

    Livealot

    Joined:
    Sep 2, 2013
    Posts:
    228
    My current workaround is to create an empty gameobject child under the VFX component's gameobject. In the prefabs, I can manually assign these empty children to their parent's property binder.

    Then, after my real target is spawned, I reparent the empty children to the real targets as needed.

    The other workaround is to skip property binders entirely, and just script the target assignments directly to the exposed properties of the vfxgraph. But then you also need to manage the updating of those targets, for example, in an update loop to set the exposed parameter to the latest position of the target.

    Another tip if you're primarily tracking target positions...there's a world/local toggle on the exposed property in the blackboard that's different than the world/local toggle on blocks that use that property. So if you're getting unexpected results, check that those are each set appropriately for your scenario.
     
    andylewisart likes this.
  3. Zaknarfen

    Zaknarfen

    Joined:
    Jun 29, 2015
    Posts:
    4
    Hey, I was running into the same problem as you were and my solution was a bit different. I grabbed the code from the internal Unity class I needed, called VFXTransformBinder, and I pasted it in a new C# script called
    VFXTransformBinderExternal. You leave the VFXBinder line at the top (line 6), make the class public, and remove the AddComponentMenu line (line 5). After doing this, just add it as a component to any GameObject with a VFXPropertyBinder and it will automatically bind to it.

    The final part is adding a variable with type VFXTransformBinderExternal to a script and setting the target variable dynamically (which is what I needed).

    If you are using Rider as IDE just ctrl+shif+f and paste the class name to find the implementation. I hope this helps other people.
     
  4. andylewisart

    andylewisart

    Joined:
    Nov 4, 2013
    Posts:
    19
    Smart workaround. Saved me a lot of time. Thanks!
     
  5. fdiba

    fdiba

    Joined:
    Aug 17, 2018
    Posts:
    6
    I tried the same solution : use a dumb empty child, then parent the child to the real target but my position has an offset now... How can I remove it ? I tried:

    ChildGameObject1.transform.localPosition = Vector3.zero;

    But its not working.
     
  6. fdiba

    fdiba

    Joined:
    Aug 17, 2018
    Posts:
    6
    I did find a solution by offsetting the vfx object but if you know how i can set the child to its "last parent" position it would be better.
     
  7. alti

    alti

    Joined:
    Jan 8, 2014
    Posts:
    94
    Code (CSharp):
    1.  
    2.     public string findParent;
    3.  
    4.     void Start () {
    5.         StartCoroutine(FindParent());
    6.     }
    7.  
    8.     IEnumerator FindParent(){
    9.         while(GameObject.Find(findParent) == null){
    10.                 yield return null; //finding the parent
    11.             }
    12.         transform.SetParent(GameObject.Find(findParent).transform); //parent found
    13.         transform.position = Vector3.zero;
    14.     }
    1. Assign this scipt to a child object of your VFX gameobject.
    2. Assign that child object to the VFX Binder script component on your VFX gameobject.
    3. type the name of the object you wanted to bind to, into the "find parent" string in the child object's inspector.

    You'll have an extra object in the scene, technically, but it will calculate nothing extra beyond that coroutine.

    Alternatively you can just use an update method on anyscript you reference the vfx graph on and write:
    VisualEffect ve = GetComponent<VisualEffect>();
    Transform target;
    ve.SetVector3(target.position);

    Assign the target by finding it using the method above or whatever way you like. Both do the same thing, but I suspect the former is the most performant.
     
    Last edited: Mar 16, 2022