using System.Collections.Generic; using UnityEngine; using System.Linq; [ExecuteInEditMode] public class PSMeshRendererUpdater : MonoBehaviour { public GameObject MeshObject; public float StartScaleMultiplier = 1; public Color Color = Color.black; const string materialName = "MeshEffect"; List rendererMaterials = new List(); List skinnedMaterials = new List(); public bool IsActive = true; public float FadeTime = 1.5f; bool currentActiveStatus; private bool needUpdateAlpha; Color oldColor = Color.black; private float currentAlphaTime; string[] colorProperties = { "_TintColor", "_Color", "_EmissionColor", "_BorderColor", "_ReflectColor", "_RimColor", "_MainColor", "_CoreColor", "_FresnelColor" }; void OnEnable() { alpha = 0; prevAlpha = 0; IsActive = true; } float alpha; float prevAlpha; Dictionary startAlphaColors; private bool previousActiveStatus; bool needUpdate; bool needLastUpdate; Dictionary startParticleParameters; void Update() { if (!Application.isPlaying) return; if (startAlphaColors == null) { InitStartAlphaColors(); } if (IsActive && alpha < 1) alpha += Time.deltaTime / FadeTime; if (!IsActive && alpha > 0) alpha -= Time.deltaTime / FadeTime; if (alpha > 0 && alpha < 1) { needUpdate = true; } else { needUpdate = false; alpha = Mathf.Clamp01(alpha); if (Mathf.Abs(prevAlpha - alpha) >= Mathf.Epsilon) UpdateVisibleStatus(); } prevAlpha = alpha; if (needUpdate) UpdateVisibleStatus(); if (Color != oldColor) { oldColor = Color; UpdateColor(Color); } } void InitStartAlphaColors() { startAlphaColors = new Dictionary(); var renderers = GetComponentsInChildren(true); foreach (var rend in renderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if(mats[i].name.Contains(materialName)) GetStartAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i]); } } var skinRenderers = GetComponentsInChildren(true); foreach (var rend in skinRenderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) GetStartAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i]); } } var lights = GetComponentsInChildren(true); for (int i = 0; i < lights.Length; i++) { var lightCurve = lights[i].GetComponent(); float intencity = 1; if (lightCurve != null) intencity = lightCurve.GraphIntensityMultiplier; startAlphaColors.Add(lights[i].GetHashCode().ToString() + i, intencity); } if (MeshObject) { renderers = MeshObject.GetComponentsInChildren(true); foreach (var rend in renderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) GetStartAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i]); } } } if (MeshObject) { skinRenderers = MeshObject.GetComponentsInChildren(true); foreach (var rend in skinRenderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) GetStartAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i]); } } } } void InitStartParticleParameters() { startParticleParameters = new Dictionary(); var particles = MeshObject.GetComponentsInChildren(true); foreach (var ps in particles) { startParticleParameters.Add(ps, new ParticleStartInfo {StartSize = ps.main.startSize, StartSpeed = ps.main.startSpeed}); } } void UpdateVisibleStatus() { var renderers = GetComponentsInChildren(true); foreach (var rend in renderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) UpdateAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i], alpha); } } var skinRenderers = GetComponentsInChildren(true); foreach (var rend in skinRenderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) UpdateAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i], alpha); } } renderers = MeshObject.GetComponentsInChildren(true); foreach (var rend in renderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) UpdateAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i], alpha); } } skinRenderers = MeshObject.GetComponentsInChildren(true); foreach (var rend in skinRenderers) { var mats = rend.materials; for (int i = 0; i < mats.Length; i++) { if (mats[i].name.Contains(materialName)) UpdateAlphaByProperties(rend.GetHashCode().ToString(), i, mats[i], alpha); } } var lightCurves = GetComponentsInChildren(true); foreach (var lightCurve in lightCurves) { lightCurve.enabled = IsActive; } var lights = GetComponentsInChildren(true); for (int i = 0; i < lights.Length; i++) { if (!IsActive) { var startAlpha = startAlphaColors[lights[i].GetHashCode().ToString() + i]; lights[i].intensity = alpha * startAlpha; } } var particleSystems = GetComponentsInChildren(true); foreach (var ps in particleSystems) { if (!IsActive && !ps.isStopped) ps.Stop(); if (IsActive && ps.isStopped) ps.Play(); } var currentTrails = GetComponentsInChildren(); foreach (var trail in currentTrails) { trail.IsActive = IsActive; } } void UpdateAlphaByProperties(string rendName, int materialNumber, Material mat, float alpha) { foreach (var prop in colorProperties) { if (mat.HasProperty(prop)) { var startAlpha = startAlphaColors[rendName + materialNumber + prop.ToString()]; var color = mat.GetColor(prop); color.a = alpha * startAlpha; mat.SetColor(prop, color); } } } void GetStartAlphaByProperties(string rendName, int materialNumber, Material mat) { foreach (var prop in colorProperties) { if (mat.HasProperty(prop)) { var key = rendName + materialNumber + prop.ToString(); if (!startAlphaColors.ContainsKey(key)) startAlphaColors.Add(rendName + materialNumber + prop.ToString(), mat.GetColor(prop).a); } } } public void UpdateColor(Color color) { if (MeshObject == null) return; var hsv = ME_ColorHelper.ColorToHSV(color); ME_ColorHelper.ChangeObjectColorByHUE(MeshObject, hsv.H); } public void UpdateColor(float HUE) { if (MeshObject == null) return; ME_ColorHelper.ChangeObjectColorByHUE(MeshObject, HUE); } public void UpdateMeshEffect() { transform.localPosition = Vector3.zero; transform.localRotation = new Quaternion(); rendererMaterials.Clear(); skinnedMaterials.Clear(); if (MeshObject == null) return; UpdatePSMesh(MeshObject); AddMaterialToMesh(MeshObject); } void CheckScaleIncludedParticles() { } public void UpdateMeshEffect(GameObject go) { rendererMaterials.Clear(); skinnedMaterials.Clear(); if (go == null) { Debug.Log("You need set a gameObject"); return; } MeshObject = go; UpdatePSMesh(MeshObject); AddMaterialToMesh(MeshObject); } private void UpdatePSMesh(GameObject go) { if (startParticleParameters == null) InitStartParticleParameters(); var ps = GetComponentsInChildren(); var meshRend = go.GetComponentInChildren(); var skinMeshRend = go.GetComponentInChildren(); var lights = GetComponentsInChildren(); float realBound = 1; float transformMax = 1; if (meshRend != null) { realBound = meshRend.bounds.size.magnitude; transformMax = meshRend.transform.lossyScale.magnitude; } if (skinMeshRend != null) { realBound = skinMeshRend.bounds.size.magnitude; transformMax = skinMeshRend.transform.lossyScale.magnitude; } foreach (var particleSys in ps) { particleSys.transform.gameObject.SetActive(false); var sh = particleSys.shape; if (sh.enabled) { if (meshRend != null) { sh.shapeType = ParticleSystemShapeType.MeshRenderer; sh.meshRenderer = meshRend; } if (skinMeshRend != null) { sh.shapeType = ParticleSystemShapeType.SkinnedMeshRenderer; sh.skinnedMeshRenderer = skinMeshRend; } } var mainPS = particleSys.main; if (startParticleParameters.ContainsKey(particleSys)) { var startParticleInfo = startParticleParameters[particleSys]; mainPS.startSize = UpdateParticleParam(startParticleInfo.StartSize, mainPS.startSize, (realBound / transformMax) * StartScaleMultiplier); mainPS.startSpeed = UpdateParticleParam(startParticleInfo.StartSpeed, mainPS.startSpeed, (realBound / transformMax) * StartScaleMultiplier); } //var startSize = mainPS.startSize; //if (startSize.mode == ParticleSystemCurveMode.TwoConstants) //{ // startSize.constantMin *= realBound / transformMax; // startSize.constantMax *= realBound / transformMax; //} //if (startSize.mode == ParticleSystemCurveMode.Constant) // startSize.constant *= realBound / transformMax; //else mainPS.startSizeMultiplier *= realBound / transformMax; //mainPS.startSize = startSize; particleSys.transform.gameObject.SetActive(true); } if (meshRend != null) foreach (var light1 in lights) light1.transform.position = meshRend.bounds.center; if (skinMeshRend != null) foreach (var light1 in lights) light1.transform.position = skinMeshRend.bounds.center; } class ParticleStartInfo { public ParticleSystem.MinMaxCurve StartSize; public ParticleSystem.MinMaxCurve StartSpeed; } ParticleSystem.MinMaxCurve UpdateParticleParam(ParticleSystem.MinMaxCurve startParam, ParticleSystem.MinMaxCurve currentParam, float scale) { if (currentParam.mode == ParticleSystemCurveMode.TwoConstants) { currentParam.constantMin = startParam.constantMin * scale; currentParam.constantMax = startParam.constantMax * scale; } else if (currentParam.mode == ParticleSystemCurveMode.Constant) currentParam.constant = startParam.constant * scale; return currentParam; } private void AddMaterialToMesh(GameObject go) { var meshMatEffect = GetComponentInChildren(); if (meshMatEffect == null) return; var meshRenderer = go.GetComponentInChildren(); var skinMeshRenderer = go.GetComponentInChildren(); // foreach (var meshRenderer in meshRenderers) if (meshRenderer != null) { rendererMaterials.Add(meshRenderer.sharedMaterials); meshRenderer.sharedMaterials = AddToSharedMaterial(meshRenderer.sharedMaterials, meshMatEffect); } // foreach (var skinMeshRenderer in skinMeshRenderers) if(skinMeshRenderer!=null) { skinnedMaterials.Add(skinMeshRenderer.sharedMaterials); skinMeshRenderer.sharedMaterials = AddToSharedMaterial(skinMeshRenderer.sharedMaterials, meshMatEffect); } } Material[] AddToSharedMaterial(Material[] sharedMaterials, ME_MeshMaterialEffect meshMatEffect) { if (meshMatEffect.IsFirstMaterial) return new[] { meshMatEffect.Material }; var materials = sharedMaterials.ToList(); for (int i = 0; i < materials.Count; i++) { if (materials[i].name.Contains(materialName)) materials.RemoveAt(i); } //meshMatEffect.Material.name = meshMatEffect.Material.name + materialName; materials.Add(meshMatEffect.Material); return materials.ToArray(); } void OnDestroy() { //Activation(true); if (MeshObject == null) return; var meshRenderers = MeshObject.GetComponentsInChildren(); var skinMeshRenderers = MeshObject.GetComponentsInChildren(); for (int i = 0; i < meshRenderers.Length; i++) { if (rendererMaterials.Count == meshRenderers.Length) meshRenderers[i].sharedMaterials = rendererMaterials[i]; var materials = meshRenderers[i].sharedMaterials.ToList(); for (int j = 0; j < materials.Count; j++) { if (materials[j].name.Contains(materialName)) materials.RemoveAt(j); } meshRenderers[i].sharedMaterials = materials.ToArray(); } for (int i = 0; i < skinMeshRenderers.Length; i++) { if (skinnedMaterials.Count == skinMeshRenderers.Length) skinMeshRenderers[i].sharedMaterials = skinnedMaterials[i]; var materials = skinMeshRenderers[i].sharedMaterials.ToList(); for (int j = 0; j < materials.Count; j++) { if (materials[j].name.Contains(materialName)) materials.RemoveAt(j); } skinMeshRenderers[i].sharedMaterials = materials.ToArray(); } rendererMaterials.Clear(); skinnedMaterials.Clear(); } }