private void TransformParticleSystem(ParticleSystem particles, Transform anchorTransform, float forward, float height, float rotationYModifier)
        {
            if (particles == null || !IsFirstPerson || Intensity == 0.0f)
            {
                return;
            }
            Vector3 pos = anchorTransform.position;
            Vector3 anchorForward;
            bool    inNullZone = false;
            int     count      = Physics.OverlapSphereNonAlloc(anchorTransform.position, 0.001f, WeatherMakerScript.tempColliders);

            for (int i = 0; i < count; i++)
            {
                WeatherMakerNullZoneScript script = WeatherMakerScript.tempColliders[i].GetComponent <WeatherMakerNullZoneScript>();
                if (script != null && script.NullZoneActive && (script.CurrentMask & (int)NullZoneRenderMask.Precipitation) == 0)
                {
                    inNullZone = true;
                    break;
                }
            }

            // update particle system state for this transform
            ParticleSystemState state;
            Dictionary <ParticleSystem, ParticleSystemState> stateDict;

            if (!states.TryGetValue(anchorTransform, out stateDict))
            {
                states[anchorTransform] = stateDict = new Dictionary <ParticleSystem, ParticleSystemState>();
            }
            if (!stateDict.TryGetValue(particles, out state))
            {
                stateDict[particles] = state = new ParticleSystemState {
                    PreviousPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue)
                };
            }

            // if we were forced to world space from local space, go back to local space
            if (state.WasChangedFromLocalToWorldSpace)
            {
                state.WasChangedFromLocalToWorldSpace = false;
                var main = particles.main;
                main.simulationSpace = ParticleSystemSimulationSpace.Local;
            }

            if (particles.main.simulationSpace == ParticleSystemSimulationSpace.Local && !inNullZone)
            {
                if (WeatherMakerWindScript.Instance != null && WeatherMakerWindScript.Instance.CurrentWindVelocity != Vector3.zero)
                {
                    // as wind intensity increases, move forward and height of the system more inline with the player so it blows in their face
                    anchorForward = -(WeatherMakerWindScript.Instance.CurrentWindVelocity.normalized);
                    pos          += (anchorForward * Mathf.Lerp(forward, Mathf.Max(forward, 10.0f), WeatherMakerWindScript.Instance.WindZone.windMain * 4.0f));
                }
                else
                {
                    // can't move against the transform forward because it will look awful as player rotates
                    // just set on top of player directly
                    anchorForward = Vector3.zero;
                    pos.y        += height;
                }
            }
            else
            {
                if (inNullZone)
                {
                    // in null zone, put the precipitation right above the player at a distance
                    forward = 0.0f;
                    float standardHeight = (particles == ParticleSystem ? Height : (particles == MistParticleSystem ? MistHeight : SecondaryHeight));
                    height = Mathf.Max(NullZoneHeight, standardHeight);

                    var main = particles.main;
                    if (main.simulationSpace == ParticleSystemSimulationSpace.Local)
                    {
                        // mark this so we can switch back to local space when the null zone is exited
                        state.WasChangedFromLocalToWorldSpace = true;

                        // must use world space, looks funny swimming under water or moving in a building and moving with the player
                        main.simulationSpace = ParticleSystemSimulationSpace.World;
                    }
                }

                // position up and forward based on parameters
                anchorForward = anchorTransform.forward;
                pos.x        += anchorForward.x * forward;
                pos.y        += height;
                pos.z        += anchorForward.z * forward;
            }

            // if new state or a long distance, just snap the particle system into place
            if (Vector3.Distance(pos, state.PreviousPosition) > 100.0f)
            {
                particles.transform.position = state.PreviousPosition = pos;
            }
            else
            {
                // go to new position quickly but not instantly
                particles.transform.position = state.PreviousPosition = (FirstPersonFollowSpeed <= 0.0f ? pos : Vector3.Slerp(state.PreviousPosition, pos, Time.deltaTime * FirstPersonFollowSpeed));
            }
            if (particles.shape.mesh != null)
            {
                Vector3 angles = particles.transform.rotation.eulerAngles;
                particles.transform.rotation = Quaternion.Euler(angles.x, anchorTransform.rotation.eulerAngles.y * rotationYModifier, angles.z);
            }
        }
Пример #2
0
        private void CameraPreCull(Camera camera)
        {
            if (!Application.isPlaying || !ShouldProcessCamera(camera))
            {
                return;
            }

            bool intersectsCamera = false;
            bool hasWaterNullZone = false;

            if (WeatherMakerScript.IsLocalPlayer(camera.transform))
            {
                int hits = Physics.OverlapSphereNonAlloc(camera.transform.position, 0.001f, WeatherMakerScript.tempColliders);
                for (int i = 0; i < hits; i++)
                {
                    if (WeatherMakerScript.tempColliders[i] == waterCollider)
                    {
                        intersectsCamera = true;
                    }
                    else
                    {
                        WeatherMakerNullZoneScript script = WeatherMakerScript.tempColliders[i].GetComponent <WeatherMakerNullZoneScript>();
                        hasWaterNullZone |= (script != null && script.CurrentState != null && (script.CurrentState.RenderMask & NullZoneRenderMask.Water) != NullZoneRenderMask.Water);
                    }
                }
            }

            if (intersectsCamera && !hasWaterNullZone)
            {
                if (underwaterCameras.Add(camera))
                {
                    // transition to being underwater
                    //Debug.Log("Went underwater: " + camera.name);
                    PlayUnderwaterSound();
                    PlaySplashSound();
                    if (UnderwaterCallback != null)
                    {
                        UnderwaterCallback.Invoke(this, camera, true);
                    }

                    // TODO: Activate any post processing volume
                }

                // render surface after precipitation and other alpha effects if under water
                MeshRenderer.sharedMaterial.renderQueue = 3000;
                isUnderwater = true;

                // reduce sun light as camera goes further down in the water
                if (WeatherMakerLightManagerScript.Instance != null)
                {
                    float density = MeshRenderer.sharedMaterial.GetFloat(WMS._WaterFogDensity);
                    float depth   = Mathf.Max(0.0f, transform.position.y - camera.transform.position.y);
                    float atten   = (1.0f / (density * density * depth * depth));
                    atten = Mathf.Clamp(atten, 0.0f, 1.0f);
                    WeatherMakerLightManagerScript.Instance.DirectionalLightIntensityMultipliers["WeatherMakerWaterScript" + GetInstanceID()] = atten;
                }
            }
            else
            {
                if (underwaterCameras.Contains(camera))
                {
                    // transition away from being underwater
                    //Debug.Log("No longer underwater: " + camera.name);
                    underwaterCameras.Remove(camera);
                    if (UnderwaterAudioSource != null)
                    {
                        UnderwaterAudioSource.Stop();
                    }
                    PlaySplashSound();
                    if (UnderwaterCallback != null)
                    {
                        UnderwaterCallback.Invoke(this, camera, false);
                    }
                    if (WeatherMakerLightManagerScript.Instance != null)
                    {
                        WeatherMakerLightManagerScript.Instance.DirectionalLightIntensityMultipliers.Remove("WeatherMakerWaterScript" + GetInstanceID());
                    }

                    // TODO: Deactivate any post processing volume
                }

#if UNITY_LWRP
                // can't use alpha test trick, so just render just before transparent
                MeshRenderer.sharedMaterial.renderQueue = 2998;
#else
                // default render queue if above water
                MeshRenderer.sharedMaterial.renderQueue = -1;
#endif

                isUnderwater = false;
            }
        }