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);
}
}
}