Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

VFX Graph : How do I set a transform reference / set property binder by script?

Discussion in 'Graphics Experimental Previews' started by marcrem, Oct 15, 2020.

  1. marcrem

    marcrem

    Joined:
    Oct 13, 2016
    Posts:
    341
    Hi,

    In my VFX, I have a reference to a Transform, that I can assign in the scene through the property binder. However, if my VFX is instantiated at runtime, I can't find a way to assign this through script.

    Yeah, I could change my graph to expose a Vector3 for position, another one for Eulers, and another one for scale, but that would be very convenient and simpler if I could do what you can do in the editor.

    So, how do I add / set a property binder through script?

    Thanks!
     
  2. Voronoi

    Voronoi

    Joined:
    Jul 2, 2012
    Posts:
    596
    Did you ever figure this out? The UnityEngine.VFX.Utility.VFXPositionBinder is not accessible, how can I get or add that to a Visual Effect that is playing at runtime?
     
  3. marcrem

    marcrem

    Joined:
    Oct 13, 2016
    Posts:
    341
    Not only you're late, but you also didn't read the original post.
     
  4. marcrem

    marcrem

    Joined:
    Oct 13, 2016
    Posts:
    341
    No, I had to expose all the variables instead :/
     
  5. Faysik

    Faysik

    Joined:
    Oct 26, 2017
    Posts:
    2
    Hi!
    Inside VFXTransformBinder class there is a example of how it's done.
    For my cases i wrote this extension class.

    Code (CSharp):
    1. public static class VFXExtensions
    2. {
    3.     private const string VFXPositionPostfix = "_position";
    4.     private const string VFXRotationPostfix = "_angles";
    5.     private const string VFXScalePostfix = "_scale";
    6.  
    7.     public static void SetVFXTransformProperty(this VisualEffect visualEffect, string propertyName, Transform transform)
    8.     {
    9.         var position = propertyName + VFXPositionPostfix;
    10.         var angles = propertyName + VFXRotationPostfix;
    11.         var scale = propertyName + VFXScalePostfix;
    12.  
    13.         visualEffect.SetVector3(position, transform.position);
    14.         visualEffect.SetVector3(angles, transform.eulerAngles);
    15.         visualEffect.SetVector3(scale, transform.localScale);
    16.     }
    17. }
     
  6. M-Elwy

    M-Elwy

    Joined:
    Jan 28, 2021
    Posts:
    38
    For anybody how face this issue, the solution is to clone VFXTransformBinder to new class

    The new class as below:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.VFX;
    3. using UnityEngine.VFX.Utility;
    4.  
    5. // The VFXBinder Attribute will populate this class into the property binding's add menu.
    6. [VFXBinder("Transform/MyTransform")]
    7. // The class need to extend VFXBinderBase
    8. public class MyVFXTransformBinder : VFXBinderBase
    9. {
    10.     public string Property { get { return (string)m_Property; } set { m_Property = value; UpdateSubProperties(); } }
    11.  
    12.     [VFXPropertyBinding("UnityEditor.VFX.Transform"), SerializeField, UnityEngine.Serialization.FormerlySerializedAs("m_Parameter")]
    13.     protected ExposedProperty m_Property = "Transform";
    14.     public Transform Target = null;
    15.  
    16.     private ExposedProperty Position;
    17.     private ExposedProperty Angles;
    18.     private ExposedProperty Scale;
    19.     protected override void OnEnable()
    20.     {
    21.         base.OnEnable();
    22.         UpdateSubProperties();
    23.     }
    24.  
    25.     void OnValidate()
    26.     {
    27.         UpdateSubProperties();
    28.     }
    29.  
    30.     void UpdateSubProperties()
    31.     {
    32.         Position = m_Property + "_position";
    33.         Angles = m_Property + "_angles";
    34.         Scale = m_Property + "_scale";
    35.     }
    36.  
    37.     public override bool IsValid(VisualEffect component)
    38.     {
    39.         return Target != null && component.HasVector3((int)Position) && component.HasVector3((int)Angles) && component.HasVector3((int)Scale);
    40.     }
    41.  
    42.     public override void UpdateBinding(VisualEffect component)
    43.     {
    44.         component.SetVector3((int)Position, Target.position);
    45.         component.SetVector3((int)Angles, Target.eulerAngles);
    46.         component.SetVector3((int)Scale, Target.localScale);
    47.     }
    48.  
    49.     public override string ToString()
    50.     {
    51.         return string.Format("Transform : '{0}' -> {1}", m_Property, Target == null ? "(null)" : Target.name);
    52.     }
    53. }
    Then add it either by dragging the new class file and dropping to visual effect inspector, or from VFX Property Binder inspector (attached screenshot)


    Then you can access it from script as below:
    Code (CSharp):
    1. MyVFXTransformBinder myTransformBinder =  vfx.GetComponent<MyVFXTransformBinder>();
    2. myTransformBinder.Target = otherGameObject.transform;

    Hope this helps.
     

    Attached Files:

    stfunity, ssojyeti2, ThinhHB and 3 others like this.
  7. hellothxsorrinio

    hellothxsorrinio

    Joined:
    Apr 6, 2019
    Posts:
    4
    Thanks! Works like a charm!
     
  8. DigitalChaotics

    DigitalChaotics

    Joined:
    Dec 18, 2013
    Posts:
    25
    Unfortunate, but true. VFXTransformBinder needs to be public. So do its siblings.
     
  9. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,098
    Code (csharp):
    1. component.SetVector3((int)Scale, Target.localScale);
    Don't you guys think this is en error, and it should be Target.lossyScale ?