Open1

Unityで線を引くコード

MachiaWorksMachiaWorks

何がしたいのか

線が引きたくてですね。

素直にLineRendererを使えばいいんですが、
DrawMeshを利用している関係上少しやりづらい。
ということで、DrawMeshだけでなんとか線を引けるように検討する。

手順

  • 頂点を定義
  • UV座標を定義(頂点と同じ数)
  • 三角形の構成を定義
  • DrawMeshのAPIコール時に上記情報を指定(Meshクラスに格納されてる)

あとは点を中心に進行方向(次の点へのベクトル)と垂直に幅を取って2点を定義すれば
線が完成する。
ピクセル単位の線ではなく、あくまでテクスチャ付きポリライン扱い。

余談

テクスチャの位置が反転しているっぽいけど、これは三角形の定義順とかも絡んでくる。

コード

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class LineDraw : MonoBehaviour {
    [SerializeField]
    Material m_mat;
    Mesh m_mesh;
    public float buf_x=1.0f;
    public float buf_y=1.0f;
    public float offset_x=0.0f;
    public float offset_y=0.0f;
    private int bullet_num=1;

    //
    private Vector2[] uv_base;
    private Vector2[] uv_result=new Vector2[8];
    private float delta = 0.01666667f;
    private float _time;
    private float _pre_time;
    public class status{
        public float x;
        public float y;
        public float z;
        public bool isAlive;
        public int count;
        public float dx;
        public float dy;

        public status(){
            x=0.0f;
            y=0.0f;
            isAlive=false;
            count=0;
            dx=0.0f;
            dy=0.0f;
        }
    };
    private Vector2 offset;
    public status[] bullet_status;
    private MaterialPropertyBlock _materialPropertyBlock;
    void Start () {
        // 動的なMesh生成
        m_mesh = new Mesh();
        m_mesh.vertices = new Vector3[] {
            new Vector3 (-1.0f+3.0f, -1.0f),
            new Vector3 (1.0f+2.0f, -1.0f),
            new Vector3 (1.0f, 0.0f),
            new Vector3 (-1.0f, 0.0f),
            new Vector3 (1.0f, 3.0f),
            new Vector3 (-1.0f, 3.0f),
            new Vector3 (1.0f-3.0f, 6.0f),
            new Vector3 (-1.0f-2.0f, 6.0f),
        };
        uv_base = new Vector2[]
        {
            new Vector2(0,0),
            new Vector2(0.25f,0),
            new Vector2(0.25f,0.5f),
            new Vector2(0, 0.5f),
            new Vector2(0.25f,0.75f),
            new Vector2(0, 0.75f),
            new Vector2(0.25f,1.0f),
            new Vector2(0,  1.0f),

        };
        m_mesh.triangles = new int[] {
            0, 3, 2,
            0, 2, 1,
            3, 4, 2,
            3, 5, 4,
            5,7,6,
            5,6,4,
        };
        m_mesh.RecalculateNormals();
        m_mesh.RecalculateBounds();
        bullet_status = new status[bullet_num];
        for(int i=0;i<bullet_num; i++){
            bullet_status[i] = new status();
            bullet_status[i].dx = 0.0f;//Random.Range(-0.05f, 0.05f);
            bullet_status[i].dy = 0.0f;//Random.Range(-0.05f, 0.05f);
            bullet_status[i].isAlive = true;
            bullet_status[i].count=i;
            bullet_status[i].z = i*0.00001f;
        }
        //_materialPropertyBlock = new MaterialPropertyBlock();
        _time=Time.deltaTime;
        _pre_time=Time.deltaTime;
    }
    private void Update()
    {
        bool isMove = false;
        _time += Time.deltaTime;
        if( _time> delta){
            isMove =true;
            _time=0.0f;
            //Debug.Log(_time);
        }
        selfUpdate(isMove);
    }
    public void selfUpdate(bool isMove){
        //_materialPropertyBlock.Clear();
        Material tmp = m_mat;
 
        for(int i=0; i<bullet_num; i++ ){
            //描画命令
            if( bullet_status[i].isAlive==true){
 
                //UV座標の更新
                for( int j=0; j<8; j++){
                    {
                        uv_result[j].x = uv_base[j].x;// + (bullet_status[i].count%4*0.25f);
                    }
                    //Y座標は変化なし
                    uv_result[j].y= uv_base[j].y;
                }
                //UV座標をアニメさせる
                m_mesh.uv = uv_result;
                if( isMove== true){
                    bullet_status[i].x += bullet_status[i].dx;
                    bullet_status[i].y += bullet_status[i].dy;
                }
                    tmp = m_mat;

/*
                offset.x = bullet_status[i].count%4*0.25f;
                offset.y = 0.0f;
                */
                //_materialPropertyBlock.SetTextureOffset("_MainTex", offset);
                //_materialPropertyBlock.SetVector("_MainTex_ST", new Vector4(1.0f, 1.0f, bullet_status[i].count%4*0.25f, 0.0f));
                Graphics.DrawMesh(m_mesh, new Vector3(bullet_status[i].x,
                                                bullet_status[i].y,
                                                bullet_status[i].z),
                                                Quaternion.identity,//Quaternion.AngleAxis(20*(float)(bullet_status[i].count%18), new Vector3(0,0,1)), //
                                                tmp, 0
                                                //,null, 0, _materialPropertyBlock, false, false
                                                );
            }
            //カウント
            if( isMove == true){
                bullet_status[i].count++;
                if( bullet_status[i].count>0)
                    bullet_status[i].isAlive=true;
            }
        }
    }
}