The process of detecting game progress (character's HP drop, collision position, spell charging completion, etc.) using C# and dynamically controlling the speed, emitted light color, and emission amount of the VFX Graph effect accordingly is the basis of production in game development. However, the problem that the effect does not respond at all even though the correct code has been written in the script frequently occurs in many production sites. In this article, we will explain the mechanism of this communication disconnection bug in an easy-to-understand manner using the analogy of ``forgetting to connect an extension at the office,'' and provide confirmation procedures to ensure correct operation and highly efficient optimization code.
1. Understand with an analogy: ``Omitted extension registration and spelling mistakes at the reception''
In order to intuitively understand this bug in which the value from C# to VFX is not delivered, let's consider ``The process of making a call from an external business partner to an internal person in charge'' as an example.
Suppose that you, as a business partner (C# script), want to call the ``color change person (property)'' at a certain company (VFX Graph) and give the instruction to ``change the color to red (SetVector4).'' However, at the company's reception desk (VFX Blackboard settings), the "Exposed" setting, which allows the person in charge to receive direct calls from outside, was turned off. Furthermore, the spelling of the name you tried to call (designated name in C#) did not match the "official real name (Reference Name)" of the person in charge registered in the list at the reception desk, so you tried to call him by his nickname (Display Name).
The receptionist quietly hangs up and says, ``There is no person in charge with that extension number and name registered in the company,'' completely ignoring this order. Since you, who are outside the office, do not receive any error notifications, you assume that the command was transmitted correctly, and the person in charge inside the office repeats the initial setting (Default Value) without doing anything.
This discrepancy is the truth behind 'Exposed publication omission' and 'Reference Name mismatch bug'. For safety reasons, VFX Graph only allows variables that are explicitly exposed externally (C#) to be rewritten. Also, use strictly internal system names for identification, not display names. If these are out of sync, Unity will ignore the process without even issuing a warning error.
2. Solution A: Sync Exposed check and Reference Name in Blackboard
To resolve this bug, open the settings on the VFX Graph asset side and properly sync the extension exposure settings and roster registration.
Setup steps:
- Open the target VFX Graph asset.
- Look at the variable list panel called ``Blackboard'' in the top left of the editor. If it is not visible, turn on the "Blackboard" button in the menu bar.
- Check the left edge of the variable you want to change from C#. If the round checkmark (Exposed) is gray (unpublished), click it to turn it solid green (exposed).
- Select the variable and check its properties in the Inspector window.
- Check the name written in the Reference field (e.g. `BaseColor` instead of `_BaseColor`) and note the exact case, presence of underscores (`_`), etc.
- When setting the value on the C# script side, enter the name of this "Reference" exactly as the string argument.
*A common mistake is to try to access from C# using the display name on Blackboard, ``Display Name'' (e.g. `Base Color` *with spaces), but this does not work. Be sure to use the same name entered in "Reference".
3. Solution B: Faster script implementation using hash IDs (professional optimization)
When you call `vfx.SetFloat("MyParameter", value)` from C# with a string every frame (e.g. in `Update`), Unity internally performs a string search every frame, which reduces CPU load (GC Alloc) occurs and dust accumulates, leading to a drop in frame rate.
In practice, in order to avoid string searches, a professional optimization technique is to convert the name to a hash value (`int`) in advance and pass the value by specifying the ID.
using UnityEngine;
using UnityEngine.VFX;
[RequireComponent(typeof(VisualEffect))]
public class VfxParameterController : MonoBehaviour
{
private VisualEffect vfx;
private float currentCharge = 0f;
// 1. Prepare a variable to cache the static hash ID (eliminate string references)
private static readonly int ChargeAmountID = Shader.PropertyToID("ChargeAmount");
private static readonly int CoreColorID = Shader.PropertyToID("CoreColor");
void Start()
{
vfx = GetComponent();
}
void Update()
{\
currentCharge += Time.deltaTime * 0.5f;
if (currentCharge > 1.0f) currentCharge = 0f;
if (vfx != null)
{
// 2. Set parameters using cached integer IDs
// This eliminates string search overhead and memory allocation every frame
vfx.SetFloat(ChargeAmountID, currentCharge);
vfx.SetVector4(CoreColorID, Color.Lerp(Color.blue, Color.red, currentCharge));
}
}
}
By thoroughly implementing this code structure, not only is it 100% guaranteed that the values from C# will be reflected, but you will also be able to achieve extremely lightweight and smooth production control that does not cause any garbage collection even when executed every frame.