bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

TronTrailをC#にした

プロシージャルなメッシュを作った方が幅が広がりそうなので、入門的な感じで。
マテリアルとテクスチャを用意しておいてそれを使う。

using UnityEngine;
using System.Collections;

public class TrailMain : MonoBehaviour {
	
	GameObject m_TrailObject = null;

	// Use this for initialization
	void Start () {
		Material mat = Resources.Load("Trail/trail_mat") as Material;
		Texture2D tex = Resources.Load("Trail/trail") as Texture2D;
		m_TrailObject = Trail.Create(mat, tex);
	}
	
	// Update is called once per frame
	void Update () {
	
		m_TrailObject.transform.position = new Vector3(10.0f*Mathf.Cos(Time.time), 0, 10.0f*Mathf.Sin(Time.time));
	}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/**
 * @brief	軌跡.
 */
public class Trail : MonoBehaviour {
	
	public static GameObject Create(Material mat, Texture2D tex) {
		
		GameObject go = new GameObject("Trail");
		go.AddComponent<Trail>();
		go.AddComponent<MeshFilter>();
		MeshRenderer mr = go.AddComponent<MeshRenderer>();
		mr.material = mat;
		mr.material.mainTexture = tex;
		
		return go;
	}
	
	class TrailSection {
		Vector3 m_Position = Vector3.zero;
		Vector3 m_UpDir = Vector3.zero;
		float m_Time = 0.0f;
		
		public Vector3 Positioin {
			get { return m_Position; }
			set { m_Position = value; }
		}
		public Vector3 UpDir {
			get { return m_UpDir; }
			set { m_UpDir = value; }
		}
		public float Time {
			get { return m_Time; }
			set { m_Time = value; }
		}
	}
	
	float m_Height = 2.0f;
	float m_Time = 2.0f;
	bool m_AlwaysUp = false;
	float m_MinDistance = 0.1f;
	
	Color m_StartColor = Color.white;
	Color m_EndColor = new Color(1.0f, 1.0f, 1.0f, 0.0f);
	
	List<TrailSection> m_TrailSectionList = null;
	
	void Awake () {
		m_TrailSectionList = new List<TrailSection>();
	}
	
	// Update is called once per frame
	void LateUpdate () {
		Vector3 pos = gameObject.transform.position;
		float now = Time.time;
		
		RemoveOldSection(now);
		AddNewSection(pos, now);
		
		RebuildMesh();
	}
	
	void RemoveOldSection(float now) {
		int section_count = m_TrailSectionList.Count;
		while(section_count > 0 && now > m_TrailSectionList[section_count-1].Time + m_Time) {
			m_TrailSectionList.RemoveAt(section_count-1);
			--section_count;
		}
	}
	
	void AddNewSection(Vector3 pos, float now) {
		
		if(m_TrailSectionList.Count == 0 || (m_TrailSectionList[0].Positioin - pos).sqrMagnitude > m_MinDistance * m_MinDistance) {
			TrailSection section = new TrailSection();
			section.Positioin = pos;
			if(m_AlwaysUp) {
				section.UpDir = Vector3.up;
			}
			else {
				section.UpDir = gameObject.transform.TransformDirection(Vector3.up);
			}
			section.Time = now;
			m_TrailSectionList.Insert(0, section);
		}
	}
	
	void RebuildMesh() {
		
		MeshFilter meshFilter = GetComponent<MeshFilter>();
		Mesh mesh = meshFilter.mesh;
		mesh.Clear();
		
		int count = m_TrailSectionList.Count;
		if(count < 2) {
			return;
		}
		
		Vector3 [] vertices = new Vector3[count*2];
		Color [] colors = new Color[count*2];
		Vector2 [] uv = new Vector2[count*2];
		
		TrailSection prevSection = m_TrailSectionList[0];
		TrailSection curSection = m_TrailSectionList[0];
		
		Matrix4x4 localTransform = gameObject.transform.worldToLocalMatrix;
		
		// generate vertex, uv and colors
		for(int i = 0; i < count; ++i) {
			prevSection = curSection;
			curSection = m_TrailSectionList[i];
			float u = 0.0f;
			if(i != 0) {
				u = Mathf.Clamp01((Time.time - curSection.Time)/m_Time);
			}
			Vector3 upDir = curSection.UpDir;
			vertices[i*2+0] = localTransform.MultiplyPoint(curSection.Positioin);
			vertices[i*2+1] = localTransform.MultiplyPoint(curSection.Positioin+upDir*m_Height);
			
			uv[i*2+0] = new Vector2(u, 0.0f);
			uv[i*2+1] = new Vector2(u, 1.0f);
			
			Color interpolatedColor = Color.Lerp(m_StartColor, m_EndColor, u);
			colors[i*2+0] = interpolatedColor;
			colors[i*2+1] = interpolatedColor;
		}
		
		// generate triangles indices
		int [] triangles = new int[(count-1)*2*3];
		for(int i = 0; i < triangles.Length/6; ++i) {
			triangles[i*6+0] = i*2+0;
			triangles[i*6+1] = i*2+1;
			triangles[i*6+2] = i*2+2;
			
			triangles[i*6+3] = i*2+2;
			triangles[i*6+4] = i*2+1;
			triangles[i*6+5] = i*2+3;
		}
		
		mesh.vertices = vertices;
		mesh.colors = colors;
		mesh.uv = uv;
		mesh.triangles = triangles;
	}
}