private void UpdateProfile() { // clients will get the transition sent to them via network extension if (WeatherMakerScript.Instance == null || !WeatherMakerScript.Instance.NetworkConnection.IsServer || (SingleProfile == null && ProfileGroup == null)) { return; } else if (SingleProfile == null) { currentProfileSingle = null; if (secondsRemainingTransition <= 0.0f) { if ((secondsRemainingHold -= Time.deltaTime) <= 0.0f) { // setup new transition WeatherMakerProfileScript oldProfile = currentProfile; currentProfile = ProfileGroup.PickWeightedProfile(); RangeOfFloats duration = TransitionDuration; currentProfile = WeatherMakerProfileGroupScript.OverrideProfile(currentProfile, CloudProfile, SkyProfile, AuroraProfile, PrecipitationProfile, FogProfile, WindProfile, LightningProfile, SoundProfile, duration, HoldDuration); secondsRemainingTransition = currentProfile.RandomTransitionDuration(); secondsRemainingHold = currentProfile.RandomHoldDuration(); NotifyThoseInZoneOfProfileChange(oldProfile, currentProfile, secondsRemainingTransition); CleanupProfile(oldProfile); } } else { // else let the transition continue secondsRemainingTransition -= Time.deltaTime; } } else if (SingleProfile != currentProfileSingle) { currentProfileSingle = SingleProfile; WeatherMakerProfileScript oldProfile = currentProfile; RangeOfFloats duration = TransitionDuration; currentProfile = WeatherMakerProfileGroupScript.OverrideProfile(SingleProfile, CloudProfile, SkyProfile, AuroraProfile, PrecipitationProfile, FogProfile, WindProfile, LightningProfile, SoundProfile, duration, HoldDuration); secondsRemainingTransition = currentProfile.RandomTransitionDuration(); NotifyThoseInZoneOfProfileChange(oldProfile, SingleProfile, secondsRemainingTransition); CleanupProfile(oldProfile); } }
/// <summary> /// Pick a random profile based on weights of the profiles /// </summary> /// <returns>Random weighted profile or null if no profiles setup</returns> public WeatherMakerProfileScript PickWeightedProfile() { if (Profiles == null || Profiles.Length == 0) { return(null); } int maxWeight = 0; // ensure profiles are sorted by weight ascending sortedProfiles.Clear(); sortedProfiles.AddRange(Profiles); sortedProfiles.Sort(this); // get the max weight (sum of all weights) foreach (WeatherMakerProfileAndWeight w in sortedProfiles) { if (!w.Profile.Disabled) { maxWeight += w.Weight; } } // pick a weight that we need to exceed to pick a profile int randomWeight = UnityEngine.Random.Range(0, maxWeight); // interate all profiles, as we sum up the weight and it crosses are random weight, we have our profile foreach (WeatherMakerProfileAndWeight profile in sortedProfiles) { if (!profile.Profile.Disabled) { if (randomWeight < profile.Weight) { WeatherMakerProfileScript individualProfile = profile.GetProfile(); return(OverrideProfile(individualProfile, CloudProfile, SkyProfile, AuroraProfile, PrecipitationProfile, FogProfile, WindProfile, LightningProfile, SoundProfile, TransitionDuration, HoldDuration)); } randomWeight -= profile.Weight; } } // shouldn't get here Debug.LogError("Error in PickWeightedProfile algorithm, should not return null here"); return(null); }
private void TargetRpcWeatherProfileChanged(NetworkConnection conn, string oldProfileName, string oldProfileJson, string newProfileName, string newProfileJson, float transitionDuration) { if (netId != 0 && isClient && WeatherMakerScript.Instance != null) { // notify any listeners of the change - hold duration is -1.0 meaning the server will send another profile when it is ready (hold duration unknown to client) WeatherMakerProfileScript oldProfileFromJson = null; WeatherMakerProfileScript newProfileFromJson = null; if (oldProfileName != null && oldProfileJson != null) { oldProfileFromJson = GameObject.Instantiate(Resources.Load <WeatherMakerProfileScript>(oldProfileName)); JsonUtility.FromJsonOverwrite(oldProfileJson, oldProfileFromJson); } if (newProfileName != null && newProfileJson != null) { newProfileFromJson = GameObject.Instantiate(Resources.Load <WeatherMakerProfileScript>(newProfileName)); JsonUtility.FromJsonOverwrite(newProfileJson, newProfileFromJson); } WeatherMakerScript.Instance.RaiseWeatherProfileChanged(oldProfileFromJson, newProfileFromJson, transitionDuration, -1.0f, true, null); } }
private void Update() { UpdateMainThreadActions(); #if UNITY_EDITOR if (transform.position != Vector3.zero || transform.localScale != Vector3.one || transform.rotation != Quaternion.identity) { Debug.LogError("For correct rendering, weather maker prefab should have position and rotation of 0, and scale of 1."); } #endif // only for editor mode, detect when inspector has dragged in a new profile if (_WeatherProfile != lastProfile) { if (WeatherProfileChanged != null) { WeatherProfileChanged.Invoke(lastProfile, _WeatherProfile); } lastProfile = _WeatherProfile; UpdateWeatherProfile(); } #if UNITY_EDITOR if (Application.isPlaying) { #endif CheckForPrecipitationChange(); UpdateCollision(); UpdateClouds(); #if UNITY_EDITOR } #endif UpdateShaders(); UpdateCameras(); LightManagerScript.Sun = Sun; LightManagerScript.Moons = Moons; }
/// <summary> /// Call whenever the weather profile needs to change, handles client/server, etc. /// If no networking or network server, this will perform the transition. /// WeatherProfileChanged will then be called. /// </summary> /// <param name="oldProfile">Old weather profile</param> /// <param name="newProfile">New weather profile</param> /// <param name="transitionDuration">Transition duration</param> /// <param name="holdDuration">Hold duration</param> /// <param name="forceTransition">True to force a transition, false otherwise. True means it was forced from a server or some other way.</param> /// <param name="connectionIds">Connection ids to send to (null for none or single player)</param> public void RaiseWeatherProfileChanged(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDuration, float holdDuration, bool forceTransition, string[] connectionIds) { // default behavior is to perform transition if (forceTransition || !NetworkConnection.IsConnected) { // if no network involved OR we are a client and we got a server update, perform the fast transition if needed if (!HasHadWeatherTransition) { HasHadWeatherTransition = true; transitionDuration = 0.001f; } Debug.LogFormat("Changing weather profile {0} to {1}, transition time: {2}, hold time: {3}", (oldProfile == null ? "None" : oldProfile.name), (newProfile == null ? "None" : newProfile.name), transitionDuration, (holdDuration <= 0.0f ? "Unknown" : holdDuration.ToString(CultureInfo.InvariantCulture))); newProfile.TransitionFrom(this, oldProfile, transitionDuration); } // notify listeners, if using network this should notify the network script to blast out a transition to all clients if (WeatherProfileChangedEvent != null) { WeatherProfileChangedEvent.Invoke(oldProfile, newProfile, transitionDuration, connectionIds); } }
/// <summary> /// Profile change event for aurora manager /// </summary> /// <param name="oldProfile">Old profile</param> /// <param name="newProfile">New profile</param> /// <param name="transitionDelay">Transition delay</param> /// <param name="transitionDuration">Transition duration</param> public void WeatherProfileChanged(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDelay, float transitionDuration) { CloudScript.AuroraAnimationDuration = transitionDelay + transitionDuration; CloudScript.AuroraProfile = newProfile.AuroraProfile; }
public void TransitionFrom(IWeatherMakerProvider managers, WeatherMakerProfileScript script, float transitionDuration) { if (managers == null) { return; } float precipitationIntensity = (PrecipitationProfile == null ? 0.0f : PrecipitationProfile.IntensityRange.Random()); float cloudChangeDuration; float precipitationChangeDelay; float precipitationChangeDuration; transitionDuration = (transitionDuration <= 0.0f ? float.MaxValue : transitionDuration); if (precipitationIntensity == 0.0f) { // changing to no precipitation, no delay in reduction of precipitation precipitationChangeDelay = 0.0f; // get precipitation removed quickly precipitationChangeDuration = transitionDuration * 0.5f; // clouds take full duration to transition out cloudChangeDuration = transitionDuration; } else { // delay change in precipitation so clouds, etc. have time to animate in precipitationChangeDelay = transitionDuration * 0.4f; // precipitation animates in with remainder of time after delay precipitationChangeDuration = transitionDuration - precipitationChangeDelay; // clouds animate in faster, we want them mostly in before precipitation gets going cloudChangeDuration = transitionDuration * 0.7f; } // notify precipitation manager if (managers.PrecipitationManager != null) { managers.PrecipitationManager.WeatherProfileChanged(script, this, precipitationChangeDelay, precipitationChangeDuration); } // notify clouds if (managers.CloudManager != null) { managers.CloudManager.WeatherProfileChanged(script, this, 0.0f, cloudChangeDuration); } // notify sky if (managers.SkyManager != null) { managers.SkyManager.WeatherProfileChanged(script, this, 0.0f, transitionDuration); } // notify aurora if (managers.AuroraManager != null) { managers.AuroraManager.WeatherProfileChanged(script, this, 0.0f, transitionDuration); } // notify fog if (managers.FogManager != null) { managers.FogManager.WeatherProfileChanged(script, this, 0.0f, transitionDuration); } // notify wind if (managers.WindManager != null) { managers.WindManager.WeatherProfileChanged(script, this, 0.0f, transitionDuration); } // notify thunder and lightning if (managers.ThunderAndLightningManager != null) { managers.ThunderAndLightningManager.WeatherProfileChanged(script, this, precipitationChangeDelay, transitionDuration); } // notify player sound manager if (managers.PlayerSoundManager != null) { managers.PlayerSoundManager.WeatherProfileChanged(script, this, precipitationChangeDelay, transitionDuration); } }
/// <summary> /// Cloud manager weather profile change handler /// </summary> /// <param name="oldProfile">Old profile</param> /// <param name="newProfile">New profile</param> /// <param name="transitionDelay">Transition delay</param> /// <param name="transitionDuration">Transition duration</param> public void WeatherProfileChanged(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDelay, float transitionDuration) { CloudScript.ShowCloudsAnimated(newProfile.CloudProfile, transitionDelay, transitionDuration); }
/// <summary> /// Weather profile changed handler for wind /// </summary> /// <param name="oldProfile">Old profile</param> /// <param name="newProfile">New profile</param> /// <param name="transitionDelay">Transition delay</param> /// <param name="transitionDuration">Transition duration</param> public void WeatherProfileChanged(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDelay, float transitionDuration) { WindScript.SetWindProfileAnimated(newProfile.WindProfile, transitionDelay, transitionDuration); }
public void WeatherProfileChanged(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDelay, float transitionDuration) { FogScript.ShowFogAnimated(newProfile.FogProfile, transitionDelay, transitionDuration); }
private void NotifyThoseInZoneOfProfileChange(WeatherMakerProfileScript oldProfile, WeatherMakerProfileScript newProfile, float transitionDuration) { // anyone in this zone gets a new profile List <Transform> playersInZone; if (!zonesAndPlayers.TryGetValue(this, out playersInZone) || !PruneNulls(playersInZone)) { // no players in zone, we are done return; } List <string> connectionIds = new List <string>(); bool hasLocalPlayer = false; for (int i = 0; i < playersInZone.Count; i++) { Transform player = playersInZone[i]; hasLocalPlayer = WeatherMakerScript.IsLocalPlayer(player); connectionIds.Add(WeatherMakerScript.Instance.NetworkConnection.GetConnectionId(player)); } if (hasLocalPlayer) { WeatherMakerScript.Instance.LastLocalProfile = newProfile; } // send notification that those in this zone need a new weather profile WeatherMakerScript.Instance.RaiseWeatherProfileChanged(oldProfile, newProfile, secondsRemainingTransition, secondsRemainingHold, false, connectionIds.ToArray()); }
private void OnTriggerExit(Collider other) { if (SingleProfile == null && ProfileGroup == null) { return; } bool isServer = WeatherMakerScript.Instance != null && WeatherMakerScript.Instance.NetworkConnection.IsServer; if (isServer && gameObject.activeInHierarchy && enabled && WeatherMakerScript.IsPlayer(other.transform)) { List <WeatherMakerWeatherZoneScript> playerZones; if (!playersAndZones.TryGetValue(other.transform, out playerZones)) { playersAndZones[other.transform] = playerZones = new List <WeatherMakerWeatherZoneScript>(); } if (!playerZones.Contains(this)) { // not in this zone, exit out - sometimes OnTriggerExit is called twice in a row return; } List <Transform> zonePlayers; if (!zonesAndPlayers.TryGetValue(this, out zonePlayers)) { zonesAndPlayers[this] = zonePlayers = new List <Transform>(); } // if entering a new zone, begin transition to the new zone's current weather WeatherMakerProfileScript previousProfile = (playerZones.Count == 0 ? null : playerZones[playerZones.Count - 1].currentProfile); WeatherMakerProfileScript newProfile = null; // remove zone from the player zone stack playerZones.Remove(this); // remove player from the zone player list zonePlayers.Remove(other.transform); float transitionDuration = 0.0f; // add the player to the previous weather zone if any WeatherMakerWeatherZoneScript newZone = null; if (playerZones.Count != 0) { newZone = playerZones[playerZones.Count - 1]; if (!zonesAndPlayers.TryGetValue(newZone, out zonePlayers)) { zonePlayers = new List <Transform>(); } zonePlayers.Add(other.transform); // pick a new duration for the transition if (newZone.currentProfile != null) { transitionDuration = newZone.currentProfile.RandomTransitionDuration(); newProfile = newZone.currentProfile; } } else { Debug.LogError("Exited weather zone into no more zones, please add a global weather zone as a catch all zone"); return; } if (WeatherMakerScript.IsLocalPlayer(other.transform)) { WeatherMakerScript.Instance.LastLocalProfile = newProfile; WeatherMakerScript.Instance.WeatherZoneChanged.Invoke(newZone); } string connectionId = WeatherMakerScript.Instance.NetworkConnection.GetConnectionId(other.transform); // transition to new weather zone // if transition from another zone, multiply the transition duration so we get to the new weather zone weather more quickly WeatherMakerScript.Instance.RaiseWeatherProfileChanged(previousProfile, newProfile, transitionDuration * (previousProfile == null ? 1.0f : TransitionDurationMultiplier), secondsRemainingHold, false, (connectionId == null ? null : new string[1] { connectionId })); } }
private void OnTriggerEnter(Collider other) { if (SingleProfile == null && ProfileGroup == null) { return; } bool isServer = WeatherMakerScript.Instance != null && WeatherMakerScript.Instance.NetworkConnection.IsServer; if (isServer && gameObject.activeInHierarchy && enabled && WeatherMakerScript.IsPlayer(other.transform)) { // ensure we have player zones and zone players lists List <WeatherMakerWeatherZoneScript> playerZones; if (!playersAndZones.TryGetValue(other.transform, out playerZones)) { playersAndZones[other.transform] = playerZones = new List <WeatherMakerWeatherZoneScript>(); } if (playerZones.Contains(this)) { // already in the zone, don't re-process, sometimes OnTriggerEnter is called twice in a row return; } List <Transform> zonePlayers; if (!zonesAndPlayers.TryGetValue(this, out zonePlayers)) { zonesAndPlayers[this] = zonePlayers = new List <Transform>(); } // remove player from their previous zone WeatherMakerWeatherZoneScript prevZone = null; if (playerZones.Count != 0) { // remove player from previous weather zone prevZone = playerZones[playerZones.Count - 1]; List <Transform> prevZonePlayers; if (zonesAndPlayers.TryGetValue(prevZone, out prevZonePlayers)) { prevZonePlayers.Remove(other.transform); } } // see if we have a previous zone, if so we have a previous profile to transition from WeatherMakerProfileScript previousProfile = (playerZones.Count == 0 ? null : playerZones[playerZones.Count - 1].currentProfile); float transitionDuration = (previousProfile == null ? 0.001f : currentProfile.RandomTransitionDuration()); // add zone to the player zone stack playerZones.Add(this); // add player to the zone player list zonePlayers.Add(other.transform); if (WeatherMakerScript.IsLocalPlayer(other.transform)) { WeatherMakerScript.Instance.LastLocalProfile = currentProfile; if (prevZone != this) { WeatherMakerScript.Instance.WeatherZoneChanged.Invoke(this); } } // pick a new duration for the transition string connectionId = WeatherMakerScript.Instance.NetworkConnection.GetConnectionId(other.transform); // transition to new weather zone // if transition from another zone, multiply the transition duration so we get to the new weather zone weather more quickly WeatherMakerScript.Instance.RaiseWeatherProfileChanged(previousProfile, currentProfile, transitionDuration * (previousProfile == null ? 1.0f : TransitionDurationMultiplier), secondsRemainingHold, false, (connectionId == null ? null : new string[1] { connectionId })); } }