使用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便不能使用了。具體使用什么碰撞器以后再研究。
