Access Terrain Wind Setting and Wind Zone in Unity3D 3.0.02f

URL? I don’t see it, still in 3.4.0f5.

Hi Nividica, I followed both your scripts and tried to apply them to my environment which has a windzone which affects the grass and trees however I have encountered some problems when attaching them to my camera and the windzone object in my environment. The errors that appear on the console are the following which I have posted below. If you can aid me with this I’ll be most grateful. Thanks.

  1. The starting settings of the windzone are :Main=1, Turbulence=1, Pulse Magnitude=0.5, Pulse Frequency=0.01 UnityEngine.Debug:Log(Object)

  2. IndexOutOfRangeException: Array index is out of range. (wrapper stelemref) object:stelemrf (object,intptr,object)

  3. NullReferenceException: Object reference not set to an instance of an object
    ScriptableWindzoneInterface.GetWindZoneValue (System.String MemberName) (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:150)
    ScriptableWindzoneInterface.get_WindMain () (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:45)
    WindzoneController.Start () (at Assets/Standard Assets (Mobile)/Scripts/WindzoneController.cs:16)

  4. Could not find a wind zone to link to: Main Camera (WindzoneController)
    UnityEngine.Debug:LogError(Object)
    ScriptableWindzoneInterface:Init() (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:120)
    WindzoneController:Start() (at Assets/Standard Assets (Mobile)/Scripts/WindzoneController.cs:13)

Hmm, it’s been a while since I last worked with this, but from log#4, it looks like the WindZoneController.cs is not attached to an object that also has a windzone. The object you attached WindZoneController.cs to must also have a windzone component attached, as the reference to the windzone is acquired via the parent object.

Like:
[Object]
+[Attached][Windzone]
+[Attached][WindZoneController.cs]

Not:
[Object1]
+[Attached][Windzone]

[Object2]
+[Attached][WindZoneController.cs]

Also, each WindZoneController.cs controls it’s own windzone, the script is not global, so you cant have something like this:

[Object]
+[Attached][Windzone]
+[Attached][WindZoneController.cs]

[Camera]
+[Attached][WindZoneController.cs]

Making any changes to Camera.WindZoneController would have no effect on Object.Windzone, and in-fact I think it would report errors, as the camera does not have an attached windzone.

The possible issues I can think of are:

  1. WindZoneController.cs is not attached to an object with an attached WindZone
  2. The version of unity your using no longer supports my solution ( I’m running version 3.3.0f4 )
  3. Your building for a platform that doesn’t support introspection. ( The web version does not )

Let me know if this helps any :slight_smile:

Hi Nividica, thanks for your quick response however I’m still having problems. I have attached both the ScriptableWindzoneInterface and WindzoneController scripts to my terrain and thats the only place where script is added not even the camera have the scripts attached or even the trees and grass because its part of the terrain. I also wanted to ask do these scripts allow me to change the values of the windzone from the script itself? because even though there is interaction from the grass and tress from the windzone I’m trying to control the windzone to make dynamic wind as in constant changing wind and if that isn’t possible then changing the values of the windzone values via script would be good. The following errors I’m getting are

  1. Could not find a wind zone to link to: Terrain (WindzoneController)
    UnityEngine.Debug:LogError(Object)
    ScriptableWindzoneInterface:Init() (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:120)
    WindzoneController:Start() (at Assets/Standard Assets (Mobile)/Scripts/WindzoneController.cs:13)

  2. NullReferenceException: Object reference not set to an instance of an object
    ScriptableWindzoneInterface.GetWindZoneValue (System.String MemberName) (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:150)
    ScriptableWindzoneInterface.get_WindMain () (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:45)
    WindzoneController.Start () (at Assets/Standard Assets (Mobile)/Scripts/WindzoneController.cs:16)

Thanks for reading this, sorry if I wrote too much

Hey PEF, ment to get back sooner but I’ve had my head wrapped up in writing code for minecraft :smile:
When I get back home I’ll take a closer look and see if there is something I’m overlooking, and I’ll post some pics of my setup so u can compare.

Hmm, it’s still not finding a Windzone to link to. It’s hard to say where the problem lies since I can’t see the project layout. But no worries, I whiped up a quick example project for you so you can see first hand how I’m doing it. If throws errors with my example project then I would have to guess there is an incompatibility somewhere, version, platform ect.

Yup, the script publicly exposes all the values of the windzone except the mode.

  • WindMain
  • WindTurbulence
  • WindPulseMagnitude
  • WindPulseFrequency
  • Radius

857777–31986–$WindzoneExample.zip (432 KB)

Hey Nividica, thanks for the example it was good to see your layout and your example worked without any errors however I have applied the windzonecontroller to the windzone in my environment however I am still encountering 1 error that keeps re-occuring which I have pasted below. I have provided some screenshots of my environment along with the layout. If you wouldn’t mind looking at them also in the script you mentioned the wind can be controlled. So do I change the value in the Windzonecontroller script where it says

WindMain

WindTurbulence

WindPulseMagnitude

WindPulseFrequency

Radius

  1. IndexOutOfRangeException: Array index is out of range.
    (wrapper stelemref) object:stelemref (object,intptr,object)
    ScriptableWindzoneInterface.set_WindMain (Single value) (at Assets/Standard Assets (Mobile)/Scripts/ScriptableWindzoneInterface.cs:50)
    WindzoneController.Update () (at Assets/Standard Assets (Mobile)/Scripts/WindzoneController.cs:26)


It looks like the line it’s talking about is

set
            {
                // Set the argument
--------------->m_WindZoneArgs[0] = value ;
               
                // Set the value of `windMain`
                SetWindZoneValue( "set_windMain" , m_WindZoneArgs ) ;
            }

Not sure why it would single that one out, just make sure that line still has a 0 in it.

The m_WindZoneArgs should be getting initialized during the objects creation via:

// Used to pass an argument to WindZone setter functions
        object[] m_WindZoneArgs = new object[1] ;

However it may not be, try re-initializing it in the Init() function like this:

 public void Init () {
           
            // Get the windzone of this game object
            m_WindzoneComponent = GetComponent("WindZone");
           
            // Ensure there was a windzone to link to
            if ( m_WindzoneComponent == null ) {
                // Log the error
                Debug.LogError( "Could not find a wind zone to link to: " + this ) ;
               
                // Disable this script for the remainder of the run
                this.enabled = false;
               
                // Stop here
                return ;
            }            

            // Re-initialize the argument array
            m_WindZoneArgs = new object[1] ;          

            // Get the system qualified type
            m_WindzoneType = m_WindzoneComponent.GetType() ;
           
        }

I just wish the line number in the errors lined up better with the actual script, it’s one of those things about unity that’s bugged me for a long time.

Sure, just treat it like any other class’s properties. You can use Update() to check the state game to update and adjust the wind accordingly, or you can use a more event driven approach, like creating a button in the GUI that stops the wind. It all depends on how you want your system set up. If your just looking for some randomness to your wind putting the logic in Update() will work just fine.

Hey Nividica, thanks for your help and there are no errors. However even after your explanation on how to the change the values of the windzone from the script itself I am still not certain. In the WindzoneController script I can see WindMain, WindTurbulence, WindPulseMagnitude, WindPulseFrequency and Radius but my confusion lies because there are no values to change as in terms of numbers. Instead it will say WindTurbulence = WindMain ; but in Unity the default settings are displayed 1 or 0.01. If you have time could you get back to me on this one? Thanks.

OH, You mean in the example script! Yeah I was setting all the values to the same number in the example to make sure everything was working as it should. That script is there as an example of how to create a child class of ScriptableWindzoneInterface, you can use it or create a new child class with this template:

    using UnityEngine;
    using System.Collections;
     
    public class <YOURCLASSNAMEHERE> : ScriptableWindzoneInterface {
     
        // Use this for initialization
        void Start () {
            // Tell the ScriptableWindzoneInterface to initialize
            base.Init() ;
        }
    }

For example if you wanted to make a windzone that responded to a change in the seasons you could do something like this:

    using UnityEngine;
    using System.Collections;
     
    public class NorthernJetStream : ScriptableWindzoneInterface {
     
        // Use this for initialization
        void Start () {
            // Tell the ScriptableWindzoneInterface to initialize
            base.Init() ;
            
            // Set the intial values
            WindMain = 1.0f;
            WindTurbulence = 2.0f;
            WindPulseMagnitude = 3.0f;
            WindPulseFrequency = 4.0f;
	}
       
        // Update is called once per frame
        void Update () {
            // Its autumn or spring make the wind erratic
            if( TheSeason.isAutumn() || TheSeason.isSpring() ) {
                WindMain = Random.Range( 0.0f , 15.0f );
            } else {
                WindMain = 1.0f;
            }
        }
    }

Or like this example that sets the windzone values when the script starts, and then spins the windzone like a floor fan.

    using UnityEngine;
    using System.Collections;     
    public class SpinningFan : ScriptableWindzoneInterface {
        void Start () {
            // Tell the ScriptableWindzoneInterface to initialize
            base.Init() ;
           
            // Set the intilial values
            WindMain = System.DateTime.Now.Second;
            WindTurbulence = 0.1f ;
            WindPulseMagnitude = 0.5f ;
            WindPulseFrequency = 0.2f ;
	     }
      
        // Update is called once per frame
        void Update () {
			this.transform.Rotate( Vector3.up , 1.0f );
        }
    }

Hey Nividica, thanks for the replies. The windzone example which makes the wind erractic depending on the seasons seems like a good option but I have no clue on how to create seasons in Unity. Do you have an idea on how to make this work? Another thing is with the Wind settings in the WinzoneController what does this line do exactly WindMain = Mathf.PingPong( ( Time.time / 2.0F ) , 1.0F ) ; and if I wanted to change the wind values could I use your WindzoneController example and write somethin like this for the wind values?

WindMain = 1.0f

WindTurbulence = 1.0f ;

WindPulseMagnitude = 2.0f ;

WindPulseFrequency = 3.0f ;

Radius = 20f;

Not really :wink: Just sounds like a good idea.

The script reference says:

PingPongs the value t, so that it is never larger than length and never smaller than 0.
The returned value will move back and forth between 0 and length.

How it interacts with my code is that each time Update() is called it adjusts the value of WindMain from 0->1.0 then 1.0->0 (hence ping-pong), the divide by 2 just slows down the rate at which this happens. It is in the example so that you can verify that the script is running and that the values are being adjusted during a test-play(via the inspector)

Yup.

Hey Nividica, thanks for your quick response yet again. I still have a few questions to ask though I am using your WindzoneController example and when I write these values which I have pasted below. The settings are still the default settings on the actual Windzone inside Unity and the console still displays the current settings of the Windzone inside Unity. So how would I get the Windzone to display the values I entered in the script and is there a way to make the wind random without having to use the season example you showed me? My aim is to make the wind dynamic via script or where I can change the values and those values affect the Windzone.

WindMain = Mathf.PingPong( ( Time.time / 2.0F ) , 1.0F ) ;

WindTurbulence = 1.0f ;

WindPulseMagnitude = 2.0f ;

WindPulseFrequency = 3.0f ;

Radius = 20f;

myTerrain.terrainData.wavingGrassSpeed = 0;
myTerrain.terrainData.wavingGrassAmount = 0;
myTerrain.terrainData.wavingGrassStrength = 0;

These are for the wind settings found in the terraindata.

Has anything changed over the years with the wind zones to make all of this easier?

1 Like