Method returning wrong value

I have been trying to write a piece of code that generates a random float called WindSpeed, between an upper and lower bound. then returning this value so other scripts can use it.

The variable is randomly generated properly but when I check the debug log, the returned value for WindSpeed is always 0.

public class WindRandomiser : MonoBehaviour
{
    [SerializeField] float WindSpeedUpperBound, WindSpeedLowerBound;
    float WindSpeed = 1f;
    void Start()
    {
        // this generates a random float between the upper and lower bound
        ChangeWindSpeed(ref WindSpeed);
    }
    private void ChangeWindSpeed(ref float WindSpeed)
    {
        WindSpeed = UnityEngine.Random.Range(WindSpeedLowerBound, WindSpeedUpperBound);
        Debug.Log("WindSpeed at start:" + WindSpeed);
    }
    public float GetWindSpeed()
    {
        // this allows other scripts to access/get the value of WindSpeed without being able to change it
        Debug.Log("WindSpeed at return: " + WindSpeed);
        return WindSpeed;
    }
}

There are a few things not clear. You have two debug logs in your code and when you said it returns the value of 0 I guess you only talk about the GetWindSpeed method?

Where and when are you actually call that GetWindSpeed method? Since you “change” the windspeed in Start, that may happen after you called GetWindSpeed so the variable hasn’t yet been initialized.

The next issue may be related to how you actually reference this script instance. Are you sure that the caller of GetWindSpeed ACTUALLY has a reference to the actual instance in the scene? Note that you can call this method on a prefab that sits in your project, but that prefab does never get its Start method called.

Try adding a context object to your debug.log statement like this:

    public float GetWindSpeed()
    {
        Debug.Log("WindSpeed at return: " + WindSpeed, gameObject);
        return WindSpeed;
    }

Now you can simply click on the log in the console and Unity will “ping” / highlight that context object you provided. So try this and click the log and see what object the method is actually called on.

1 Like

Just out of curiosity… Wouldn’t that kind of script make more sense as a ScriptableObject? That way it’s an actual asset in your project and not tied to a scene. ScriptableObjects get only a few callbacks, but Awake and OnEnable are called which can be used to roll your random number. As an asset it can be referenced from anywhere, even from prefabs.

Of course it depends on your actual usecase. If you need more inspiration how to use ScriptableObjects, I can recommend the Unite talk from 2017 by Ryan Hipple. I timestamped the section about modularizing data, but the whole talk is worth watching :slight_smile: Note that this is not THE way to go about things. It’s just a potential tool in your belt which can be quite powerful.

1 Like

It’s set to 1f by default. Try to disable generator. If it still return 0, then probably you just referenced something else in external scripts. Also, while it’s absolutely wrong thing to do in long run, for now you could try to use singleton to ensure you always have correct reference point. Just don’t become too attached to the pattern, you’ll need to unlearn it on some point :^)

I will assume (without testing) that your problem is related to passing the WindSpeed field by ref to ChangeWindSpeed. It isn’t necessary and it is confusing. Simply set the WindSpeed to the random value in Start.

Also as a habit include the name of the method in your Log statements so you have some identifying context.

Or learn just how trivial it can be to make your singleton a “multiton” and keep going.

And yes, maybe one day OP wants to have more than one wind direction going, and in this case it really isn’t a big deal to turn the “WindSingleton” into a “WindManager” and make an API to pass in which wind system you are caring about, or perhaps your position, which can be used to find which wind system you need.

Despite all the gnashing of teeth by the CompSci people, we all keep using the singleton pattern because a) it solves a lot of irritating OO patterns quickly and easily without introducing layers of “passing around this” complexity, and b) it is easy to reason about what is happening.

Personally I just made the entire weather system static in Jetpack Kurt and I haven’t worried about it since. Keep it simple. Your future self will thank you. Enclosed here just for grinners… it’s a mess of stuff, grown to hairy proportions, but hey it works and I’ve never had “hard bugs” in it.

WeatherController.cs:

using UnityEngine;
using System.Collections;

public static partial class WeatherController
{
	public static void InitGame()
	{
		WindHeading = Random.Range (0, 360);

		StartWeatherVariability();
		CallEveryUpdate.Create( UpdateWeatherVariability);
	}

	// Wind effects are calculated as the delta from your velocity
	// to the wind velocity. Even in zero wind conditions this causes
	// a noticeable damping effect. Therefore, we will run the wind
	// velocities at a much higher scale such that they impinge on you
	// right up to the point where your damping takes it out, but your
	// free-flight motion is not noticeably more-damped than before.
	public	const	float WindToPlayerVelocityAdjustmentFactor = 5.0f;

	public	static	float			WindHeading { get; private set; }

	public	static	float			WindVelocity { get; private set; }

	public	static	Vector3			CurrentWind
	{
		get
		{
			switch (SETTINGS.WindStrength)
			{
			default :
			case WeatherWindStrength.CALM:
				return Vector3.zero;
			case WeatherWindStrength.LOW:
				WindVelocity = 3.0f;
				break;
			case WeatherWindStrength.MEDIUM:
				WindVelocity = 10.0f;
				break;
			case WeatherWindStrength.HIGH:
				WindVelocity = 25.0f;
				break;
			case WeatherWindStrength.HURRICANE:
				WindVelocity = 40.0f;
				break;
			}
			return Quaternion.Euler (0, WindHeading, 0) * Vector3.forward *
				WindToPlayerVelocityAdjustmentFactor * WindVelocity *
				WindVariabilityCurrentMagnitude;
		}
	}

	static TurbulenceController turbulenceDisplacement;

	public static Vector3 CurrentTurbulenceDisplacement
	{
		get
		{
			if (!turbulenceDisplacement)
			{
				turbulenceDisplacement = TurbulenceController.Create (
					SETTINGS.CurrentTurbulence);
			}

			return turbulenceDisplacement.GetTurbulenceVector ();
		}
	}

	static TurbulenceController turbulenceController;

	public static Vector3 CurrentTurbulenceAttitude
	{
		get
		{
			if (!turbulenceController)
			{
				turbulenceController = TurbulenceController.Create (
					SETTINGS.CurrentTurbulence);
			}

			return turbulenceController.GetTurbulenceVector ();
		}
	}
}

WeatherController_Variability.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static partial class WeatherController
{
	static int WindVariabilitySwingSign;
	static float WindVariabilitySwingRate;

	// when zero, time to change swing sign
	static float WindVariabilitySignChangeTimer;

	static float WindVariabilityCurrentMagnitude;
	static float WindVariabilityDesiredMagnitude;
	const float WindVariabilityMagnitudeChangeRate = 0.35f;
	static float WindVariabilityLowerMagnitude;
	static float WindVariabilityUpperMagnitude;

	// when zero, time to change magnitude
	static float WindVariabilityMagnitudeChangeTimer;

	static void StartWeatherVariability()
	{
		RechooseWeatherWindHeadingVariance();

		WindVariabilityCurrentMagnitude = 1.0f;

		RechooseWeatherWindMagnitudeVariance();
	}

	static void RechooseAngleSwingSpeed()
	{
		WindVariabilitySwingRate = 0.0f;

		switch( SETTINGS.WindVariability)
		{
		case WeatherWindVariability.STEADY :
			WindVariabilitySwingSign = 0;
			break;
		case WeatherWindVariability.LOW :
			WindVariabilitySwingRate = Random.Range( 1.0f, 2.0f);
			break;
		case WeatherWindVariability.MEDIUM :
			WindVariabilitySwingRate = Random.Range( 2.0f, 5.0f);
			break;
		case WeatherWindVariability.HIGH :
			WindVariabilitySwingRate = Random.Range( 4.0f, 8.0f);
			break;
		case WeatherWindVariability.TORNADO :
			WindVariabilitySwingRate = Random.Range( 5.0f, 15.0f);
			break;
		}
	}

	static void RechooseDesiredWindMagnitude()
	{
		switch( SETTINGS.WindVariability)
		{
		case WeatherWindVariability.STEADY :
			WindVariabilityLowerMagnitude = 1.0f;
			WindVariabilityUpperMagnitude = 1.0f;
			break;
		case WeatherWindVariability.LOW :
			WindVariabilityLowerMagnitude = 0.8f;
			WindVariabilityUpperMagnitude = 1.2f;
			break;
		case WeatherWindVariability.MEDIUM :
			WindVariabilityLowerMagnitude = 0.5f;
			WindVariabilityUpperMagnitude = 1.4f;
			break;
		case WeatherWindVariability.HIGH :
			WindVariabilityLowerMagnitude = 0.3f;
			WindVariabilityUpperMagnitude = 1.6f;
			break;
		case WeatherWindVariability.TORNADO :
			WindVariabilityLowerMagnitude = -2.0f;
			WindVariabilityUpperMagnitude = 2.0f;
			break;
		}

		WindVariabilityDesiredMagnitude = Random.Range(
			WindVariabilityLowerMagnitude, WindVariabilityUpperMagnitude);
	}

	static void RechooseWeatherWindHeadingVariance()
	{
		WindVariabilitySwingSign = Random.Range( 0, 3) - 1;

		WindVariabilitySignChangeTimer = Random.Range( 5.0f, 20.0f);

		RechooseAngleSwingSpeed();
	}

	static void RechooseWeatherWindMagnitudeVariance()
	{
		WindVariabilityMagnitudeChangeTimer = Random.Range( 5.0f, 20.0f);

		RechooseDesiredWindMagnitude();
	}

	static void UpdateWeatherVariability()
	{
		WindVariabilitySignChangeTimer -= Time.deltaTime;
		if (WindVariabilitySignChangeTimer < 0)
		{
			RechooseWeatherWindHeadingVariance();
		}

		WindVariabilityMagnitudeChangeTimer -= Time.deltaTime;
		if (WindVariabilityMagnitudeChangeTimer < 0)
		{
			RechooseWeatherWindMagnitudeVariance();
		}

//		DSM.Debug.Value = WindHeading.ToString("0") + " / " +
//			WindVariabilitySignChangeTimer.ToString("0.0") + " / " +
//			WindVariabilitySwingSign.ToString("0") + "\n" +
//			WindVariabilityCurrentMagnitude.ToString("0.0") + " / " +
//			WindVariabilityMagnitudeChangeTimer.ToString("0.0");

		WindHeading += WindVariabilitySwingRate * WindVariabilitySwingSign * Time.deltaTime;

		WindVariabilityCurrentMagnitude = Mathf.MoveTowards( WindVariabilityCurrentMagnitude,
			WindVariabilityDesiredMagnitude, WindVariabilityMagnitudeChangeRate * Time.deltaTime);
	}
}

TurbulenceController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurbulenceController : MonoBehaviour
{
	float turbphase1, turbrate1;		// xrot
	float turbphase2, turbrate2;		// yrot
	float turbphase3, turbrate3;		// magnitude

	TurbulenceConfiguration config;

	public static TurbulenceController Create ( TurbulenceConfiguration config)
	{
		TurbulenceController tc = new GameObject ("TurbulenceController.Create();").
			AddComponent<TurbulenceController> ();

		tc.config = config;

		return tc;
	}

	public	Vector3	GetTurbulenceVector()
	{
		Vector3 Direction = Quaternion.Euler (turbphase1, turbphase2, 0) * Vector3.forward;

		float rawSine = Mathf.Sin( Mathf.Deg2Rad * turbphase3) + config.DutyCycleSineOffset;

		rawSine *= config.DutyCycleMagnitude;

		float Magnitude = Mathf.Clamp( rawSine, 0.0f, 1.0f);
		
		Magnitude *= config.Multiplier;

		Vector3 Turbulence = Direction * Magnitude;
		Turbulence.y /= 2.0f;		// nerf it on the vertical

		// general upscale
		Turbulence *= 2.0f;

		return Turbulence;
	}

	void Start()
	{
		turbphase1 = Random.Range (360, 720);
		turbphase2 = Random.Range (360, 720);
		turbphase3 = Random.Range (360, 720);
	}

	void Update ()
	{
		turbphase1 += config.Frequency * turbrate1 * Time.deltaTime;
		if (turbphase1 < 0 || turbphase1 > 360)
		{
			if (turbphase1 < 0)
				turbphase1 += 360;
			else
				turbphase1 -= 360;
			turbrate1 = Random.Range( 100, 250) * (Random.Range( 0, 2) * 2 - 1);
		}
		
		turbphase2 += config.Frequency * turbrate2 * Time.deltaTime;
		if (turbphase2 < 0 || turbphase2 > 360)
		{
			if (turbphase2 < 0)
				turbphase2 += 360;
			else
				turbphase2 -= 360;
			turbrate2 = Random.Range( 100, 250) * (Random.Range( 0, 2) * 2 - 1);
		}

		turbphase3 += turbrate3 * Time.deltaTime * config.MagnitudeRateChangeSpeed;
		if (turbphase3 < 0 || turbphase3 > 360)
		{
			if (turbphase3 < 0)
				turbphase3 += 360;
			else
				turbphase3 -= 360;
			turbrate3 = Random.Range( 100, 200) * (Random.Range( 0, 2) * 2 - 1);
		}
	}
}