using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; namespace Beyond { [RequireComponent(typeof(MeshFilter))] [RequireComponent(typeof(MeshRenderer))] [DisallowMultipleComponent] public class WeaponTrail : MonoBehaviour { [SerializeField] private Transform m_tip; [SerializeField] private Transform m_base; private Mesh m_mesh; [SerializeField] private int m_numFrames = 10; private Transform m_parentWeapon; private const int NUM_VERTICES = 2; private int m_frameNum = 0; private int m_triNum = 0; private int[] m_triangles; private Vector3[] m_vertices; private Color[] m_colours; private bThirdPersonInput m_tpInput; private Renderer m_renderer; private const int NUM_PREV_POINTS = 3; private Vector3[] m_prevTip = new Vector3[NUM_PREV_POINTS], m_prevBase = new Vector3[NUM_PREV_POINTS]; [SerializeField] private int m_maxDivisions = 4; [SerializeField] private float m_stripLength = 0.1f; [ColorUsageAttribute(true, true, 0f, 8f, 0.125f, 3f)] public Color m_colorMultiplier = Color.white; public bool m_alwaysPlay = true; // Start is called before the first frame update void Start() { m_tpInput = Player.Instance.GetComponent(); // transform.parent = null; var meshFilter = GetComponent(); m_renderer = GetComponent(); m_mesh = new Mesh(); m_renderer.shadowCastingMode = ShadowCastingMode.Off; m_mesh.MarkDynamic(); meshFilter.mesh = m_mesh; m_tip.transform.parent = transform.parent; m_base.transform.parent = transform.parent; m_parentWeapon = transform.parent; transform.parent = null; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; transform.localScale = Vector3.one; for (int i = 0; i < NUM_PREV_POINTS; i++) { m_prevTip[i] = m_tip.transform.position; m_prevBase[i] = m_base.transform.position; } //m_vertices = new Vector3[m_numFrames * NUM_VERTICES]; m_vertices = new Vector3[m_numFrames * NUM_VERTICES]; m_colours = new Color[m_vertices.Length]; m_triangles = new int[(m_numFrames-1) * 6]; var basePos = m_base.transform.position; var tipPos = m_tip.transform.position; for (int i = 0; i < m_numFrames; i++) { int vdx = i * NUM_VERTICES; m_vertices[vdx + 0] = basePos; m_vertices[vdx + 1] = tipPos; } int numV = m_vertices.Length; for (int i = 0; i < m_numFrames-1; i++) { int vdx = i * NUM_VERTICES; int tdx = i * 6; int v2 = (vdx + 2 )% numV; int v3 = (vdx + 3 )% numV; //int v2 = (vdx - 2 );//% numV; //int v3 = (vdx - 1 );//% numV; //if (v2 < 0) v2 += numV; //if (v3 < 0) v3 += numV; m_triangles[tdx + 0] = vdx + 0; m_triangles[tdx + 1] = vdx + 1; m_triangles[tdx + 2] = v2; m_triangles[tdx + 3] = v2; m_triangles[tdx + 4] = v3; m_triangles[tdx + 5] = vdx + 1; } // m_mesh.vertices = m_vertices; // m_mesh.triangles = m_triangles; } Vector3 CatmullRom(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, float s) { Vector3 res; float s2, s3; s2 = s * s; s3 = s2 * s; res = p1 * (-s3 + 2.0f * s2 - s) + p2 * (3.0f * s3 - 5.0f * s2 + 2.0f) + p3 * (-3.0f * s3 + 4.0f * s2 + s) + p4 * (s3 - s2); res /= 2.0f; return res; } bool PlayConditions() { bool playConditions = m_tpInput.cc.IsAnimatorTag("Attack") && m_parentWeapon.gameObject.activeInHierarchy; return playConditions; } /* void Update() { bool shouldPlay = PlayConditions() || m_alwaysPlay; m_renderer.enabled = shouldPlay; var basePos = m_base.transform.position; var tipPos = m_tip.transform.position; if (!shouldPlay) { for (int i = 0; i < NUM_PREV_POINTS; i++) { m_prevBase[i] = basePos; m_prevTip[i] = tipPos; } } else { Debug.Log("Attack!"); } int numV = m_vertices.Length; int idx = m_frameNum * NUM_VERTICES; if (m_numDivisions > 1) { for (int d = 0; d < m_numDivisions; d++ ) { idx = m_frameNum * NUM_VERTICES; float t = (float) d / (float) m_numDivisions; m_vertices[idx + 0] = CatmullRom(m_prevBase[1], m_prevBase[0], basePos, basePos, t); m_vertices[idx + 1] = CatmullRom(m_prevTip[1], m_prevTip[0], tipPos, tipPos, t); int tdx = m_frameNum * 6; //int v2 = (idx + 2 );//% numV; //int v3 = (idx + 3 );//% numV; int v2 = (idx - 2 );//% numV; int v3 = (idx - 1 );//% numV; if (v2 < 0) v2 += numV; if (v3 < 0) v3 += numV; m_triangles[tdx + 0] = idx + 0; m_triangles[tdx + 1] = idx + 1; m_triangles[tdx + 2] = v2; m_triangles[tdx + 3] = v2; m_triangles[tdx + 4] = v3; m_triangles[tdx + 5] = idx + 1; m_frameNum++; m_frameNum %= m_numFrames; } } else { m_vertices[idx + 0] = basePos; m_vertices[idx + 1] = tipPos; m_vertices[idx + 2] = m_prevBase[0]; m_vertices[idx + 3] = m_prevTip[0]; int tdx = m_frameNum * 6; int v2 = (idx +2 );//% numV; int v3 = (idx +3 );//% numV; if (v2 < 0) v2 += numV; if (v3 < 0) v3 += numV; m_triangles[tdx + 0] = idx + 0; m_triangles[tdx + 1] = idx + 1; m_triangles[tdx + 2] = v2; m_triangles[tdx + 3] = v2; m_triangles[tdx + 4] = v3; m_triangles[tdx + 5] = idx + 1; m_frameNum++; m_frameNum %= m_numFrames; } //fill colours Color colour = Color.white; for (int i = 0; i < m_numFrames; i++) { //colour.a = (float) (i) / ((float) m_numFrames); colour.a = (float) (m_numFrames - i) / ((float) m_numFrames); int cnum = (m_frameNum - i) % m_numFrames; if (cnum < 0) cnum += m_numFrames; int cid = (cnum * NUM_VERTICES); for (int j = 0; j < NUM_VERTICES; j++) { m_colours[cid + j] = colour; } } m_mesh.vertices = m_vertices; m_mesh.colors = m_colours; //m_mesh. m_mesh.triangles = m_triangles; m_mesh.RecalculateBounds(); for (int i = 0; i < NUM_PREV_POINTS - 1; i++) { m_prevTip[i + 1] = m_prevTip[i]; m_prevBase[i + 1] = m_prevBase[i]; } m_prevTip[0] = tipPos; m_prevBase[0] = basePos; } */ // Update is called once per frame void AddStrip(Vector3 basePos, Vector3 tipPos) { int numV = m_vertices.Length; int idx = m_frameNum * NUM_VERTICES; m_vertices[idx + 0] = basePos; m_vertices[idx + 1] = tipPos; int tidx = m_triNum * 6; int v2 = (idx - 2); int v3 = (idx - 1); if (v2 < 0) v2 += numV; if (v3 < 0) v3 += numV; m_triangles[tidx + 0] = idx + 0; m_triangles[tidx + 1] = idx + 1; m_triangles[tidx + 2] = v2; m_triangles[tidx + 3] = v2; m_triangles[tidx + 4] = v3; m_triangles[tidx + 5] = idx + 1; m_frameNum++; m_frameNum %= m_numFrames; m_triNum++; m_triNum %= (m_numFrames - 1); } void FixedUpdate() { bool shouldPlay = PlayConditions() || m_alwaysPlay; m_renderer.enabled = shouldPlay; var basePos = m_base.transform.position; var tipPos = m_tip.transform.position; if (!shouldPlay) { if (Player.Instance.ActiveWeaponTrail == this) { Player.Instance.ActiveWeaponTrail = null; } for (int i = 0; i < NUM_PREV_POINTS; i++) { m_prevBase[i] = basePos; m_prevTip[i] = tipPos; } AddStrip(basePos, tipPos); return; } else { Player.Instance.ActiveWeaponTrail = this; //Debug.Log("Attack!"); } int numV = m_vertices.Length; int idx = m_frameNum * NUM_VERTICES; if (m_maxDivisions > 1) { float bdist = Vector3.Distance(m_prevBase[0], basePos); float tdist = Vector3.Distance(m_prevTip[0], tipPos); float dist = Mathf.Max(bdist, tdist); int div = Mathf.CeilToInt(dist / m_stripLength); div = Math.Min(div, m_maxDivisions); //Debug.Log("Divisions: "+div); for (int d = 0; d < div; d++ ) { float t = (float) d / (float) div; //var bp = CatmullRom(m_prevBase[1], m_prevBase[0], basePos, basePos, t); //var tp = CatmullRom(m_prevTip[1], m_prevTip[0], tipPos, tipPos, t); var bp = CatmullRom(m_prevBase[2], m_prevBase[1], m_prevBase[0], basePos, t); var tp = CatmullRom(m_prevTip[2], m_prevTip[1], m_prevTip[0], tipPos, t); AddStrip(bp, tp); } } else { AddStrip(basePos, tipPos); } //fill colours Color colour = m_colorMultiplier; for (int i = 0; i < m_numFrames; i++) { //colour.a = (float) (i) / ((float) m_numFrames); colour.a = (float) (m_numFrames - i) / ((float) m_numFrames); int cnum = (m_frameNum - i-1) % m_numFrames; if (cnum < 0) cnum += m_numFrames; int cid = (cnum * NUM_VERTICES); for (int j = 0; j < NUM_VERTICES; j++) { m_colours[cid + j] = colour; } } m_mesh.vertices = m_vertices; m_mesh.colors = m_colours; //m_mesh. m_mesh.triangles = m_triangles; m_mesh.RecalculateBounds(); for (int i = 0; i < NUM_PREV_POINTS - 1; i++) { m_prevTip[i + 1] = m_prevTip[i]; m_prevBase[i + 1] = m_prevBase[i]; } m_prevTip[0] = tipPos; m_prevBase[0] = basePos; } } }