使用Unity原生LineRenderer+Edge Collider2D實現在2D場景中畫線並帶碰撞體。
我們先來看看效果
實現思路,當鼠標點擊的時候開始在當前位置實例化LineRenderer對象,然后移動的過程中記錄移動的點並賦值給LineRenderer中的 Positions屬性動態修改LineRenderer的形狀和長度。碰撞器方面使用Edge Collider 2D 通過類似方式,記錄點並賦值給碰撞器的Points。
OK看完了大概原理還是來看看具體的代碼吧。
using UnityEngine; using System.Collections; using System.Collections.Generic; using System; public class DrawLineScripts : MonoBehaviour { //得到帶有LineRender物體對象 [Tooltip("The GameObject of LineObject")] public GameObject lineRenderer; //定義一個公共類來存儲初始化成成的物體對象 [Tooltip("The number of instantiate LineObject")] public int preFabLineCount = 6; //初始化LineRenderer 物體對象的集合 [HideInInspector] public List<GameObject> lineList; //存儲鼠標移動過的點 [HideInInspector] public List<Vector2> linePos; //移動點索引 private int idx = 0; //全局線段對象變量 private GameObject gameObj; void Awake() { //激活階段生成固定數量的物體對象 for (int i = 0; i < preFabLineCount; i++) { GameObject go = Instantiate(lineRenderer, new Vector3(0f, 0f, 0f), Quaternion.identity); //將生成的對象隱藏,當需要使用的時候修改位置並顯示出來。 go.SetActive(false); //設置實例化出來物體的父級對象 go.transform.SetParent(gameObject.transform); //將對象添加到全局列表中 lineList.Add(go); } } // Update is called once per frame void Update() { if(Input.GetMouseButtonDown(0)) //鼠標左鍵點擊的時候 { gameObj = GetLineRenderer(); //得到鼠標移動的坐標並將屏幕坐標轉換為世界坐標 Vector3 ve3 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z)); //得到對象身上的LineRenderer組件 LineRenderer lineRenderer = gameObj.GetComponent<LineRenderer>(); //設置LineRenderer組件的起始位置 lineRenderer.SetPosition(idx, new Vector3(ve3.x,ve3.y,0f)); //設置LineRenderer的寬度 lineRenderer.startWidth = 0.4f; //將二維坐標存到數組中 Vector2 v2 = new Vector2(ve3.x, ve3.y); linePos.Add(v2); } else if(Input.GetMouseButton(0)) //鼠標左鍵移動或者靜止的時候 { ++idx; //設置LineRenderer位置的索引每移動一次增加一次 LineRenderer lineRenderer = gameObj.GetComponent<LineRenderer>(); Vector3 ve3 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z)); lineRenderer.positionCount = idx + 1; lineRenderer.SetPosition(idx, new Vector3(ve3.x, ve3.y, 0f)); Vector2 v2 = new Vector2(ve3.x, ve3.y); linePos.Add(v2); } else if(Input.GetMouseButtonUp(0)) //鼠標左鍵抬起的時候 { Vector3 ve3 = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z)); EdgeCollider2D edge = gameObj.GetComponent<EdgeCollider2D>(); //得到物體身上的EdgeCollider2D組件 edge.points = linePos.ToArray(); //將存起來的二維向量點賦值到碰撞器實現碰撞器初始化 linePos.Clear(); //清除點集合方便下次點擊記錄 idx = 0; //索引歸零 } } /// <summary> /// 獲取LineRenderer對象,如果對象集合中有未激活對象則取出未激活對象並激活,否則生成新對象 /// </summary> /// <returns></returns> private GameObject GetLineRenderer() { for (int i = 0; i < lineList.Count; i++) { if (lineList[i].activeInHierarchy == false) { lineList[i].SetActive(true); lineList[i].transform.position = new Vector3(0f, 0f, 0f); return lineList[i]; } } GameObject go = Instantiate(lineRenderer,new Vector3(0f,0f,0f),Quaternion.identity); go.transform.SetParent(gameObject.transform); lineList.Add(go); return go; } }
代碼里面有詳細的注釋,大部分講清了實現原理,我們看一下Inspector面板。
LineRenderer對象面板
這里講一下這個實現存在的問題,這個實現是基於2D場景的,如果要實現3D場景,只要修改其中的屏幕坐標轉換成世界坐標的方法,然后LineRenderer設置點的時候直接使用三維向量坐標即可,但是在3D場景中Edge Collider 2D便不能使用了。具體使用什么碰撞器以后再研究。