From df84ee7e568fa500fec7b1865b966345b814e68f Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 21 Oct 2020 22:51:18 +0800 Subject: =?UTF-8?q?+=20=E6=AE=8B=E5=BD=B1=E7=89=B9=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Effects/AfterImageEffects.cs | 186 +++++++++++++++++++++ Assets/Scripts/Effects/AfterImageEffects.cs.meta | 11 ++ Assets/Scripts/Effects/IEffectHandler.cs | 18 ++ Assets/Scripts/Effects/IEffectHandler.cs.meta | 11 ++ Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs | 124 ++++++++++++++ .../Effects/ShurikenBakedMeshEmitter.cs.meta | 11 ++ 6 files changed, 361 insertions(+) create mode 100644 Assets/Scripts/Effects/AfterImageEffects.cs create mode 100644 Assets/Scripts/Effects/AfterImageEffects.cs.meta create mode 100644 Assets/Scripts/Effects/IEffectHandler.cs create mode 100644 Assets/Scripts/Effects/IEffectHandler.cs.meta create mode 100644 Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs create mode 100644 Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs.meta (limited to 'Assets/Scripts/Effects') diff --git a/Assets/Scripts/Effects/AfterImageEffects.cs b/Assets/Scripts/Effects/AfterImageEffects.cs new file mode 100644 index 00000000..a19be897 --- /dev/null +++ b/Assets/Scripts/Effects/AfterImageEffects.cs @@ -0,0 +1,186 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +/// +/// 残影特效 +/// +public class AfterImageEffects : MonoBehaviour +{ + + public Material[] materials = new Material[8]; + + //开启残影 + public bool _OpenAfterImage; + + //残影颜色 + public Color _AfterImageColor = Color.black; + //残影的生存时间 + public float _SurvivalTime = 1; + //生成残影的间隔时间 + public float _IntervalTime = 0.2f; + private float _Time = 0; + //残影初始透明度 + [Range(0.1f, 1.0f)] + public float _InitialAlpha = 1.0f; + + private List _AfterImageList; + private SkinnedMeshRenderer _SkinnedMeshRenderer; + + void Awake() + { + _AfterImageList = new List(); + _SkinnedMeshRenderer = GetComponent(); + } + void Update() + { + if (_OpenAfterImage && _AfterImageList != null) + { + if (_SkinnedMeshRenderer == null) + { + _OpenAfterImage = false; + return; + } + + _Time += Time.deltaTime; + //生成残影 + CreateAfterImage(); + //刷新残影 + UpdateAfterImage(); + } + } + /// + /// 生成残影 + /// + void CreateAfterImage() + { + //生成残影 + if (_Time >= _IntervalTime) + { + _Time = 0; + + Mesh mesh = new Mesh(); + _SkinnedMeshRenderer.BakeMesh(mesh); + + Material material = new Material(_SkinnedMeshRenderer.material); + // SetMaterialRenderingMode(material, RenderingMode.Fade); + + _AfterImageList.Add(new AfterImage( + mesh, + material, + transform.localToWorldMatrix, + _InitialAlpha, + Time.realtimeSinceStartup, + _SurvivalTime)); + } + } + /// + /// 刷新残影 + /// + void UpdateAfterImage() + { + //刷新残影,根据生存时间销毁已过时的残影 + for (int i = 0; i < _AfterImageList.Count; i++) + { + float _PassingTime = Time.realtimeSinceStartup - _AfterImageList[i]._StartTime; + + if (_PassingTime > _AfterImageList[i]._Duration) + { + _AfterImageList.Remove(_AfterImageList[i]); + Destroy(_AfterImageList[i]); + continue; + } + + if (_AfterImageList[i]._Material.HasProperty("_Color")) + { + _AfterImageList[i]._Alpha *= (1 - _PassingTime / _AfterImageList[i]._Duration); + _AfterImageColor.a = _AfterImageList[i]._Alpha; + // _AfterImageList[i]._Material.SetColor("_Color", _AfterImageColor); + } + + // 绘制submesh + for(int j = 0; j < _AfterImageList[i]._Mesh.subMeshCount; ++j) + { + if (j >= 4) continue; + Graphics.DrawMesh(_AfterImageList[i]._Mesh, _AfterImageList[i]._Matrix, /*_AfterImageList[i]._Material*/materials[j], gameObject.layer, null, j); + } + } + } + /// + /// 设置纹理渲染模式 + /// + void SetMaterialRenderingMode(Material material, RenderingMode renderingMode) + { + switch (renderingMode) + { + case RenderingMode.Opaque: + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + material.SetInt("_ZWrite", 1); + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = -1; + break; + case RenderingMode.Cutout: + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + material.SetInt("_ZWrite", 1); + material.EnableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 2450; + break; + case RenderingMode.Fade: + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetInt("_ZWrite", 0); + material.DisableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 3000; + break; + case RenderingMode.Transparent: + material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + material.SetInt("_ZWrite", 0); + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_ALPHABLEND_ON"); + material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = 3000; + break; + } + } +} +public enum RenderingMode +{ + Opaque, + Cutout, + Fade, + Transparent, +} +class AfterImage : Object +{ + //残影网格 + public Mesh _Mesh; + //残影纹理 + public Material _Material; + //残影位置 + public Matrix4x4 _Matrix; + //残影透明度 + public float _Alpha; + //残影启动时间 + public float _StartTime; + //残影保留时间 + public float _Duration; + + public AfterImage(Mesh mesh, Material material, Matrix4x4 matrix4x4, float alpha, float startTime, float duration) + { + _Mesh = mesh; + _Material = material; + _Matrix = matrix4x4; + _Alpha = alpha; + _StartTime = startTime; + _Duration = duration; + } + +} \ No newline at end of file diff --git a/Assets/Scripts/Effects/AfterImageEffects.cs.meta b/Assets/Scripts/Effects/AfterImageEffects.cs.meta new file mode 100644 index 00000000..f2bd3581 --- /dev/null +++ b/Assets/Scripts/Effects/AfterImageEffects.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f9a1194f9a331f41b8f32865ba192bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Effects/IEffectHandler.cs b/Assets/Scripts/Effects/IEffectHandler.cs new file mode 100644 index 00000000..bdc4c6a0 --- /dev/null +++ b/Assets/Scripts/Effects/IEffectHandler.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class IEffectHandler : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/Scripts/Effects/IEffectHandler.cs.meta b/Assets/Scripts/Effects/IEffectHandler.cs.meta new file mode 100644 index 00000000..142a3f23 --- /dev/null +++ b/Assets/Scripts/Effects/IEffectHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb3081a24820b3e438133b2ca6eb5549 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs b/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs new file mode 100644 index 00000000..65a36d9d --- /dev/null +++ b/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs @@ -0,0 +1,124 @@ +using UnityEngine; +using System.Collections; + +public class ShurikenBakedMeshEmitter : MonoBehaviour +{ + [Tooltip("パーティクルで使用したいメッシュ")] + public SkinnedMeshRenderer skin; + //使用するメッシュの現在の形を保存 + Mesh baked; + //再生に使用するパーティクルシステム + ParticleSystem particle; + ParticleSystemRenderer render; + [Tooltip("パーティクルの再生/停止")] + public bool emit; + [Tooltip("パーティクルを放出する間隔(秒)")] + public float coolDown = 0.5f; + //現在の待機時間 + float interval = 0; + + // Use this for initialization + void Start() + { + //元となるメッシュが指定されていなければ本スクリプトを停止 + if (!skin) + this.enabled = false; + //使用するパーティクルシステムへのアクセス + particle = GetComponent(); + render = GetComponent(); + } + + // Update is called once per frame + void Update() + { + //emitが[true]なら... + if (emit) + { + //待機時間の計算 + interval -= Time.deltaTime; + //必要分の待機時間が経過したなら... + if (interval < 0) + { + //シーンに新たなGameObjectを再生(本GameObjectのコピー) + GameObject newEmitter = Instantiate(gameObject, transform.position, transform.rotation) as GameObject; + //再生したGameObjectにEmitMesh()を指示 + newEmitter.GetComponent().EmitMesh(); + //待機時間のリセット + interval = coolDown; + } + //emitが[false]なら... + } + else + { + //待機時間のリセット + interval = coolDown; + } + } + + //外部からのアクセスでパーティクルの再生をさせる + public void EmitMesh() + { + //Update ()させない為に[false] + emit = false; + //メッシュの型をリセット + baked = new Mesh(); + //使用するメッシュの現在の形を保存 + skin.BakeMesh(baked); + + //自身のパーティクルシステムへのアクセス + particle = GetComponent(); + render = GetComponent(); + + Mesh mainMesh = baked; + Mesh meshToCopy = new Mesh(); + meshToCopy.vertices = mainMesh.vertices; + meshToCopy.triangles = mainMesh.triangles; + meshToCopy.normals = mainMesh.normals; + meshToCopy.uv = mainMesh.uv; + int amount = 8; + Matrix4x4[] matrix = new Matrix4x4[amount]; + for (int i = 0; i < amount; i++) + { + matrix[i].SetTRS(new Vector3(i * 10, 0, 0), Quaternion.Euler(new Vector3(Random.Range(-5, 5), Random.Range(0, 360), Random.Range(-5, 5))), Vector3.one); + } + + CombineInstance[] ci = new CombineInstance[amount]; + for (int i = 0; i < amount; i++) + { + ci[i] = new CombineInstance(); + ci[i].mesh = meshToCopy; + ci[i].transform = matrix[i]; + } + + Mesh batchedMesh = gameObject.AddComponent().mesh = new Mesh(); + batchedMesh.CombineMeshes(ci); + + int[] mainSubTri; + int[] newSubTri; + batchedMesh.subMeshCount = mainMesh.subMeshCount; + + for (int i = 0; i < mainMesh.subMeshCount; i++) + { + mainSubTri = mainMesh.GetTriangles(i); + + newSubTri = new int[mainSubTri.Length * amount]; + + for (int ii = 0; ii < amount; ii++) + { + for (int iii = 0; iii < mainSubTri.Length; iii++) + { + newSubTri[(ii * mainSubTri.Length) + iii] = mainSubTri[iii] + (ii * mainMesh.vertexCount); + } + } + batchedMesh.SetTriangles(newSubTri, i); + } + + + //パーティクルシステムで使用するメッシュを指定 + render.mesh = meshToCopy; + //パーティクルの再生 + particle.Play(); + //本GameObjectの破棄の指示 + Destroy(gameObject, particle.duration); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs.meta b/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs.meta new file mode 100644 index 00000000..b39edab1 --- /dev/null +++ b/Assets/Scripts/Effects/ShurikenBakedMeshEmitter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bd02b95bf27c724ea9bb26806323053 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: -- cgit v1.1-26-g67d0