public static void Configure(this Transform transform, List <String> Data) { //return; String Classname = Data[Data.FindIndex(n => n == "classname") + 1], Targetname = Data[Data.FindIndex(n => n == "targetname") + 1]; transform.name = Classname; //ResourceManager.LoadModel("editor/axis_helper").SetParent(transform, false); Int32 OriginIndex = Data.FindIndex(n => n == "origin"); if (OriginIndex != -1) { //Old but gold String[] origin = Data[OriginIndex + 1].Split(' '); while (origin.Length != 3) { Int32 TempIndex = OriginIndex + 1; origin = Data[Data.FindIndex(TempIndex, n => n == "origin") + 1].Split(' '); } //Old but gold transform.position = new Vector3(-origin[1].ToSingle(), origin[2].ToSingle(), origin[0].ToSingle()) * uLoader.UnitScale; } Int32 AnglesIndex = Data.FindIndex(n => n == "angles"); if (AnglesIndex != -1) { Vector3 EulerAngles = Data[AnglesIndex + 1].ToVector3(); EulerAngles = new Vector3(EulerAngles.x, -EulerAngles.y, -EulerAngles.z); if (Classname.StartsWith("light", StringComparison.Ordinal)) { EulerAngles.x = -EulerAngles.x; } Int32 PitchIndex = Data.FindIndex(n => n == "pitch"); //Lights if (PitchIndex != -1) { EulerAngles.x = -Data[PitchIndex + 1].ToSingle(); } transform.eulerAngles = EulerAngles; } if (Classname.Contains("trigger")) { for (Int32 i = 0; i < transform.childCount; i++) { GameObject Child = transform.GetChild(i).gameObject; Child.SetActive(false); Child.AddComponent <BoxCollider>().isTrigger = true; } } #if UNITY_EDITOR if (Classname.Equals("env_sprite")) { //TODO: fix scale LensFlare lensFlare = transform.gameObject.AddComponent <LensFlare>(); if (VBSPFile.GlowFlare == null) { String path = UnityEditor.AssetDatabase.GUIDToAssetPath(UnityEditor.AssetDatabase.FindAssets("Glow t:Flare")[0]); VBSPFile.GlowFlare = UnityEditor.AssetDatabase.LoadAssetAtPath <Flare>(path); } lensFlare.flare = VBSPFile.GlowFlare; lensFlare.brightness = Data[Data.FindIndex(n => n == "scale") + 1].ToSingle(); lensFlare.fadeSpeed = Data[Data.FindIndex(n => n == "GlowProxySize") + 1].ToSingle(); lensFlare.color = Data[Data.FindIndex(n => n == "rendercolor") + 1].ToColor32(); return; } #endif /*if (Classname.Equals("point_viewcontrol")) * { * transform.gameObject.AddComponent<point_viewcontrol>().Start(); * }*/ //3D Skybox if (uLoader.Use3DSkybox && Classname.Equals("sky_camera")) { //Setup 3DSkybox Camera playerCamera = new GameObject("CameraPlayer").AddComponent <Camera>(); Camera skyCamera = transform.gameObject.AddComponent <Camera>(); CameraFly camFly = playerCamera.gameObject.AddComponent <CameraFly>(); camFly.skyScale = Data[Data.FindIndex(n => n == "scale") + 1].ToSingle(); camFly.offset3DSky = transform.position; camFly.skyCamera = skyCamera.transform; playerCamera.depth = -1; playerCamera.clearFlags = CameraClearFlags.Depth; skyCamera.depth = -2; skyCamera.clearFlags = CameraClearFlags.Skybox; //Setup 3DSkybox return; } //3D Skybox //Lights //shadow_control used to change parameters of dynamic shadows on the map: direction, color, length. if (Classname.Equals("shadow_control")) { //It can be integrated for Unity? //String[] color = Data[Data.FindIndex(n => n == "color") + 1].Split(' '); //RenderSettings.subtractiveShadowColor = new Color32(Byte.Parse(color[0]), Byte.Parse(color[1]), Byte.Parse(color[2]), 255); RenderSettings.ambientGroundColor = Data[Data.FindIndex(n => n == "color") + 1].ToColor(); //Set light direction by shadow_control if (VBSPFile.LightEnvironment != null) { if ((VBSPFile.LightEnvironment.rotation == Quaternion.identity) && !uLoader.IgnoreShadowControl) { VBSPFile.LightEnvironment.rotation = transform.rotation; } UpdateEquatorColor(); } return; } //Lights parsing if (!uLoader.UseWorldLights && Classname.Contains("light") && !Classname.StartsWith("point")) { Color ambientLight; if (Classname.Equals("light_environment")) { if (VBSPFile.LightEnvironment != null) { return; } VBSPFile.LightEnvironment = transform; //TODO: Correct parse ambient color String _ambient = Data[Data.FindIndex(n => n == "_ambient") + 1]; ambientLight = _ambient.ToColor(); RenderSettings.ambientLight = ambientLight; //Set light direction by shadow_control if (VBSPFile.ShadowControl != null) { if (!uLoader.IgnoreShadowControl && transform.rotation == Quaternion.identity) { transform.rotation = VBSPFile.ShadowControl.rotation; } UpdateEquatorColor(); } } if (uLoader.ParseLights) { Light Light = transform.gameObject.AddComponent <Light>(); if (Classname.Equals("light_spot")) { Light.type = LightType.Spot; } else if (Classname.Equals("light_environment")) { Light.type = LightType.Directional; } Vector4 _lightColor = Data[Data.FindIndex(n => n == "_light") + 1].ToColorVec(); Single intensity = _lightColor.w; Single m_Attenuation0 = 0; Single m_Attenuation1 = 0; Single m_Attenuation2 = 0; Light.color = new Color(_lightColor.x / 255, _lightColor.y / 255, _lightColor.z / 255, 255); Single LightRadius = 256; if (Light.type == LightType.Spot || Light.type == LightType.Point) { if (Light.type == LightType.Spot) { //Single inner_cone = Converters.ToSingle(Data[Data.FindIndex(n => n == "_cone2") + 1]); Single cone = Data[Data.FindIndex(n => n == "_cone") + 1].ToSingle() * 2; //radius -= inner_cone / cone; Light.spotAngle = Mathf.Clamp(cone, 0, 179); } Single _distance = Data[Data.FindIndex(n => n == "_distance") + 1].ToInt32(); if (_distance != 0) { LightRadius = _distance; intensity *= 1.5f; } else { Single _fifty_percent_distance = Data[Data.FindIndex(n => n == "_fifty_percent_distance") + 1].ToSingle(); Boolean isFifty = _fifty_percent_distance != 0; if (isFifty) { //New light style Single _zero_percent_distance = Data[Data.FindIndex(n => n == "_zero_percent_distance") + 1].ToSingle(); if (_zero_percent_distance < _fifty_percent_distance) { // !!warning in lib code???!!! Debug.LogWarningFormat("light has _fifty_percent_distance of {0} but no zero_percent_distance", _fifty_percent_distance); _zero_percent_distance = 2.0f * _fifty_percent_distance; } Single a = 0, b = 1, c = 0; if (!MathLibrary.SolveInverseQuadraticMonotonic(0, 1.0f, _fifty_percent_distance, 2.0f, _zero_percent_distance, 256.0f, ref a, ref b, ref c)) { Debug.LogWarningFormat("can't solve quadratic for light {0} {1}", _fifty_percent_distance, _zero_percent_distance); } Single v50 = c + _fifty_percent_distance * (b + _fifty_percent_distance * a); Single scale = 2.0f / v50; a *= scale; b *= scale; c *= scale; m_Attenuation2 = a; m_Attenuation1 = b; m_Attenuation0 = c; } else { //Old light style Single constant_attn = Data[Data.FindIndex(n => n == "_constant_attn") + 1].ToSingle(); Single linear_attn = Data[Data.FindIndex(n => n == "_linear_attn") + 1].ToSingle(); Single quadratic_attn = Data[Data.FindIndex(n => n == "_quadratic_attn") + 1].ToSingle(); // old-style manually typed quadrtiac coefficients if (quadratic_attn < 0.001) { quadratic_attn = 0; } if (linear_attn < 0.001) { linear_attn = 0; } if (constant_attn < 0.001) { constant_attn = 0; } if ((constant_attn < 0.001) && (linear_attn < 0.001) && (quadratic_attn < 0.001)) { constant_attn = 1; } m_Attenuation2 = quadratic_attn; m_Attenuation1 = linear_attn; m_Attenuation0 = constant_attn; } // FALLBACK: older lights use this if (m_Attenuation2 == 0.0f) { if (m_Attenuation1 == 0.0f) { // Infinite, but we're not going to draw it as such LightRadius = 2000; } else { LightRadius = (intensity / 0.03f - m_Attenuation0) / m_Attenuation1; } } else { Single a = m_Attenuation2; Single b = m_Attenuation1; Single c = m_Attenuation0 - intensity / 0.03f; Single discrim = b * b - 4 * a * c; if (discrim < 0.0f) { // Infinite, but we're not going to draw it as such LightRadius = 2000; } else { LightRadius = (-b + Mathf.Sqrt(discrim)) / (2.0f * a); if (LightRadius < 0) { LightRadius = 0; } //DeadZoneLuna //TODO: Find the best way to fix that //DeadZoneLuna if (isFifty) { //TODO: WHY? LightRadius /= 10; } else { //TODO: Not enough intensity? LightRadius *= 10; } } } } Light.range = (LightRadius * uLoader.UnitScale); } Light.intensity = (intensity / 255f) * 1.75f; #if UNITY_EDITOR Light.lightmapBakeType = LightmapBakeType.Baked; #endif if (uLoader.UseDynamicLight) { Light.shadows = LightShadows.Soft; if (Light.type == LightType.Directional) { Light.shadowBias = 0.1f; Light.shadowNormalBias = 0; } else { Light.shadowBias = 0.01f; } } } return; } //Lights #region Counter-Strike entities test /*if (Classname.Equals("info_player_terrorist")) * { * //Placeholder model (can be removed if needed) * ResourceManager.LoadModel("player/t_phoenix").SetParent(transform, false); * } * * //Counter-Strike CT spawn point * if (Classname.Equals("info_player_counterterrorist")) * { * //Placeholder model (can be removed if needed) * ResourceManager.LoadModel("player/ct_urban").SetParent(transform, false); * } * * //Default spawn point * if (Classname.Equals("info_player_start")) * { * //Placeholder model (can be removed if needed) * ResourceManager.LoadModel("editor/playerstart").SetParent(transform, false); * } * * //weapon spawn point * if (Classname.Contains("weapon_")) * { * //Placeholder model (can be removed if needed) * ResourceManager.LoadModel("weapons/w_rif_ak47").SetParent(transform, false); * } * * //hostage spawn point * if (Classname.Equals("hostage_entity")) * { * String[] hostages = * { * "characters/hostage_01", * "characters/hostage_02", * "characters/hostage_03", * "characters/hostage_04" * }; * * ResourceManager.LoadModel(hostages[UnityEngine.Random.Range(0, hostages.Length)]).SetParent(transform, false); * }*/ #endregion Int32 RenderModeIndex = Data.FindIndex(n => n == "rendermode"); if (RenderModeIndex != -1) { if (Data[RenderModeIndex + 1] == "10") { for (Int32 i = 0; i < transform.childCount; i++) { GameObject Child = transform.GetChild(i).gameObject; Child.GetComponent <Renderer>().enabled = false; } } } if (Classname.Contains("prop_") || Classname.Contains("npc_"))// || Classname.Equals("asw_door")) { string ModelName = Data[Data.FindIndex(n => n == "model") + 1]; if (!string.IsNullOrEmpty(ModelName)) { uResourceManager.LoadModel(ModelName, uLoader.LoadAnims, uLoader.UseHitboxesOnModel).SetParent(transform, false); return; } return; } if (uLoader.ParseDecals && Classname.Equals("infodecal")) { String DecalName = Data[Data.FindIndex(n => n == "texture") + 1]; VMTFile DecalMaterial = uResourceManager.LoadMaterial(DecalName); Single DecalScale = DecalMaterial.GetSingle("$decalscale"); if (DecalScale <= 0) { DecalScale = 1f; } Int32 DecalWidth = DecalMaterial.Material.mainTexture.width; //X Int32 DecalHeight = DecalMaterial.Material.mainTexture.height; //Y Sprite DecalTexture = Sprite.Create((Texture2D)DecalMaterial.Material.mainTexture, new Rect(0, 0, DecalWidth, DecalHeight), Vector2.zero); Decal DecalBuilder = transform.gameObject.AddComponent <Decal>(); #if UNITY_EDITOR if (uLoader.DebugMaterials) { transform.gameObject.AddComponent <DebugMaterial>().Init(DecalMaterial); } #endif DecalBuilder.SetDirection(); DecalBuilder.MaxAngle = 87.5f; DecalBuilder.Offset = 0.001f; DecalBuilder.Sprite = DecalTexture; DecalBuilder.Material = DecalMaterial.Material; DecalBuilder.Material.SetTextureScale("_MainTex", new Vector2(-1, 1)); Single ScaleX = (DecalWidth * DecalScale) * uLoader.UnitScale; Single ScaleY = (DecalHeight * DecalScale) * uLoader.UnitScale; Single DepthSize = ScaleX; if (ScaleY < DepthSize) { DepthSize = ScaleY; } transform.localScale = new Vector3(ScaleX, ScaleY, DepthSize); transform.position += new Vector3(0, 0, 0.001f); #if !UNITY_EDITOR DecalBuilder.BuildAndSetDirty(); #endif } }
public void Configure(List <String> Data) { this.Data = Data; String Classname = Data[Data.FindIndex(n => n == "classname") + 1], Targetname = Data[Data.FindIndex(n => n == "targetname") + 1]; name = Classname; //StudioMDLLoader.Load("editor/axis_helper").SetParent(transform, false); if (Data.Contains("origin")) { String[] Array = Data[Data.FindIndex(n => n == "origin") + 1].Split(' '); while (Array.Length != 3) { Int32 TempIndex = Data.FindIndex(n => n == "origin") + 1; Array = Data[Data.FindIndex(TempIndex, n => n == "origin") + 1].Split(' '); } transform.position = new Vector3(-Single.Parse(Array[0]), Single.Parse(Array[2]), -Single.Parse(Array[1])) * ConfigLoader.WorldScale; } if (Data.Contains("angles")) { String[] Array = Data[Data.FindIndex(n => n == "angles") + 1].Split(' '); if (!Classname.Contains("prop_")) { EulerAngles = new Vector3(Single.Parse(Array[0]), -Single.Parse(Array[1]), -Single.Parse(Array[2])); EulerAngles.y -= 90; } else { EulerAngles = new Vector3(-Single.Parse(Array[2]), Single.Parse(Array[1]), Single.Parse(Array[0])); } //float y = EulerAngles.y; /*if (Mathf.Approximately(y, 90) || Mathf.Approximately(y, 270)) * EulerAngles.y += 90; * * if (Mathf.Approximately(y, 0) || Mathf.Approximately(y, 180)) * EulerAngles.y -= 90;*/ if (Data.Contains("pitch")) { EulerAngles.x = -Single.Parse(Data[Data.FindIndex(n => n == "pitch") + 1]); } transform.eulerAngles = EulerAngles; } if (Classname.Contains("trigger")) { for (Int32 i = 0; i < transform.childCount; i++) { GameObject Child = transform.GetChild(i).gameObject; Child.SetActive(false); Child.AddComponent <BoxCollider>().isTrigger = true; } } //if (Classname.Equals("point_viewcontrol")) // gameObject.AddComponent<point_viewcontrol>(); //3D Skybox if (Classname.Equals("sky_camera")) { //Setup 3DSkybox Camera playerCamera = new GameObject("CameraPlayer").AddComponent <Camera>(); CameraFly camFly = playerCamera.gameObject.AddComponent <CameraFly>(); camFly.skyScale = float.Parse(Data[Data.FindIndex(n => n == "scale") + 1]); camFly.offset3DSky = transform.position; if (ConfigLoader.use3DSkybox) { Camera skyCamera = gameObject.AddComponent <Camera>(); skyCamera.depth = 0f; skyCamera.farClipPlane = 70f; playerCamera.depth = 1f; playerCamera.clearFlags = CameraClearFlags.Depth; camFly.skyCamera = skyCamera.transform; } //Setup 3DSkybox } //3D Skybox //Simple light /*if(Classname.Equals("shadow_control")) * { * String[] color = Data[Data.FindIndex(n => n == "color") + 1].Split(' '); * RenderSettings.subtractiveShadowColor = new Color32(Byte.Parse(color[0]), Byte.Parse(color[1]), Byte.Parse(color[2]), 255); * }*/ if (Classname.Contains("light_") || Classname.Equals("light")) { if (Classname.Equals("light_environment")) { if (RenderSettings.sun != null) { return; } String[] _ambient = Data[Data.FindIndex(n => n == "_ambient") + 1].Split(' '); RenderSettings.ambientLight = new Color32(Byte.Parse(_ambient[0]), Byte.Parse(_ambient[1]), Byte.Parse(_ambient[2]), 255); } Light light = gameObject.AddComponent <Light>(); if (Classname.Equals("light_spot")) { light.type = LightType.Spot; } else if (Classname.Equals("light_environment")) { RenderSettings.sun = light; light.type = LightType.Directional; } String[] _light = Data[Data.FindIndex(n => n == "_light") + 1].Split(' '); light.color = new Color32(Byte.Parse(_light[0]), Byte.Parse(_light[1]), Byte.Parse(_light[2]), 255); if (light.type == LightType.Point || light.type == LightType.Spot) { String[] _distance = Data[Data.FindIndex(n => n == "_distance") + 1].Split(' '); Int32 _distance_value = 0; if (Int32.TryParse(_distance[0], out _distance_value)) { light.range = _distance_value > 0 ? _distance_value * ConfigLoader.WorldScale : 10; } else { light.range = 10; } if (light.type == LightType.Spot) { String[] _inner_cone = Data[Data.FindIndex(n => n == "_inner_cone") + 1].Split(' '); String[] _cone = Data[Data.FindIndex(n => n == "_cone") + 1].Split(' '); light.spotAngle = Int32.Parse(_inner_cone[0]) + Int32.Parse(_cone[0]); } } light.lightmapBakeType = ConfigLoader.DynamicLight ? LightmapBakeType.Mixed : LightmapBakeType.Baked; if (ConfigLoader.DynamicLight) { light.shadows = LightShadows.Soft; if (light.type == LightType.Directional) { light.shadowBias = 0.1f; light.shadowNormalBias = 0; } else { light.shadowBias = 0.01f; } } } //Simple light if (Classname.Equals("info_player_terrorist")) { StudioMDLLoader.Load("player/t_phoenix").SetParent(transform, false); } if (Classname.Equals("info_player_counterterrorist")) { StudioMDLLoader.Load("player/ct_urban").SetParent(transform, false); } if (Classname.Equals("info_player_start")) { StudioMDLLoader.Load("editor/playerstart").SetParent(transform, false); } if (Classname.Contains("weapon_")) { StudioMDLLoader.Load("weapons/w_rif_ak47").SetParent(transform, false); } if (Classname.Equals("hostage_entity"))//hostage_entity { String[] hostages = new[] { "characters/hostage_01", "characters/hostage_02", "characters/hostage_03", "characters/hostage_04" }; StudioMDLLoader.Load(hostages[UnityEngine.Random.Range(0, hostages.Length)]).SetParent(transform, false); } if (Data.Contains("rendermode")) { if (Data[Data.FindIndex(n => n == "rendermode") + 1] == "10") { for (Int32 i = 0; i < transform.childCount; i++) { GameObject Child = transform.GetChild(i).gameObject; Child.GetComponent <Renderer>().enabled = false; } } } if (Classname.Contains("prop_") || Classname.Contains("npc_")) { string ModelName = Data[Data.FindIndex(n => n == "model") + 1]; StudioMDLLoader.Load(ModelName).SetParent(transform, false); } if (Classname.Equals("infodecal")) { //This is just an example, you need to implement a complete decal system. if (ConfigLoader.LoadInfoDecals) { String TextureName = Data[Data.FindIndex(n => n == "texture") + 1]; Material DecalMat = MaterialLoader.Load(TextureName); int x = DecalMat.mainTexture.width; int y = DecalMat.mainTexture.height; float decalScale = 1; String Value = MaterialLoader.GetParametr("$decalscale"); if (!String.IsNullOrEmpty(Value)) { decalScale *= float.Parse(Value); } SpriteRenderer DecalRender = gameObject.AddComponent <SpriteRenderer>(); DecalRender.sprite = Sprite.Create((Texture2D)DecalMat.mainTexture, new Rect(0, 0, x, y), new Vector2(0.5f, 0.5f), 1); DecalRender.flipX = true; DecalRender.flipY = true; transform.localScale = new Vector3(decalScale * ConfigLoader.WorldScale, decalScale * ConfigLoader.WorldScale, 1); } } }
private void OnKeyDown(object sender, KeyboardKeyEventArgs e) { if (e.Key == KeyboardKey.U) { _sceneState.SunPosition = _sceneState.Camera.Eye; } else if (e.Key == KeyboardKey.W) { _clipmap.Wireframe = !_clipmap.Wireframe; UpdateHUD(); } else if (e.Key == KeyboardKey.B) { if (!_clipmap.BlendRegionsEnabled) { _clipmap.BlendRegionsEnabled = true; _clipmap.ShowBlendRegions = false; } else if (_clipmap.ShowBlendRegions) { _clipmap.BlendRegionsEnabled = false; } else { _clipmap.ShowBlendRegions = true; } UpdateHUD(); } else if (e.Key == KeyboardKey.L) { _clipmap.LodUpdateEnabled = !_clipmap.LodUpdateEnabled; UpdateHUD(); } else if (e.Key == KeyboardKey.C) { _clipmap.ColorClipmapLevels = !_clipmap.ColorClipmapLevels; if (_clipmap.ColorClipmapLevels) { _clipmap.ShowImagery = false; _clipmap.Lighting = true; } UpdateHUD(); } else if (e.Key == KeyboardKey.I) { _clipmap.ShowImagery = !_clipmap.ShowImagery; _clipmap.Lighting = !_clipmap.ShowImagery; if (_clipmap.ShowImagery) { _clipmap.ColorClipmapLevels = false; } UpdateHUD(); } else if (e.Key == KeyboardKey.S) { _clipmap.Lighting = !_clipmap.Lighting; UpdateHUD(); } else if (e.Key == KeyboardKey.Z) { if (_lookCamera != null) { double longitude = -119.5326056; double latitude = 37.74451389; Geodetic3D halfDome = new Geodetic3D(Trig.ToRadians(longitude), Trig.ToRadians(latitude), 2700.0); _lookCamera.ViewPoint(_ellipsoid, halfDome); _lookCamera.Azimuth = 0.0; _lookCamera.Elevation = Trig.ToRadians(30.0); _lookCamera.Range = 10000.0; } } else if (e.Key == KeyboardKey.F) { if (_lookCamera != null) { _lookCamera.Dispose(); _lookCamera = null; _flyCamera = new CameraFly(_sceneState.Camera, _window); _flyCamera.MovementRate = 1200.0; } else if (_flyCamera != null) { _flyCamera.Dispose(); _flyCamera = null; _sceneState.Camera.Target = new Vector3D(0.0, 0.0, 0.0); _lookCamera = new CameraLookAtPoint(_sceneState.Camera, _window, _ellipsoid); _lookCamera.UpdateParametersFromCamera(); } UpdateHUD(); } else if (_flyCamera != null && (e.Key == KeyboardKey.Plus || e.Key == KeyboardKey.KeypadPlus)) { _flyCamera.MovementRate *= 2.0; UpdateHUD(); } else if (_flyCamera != null && (e.Key == KeyboardKey.Minus || e.Key == KeyboardKey.KeypadMinus)) { _flyCamera.MovementRate *= 0.5; UpdateHUD(); } else if (e.Key == KeyboardKey.E) { if (_clipmap.Ellipsoid.MaximumRadius == _clipmap.Ellipsoid.MinimumRadius) { _clipmap.Ellipsoid = Ellipsoid.Wgs84; _globe.Shape = Ellipsoid.Wgs84; } else { double radius = Ellipsoid.Wgs84.MaximumRadius; _clipmap.Ellipsoid = new Ellipsoid(radius, radius, radius); _globe.Shape = _clipmap.Ellipsoid; } } }
public void Update( CameraFly _Caller, float _DeltaTime, bool _bEnable, float _Importance, float _CloudAltitudeKm, float _CloudThicknessKm ) { m_Bolt.enabled = _bEnable; if ( !_bEnable ) return; // Update current strike if any m_Bolt.UpdateStrike(); m_TimeBeforeNextStrike -= _DeltaTime; if ( m_TimeBeforeNextStrike < 0.0f ) { // Now striking... // Draw a random duration and time before another strike... float StrikeDuration = Random.Range( DURATION_MIN, DURATION_MAX ); m_TimeBeforeNextStrike = Random.Range( Mathf.Lerp( DELAY_BETWEEN_STRIKES_MAX, DELAY_BETWEEN_STRIKES_MIN, _Importance ), DELAY_BETWEEN_STRIKES_MAX ); m_TimeBeforeNextStrike += StrikeDuration; // Draw a random variation speed float VariationSpeed = Random.Range( VARIATION_SPEED_MIN, VARIATION_SPEED_MAX ); // Draw a new random position somewhere about in front of the camera Matrix4x4 Camera2World = _Caller.Manager.Camera.camera.cameraToWorldMatrix; Vector3 Right = Camera2World.GetColumn( 0 ); Vector3 At = -Camera2World.GetColumn( 2 ); Vector3 Pos = Camera2World.GetColumn( 3 ); float StrikeAngle = 0.5f * Mathf.PI + 0.5f * Mathf.Deg2Rad * ANGULAR_SLICE * (2.0f * Random.value - 1.0f); float StrikeDistance = Random.Range( STRIKE_RANGE_MIN, STRIKE_RANGE_MAX ); Vector2 StrikeOffsetXZ = StrikeDistance * new Vector2( Mathf.Cos( StrikeAngle ), Mathf.Sin( StrikeAngle ) ); Vector3 StrikePosition = Pos + StrikeOffsetXZ.x * Right + StrikeOffsetXZ.y * At; // Set bolt's altitude in the middle of the cloud layer Vector3 BoltPosition = m_Bolt.transform.position; float BoltAltitude = (_CloudAltitudeKm + 0.5f * _CloudThicknessKm) / _Caller.Manager.WorldUnit2Kilometer; BoltPosition.y = BoltAltitude; m_Bolt.transform.position = BoltPosition; // Start in the clouds m_Bolt.P0 = new Vector3( StrikePosition.x, 0.0f, StrikePosition.z ); // End in the ground m_Bolt.P1 = new Vector3( StrikePosition.x, -BoltAltitude, StrikePosition.z ); // Strike !!! m_Bolt.StartStrike( STRIKE_INTENSITY, StrikeDuration, VariationSpeed ); } }