0
votes

I'm trying to dynamically resize particles using a slider, as well as change their colour.

Particles are used to display datapoints in a 3D scatterplot. I'm using this code: https://github.com/PrinzEugn/Scatterplot_Standalone

private ParticleSystem.Particle[] particlePoints;
void Update () {
    pointScale = sizeSlider.value;
    for (int i = 0; i < pointList.Count; i++) {
        Quaternion quaternion = Camera.current.transform.rotation;
        Vector3 angles = quaternion.eulerAngles;
        // Set point color
        particlePoints[i].startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
        particlePoints[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
    }

}

The issue is that there's no transform method for Particles, and changing the "startColour" doesn't change anything.

The API states that "The current size of the particle is calculated procedurally based on this value and the active size modules."

What does that mean, and how can I change the size of the particles ?

2
What exactly do you want to do with the size? You can check Particle.startSize for giving them different sizes on start ... later they are changed according to your settings in e.g. SizeBySpeed or SizeOverLifetimederHugo
I want the user to be able to resize all of them using the slider (or any other input).Spoutnovitch
Please make sure what you really want to change, the particle size or the particle system size? The first problem is simple, change ParticleSystem.main.startSize will make sense but looks strange. A particle system apparence is not affected by size only, also consider speed, force, particle count...shingo

2 Answers

0
votes

Thanks to previous answers I managed to get this working:

In the PlacePrefabPoints method I add every instantiated prefab to a List, and I add a listener to the slider, which looks like this:

void changedPointSize(){
    pointScale = sizeSlider.value;
    for (int i = 0; i < objects.Count; i++) {
        objects[i].transform.localScale = new Vector3(pointScale, pointScale, pointScale);
    }
}

Thanks all !

0
votes

I just had a look at PointRenderer.cs -> CreateParticles and PlacePrefabPoints give a good hint what has to be changed.

So I guess you would simply change the scale values

foreach (var point in particlePoints) 
{
    Quaternion quaternion = Camera.current.transform.rotation;
    Vector3 angles = quaternion.eulerAngles;
    // Set point color
    point.startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
    point.startSize = sizeSlider.value;
}

and than re-call

GetComponent<ParticleSystem>().SetParticles(particlePoints, particlePoints.Length);

it is questionable though if you really would do this in Update. I would rather do it in sizeSlider.onValueChanged to only do it when neccesarry (you could even make a certain treshold that has to be changed before updating the view) but well for the color there might be no other option than doing it in Update but atleast there I would use a Threshold:

privtae ParticleSystem ps;

// I assume you have that referenced in the inspector
public Slider sizeSlider;

// flag to control whether system should be updated
private bool updateSystem;

privtae void Awake()
{
    ps = GetComponent<ParticleSystem>();
}

private void OnEnable()
{
    // add a listener to onValueChanged
    // it is secure to remove it first (even if not there yet)
    // this makes sure it is not added twice
    sizeSlider.onValueChanged.RemoveListener(OnsliderChanged());
    sizeSlider.onValueChanged.AddListener(OnsliderChanged());
}

private void OnDisable()
{
    // cleanup listener
    sizeSlider.onValueChanged.RemoveListener(OnsliderChanged());
}

private void OnSliderChanged()
{
    foreach (var point in particlePoints) 
    {
        point.startSize = sizeSlider.value; 
    }

    // do the same also for the instantiated prefabs
    foreach(Transform child in PointHolder.transform)
    {
        child.localScale = Vecto3.one * sizeSlider.value;
    }

    updateSystem = true;
}

private Quaternion lastCameraRot;

public float CameraUpdateThreshold;

private void Update()
{
    if(Quaternion.Angle(Camera.current.transform.rotation, lastCameraRot) > CameraUpdateThreshold)
    {
        foreach (var point in particlePoints) 
        {
            Quaternion quaternion = Camera.current.transform.rotation;
            Vector3 angles = quaternion.eulerAngles;
            // Set point color
            point.startColor = new Color(angles.x, angles.y, angles.z, 1.0f);
        }

        lastCameraRot = Camera.current.transform.rotation;
        updateSystem = true;
    }

    if(!updateSystem) return;

    updateSystem = false;
    ps.SetParticles(particlePoints, particlePoints.Length);
}