VJ attempting to learn Unity - material question

Hi,

I'm a amateur programmer having used code mainly for artistic purposes, I"m a VJ musician, etc. etc. I know the basics of programming having used java in Processing and Eclipse.

I'm loving the possibilities of unity for live performance.

I have created my first script - just to change a materials colour using the mouse, but presumably the material glitches because I am attempting to change the material to quickly. Any suggestions how I should guard against this. How can I ensure the the mesh's material will change smoothly and whithout artifacting.

I have attached the script below to a mesh.

function Update () {
    var x = Input.GetAxis("Mouse X");   
    print(x);
    var color = Color (0.2, x, 0.9);

renderer.material.SetColor ("_Color", color);

}

All help gratefully appreciated

Tim

Hey there. First off, I think it's a very interesting idea!

The glitch that you're seeing isn't actually to do with changing the material too quickly. There are a few reasons:

  1. The value of GetAxis is updating every frame, which is ~0.0166 seconds at 60FPS. If your mouse input rate fluctuates even SLIGHTLY in that time, you'll get fairly drastic colour changes, which is why some frames it flickers white, and then back to strong blue.
  2. GetAxis returns a value from -1 to 1, so when the mouse is still, or moving slightly to the left, the object will be full blue. You can add 1 and halve the result to get it as a value between 0 and 1. Also, on frames that you aren't moving the mouse, the GetAxis movement will be 0. Even with the '(value+1)/2' workaround I suggested, you'll need to ifcheck for the input being 0.

I can think of a few ways you might try to fix this.


Limit the amount that the color can change per frame (in my opinion, best result so far):

var maxChange : float = 0.05; // maximum amount the color can change by per frame

function Update ()
{
   var inputX : float = Input.GetAxis("Mouse X");

   if ( inputX != 0 )
   {
      inputX = (inputX+1)/2;
      var currGValue : float = renderer.material.color.g;
      var colorX : float = Mathf.Clamp(inputX, currGValue-maxChange, currGValue+maxChange);
      renderer.material.color = Color(0.2, colorX, 0.9);
   }
}


Average the input and only change the color once every few updates:

var updateFrequency : float = 0.15;    // seconds between update
private var inputX : float = 0.0;      // the accumulative x input per frame
private var updateTime : float = 0.0;  // the accumulated update delta time
private var updates : int = 0;         // actual number of updates

function Update ()
{
    inputX += (Input.GetAxis("Mouse X")+1)/2;
    updateTime += Time.deltaTime;
    updates++;

    if ( updateTime >= updateFrequency )
    {
        var colorX = Color (0.2, inputX/updates, 0.9);
        updateTime = inputX = updates = 0;
        renderer.material.SetColor ("_Color", colorX);
    }
}


  • Lerp between the colors with a clamped change of rate.

I'm still working through some ideas myself. I have noticed that very small input values can still make the color appear to flicker.

Hopefully this will get you started.