目录
一、什么是LineRender
LineRenderer是Unity引擎提供的一个核心渲染组件,主要用于在3D/2D场景中绘制连续的线段。相比Debug.DrawLine的调试用途,LineRenderer可以实现更复杂的可视化效果,并支持材质、光照等高级渲染特性。就是你可以认为是,画一条可看见线条。我们仅从代码角度来考虑一些常用的属性或者API,并不会着重讲解该组件的面板参数
主要特点有:
可绘制任意形状的多边形线段
支持动态修改顶点位置
可调整线宽、颜色、材质等视觉属性
支持世界空间/局部空间坐标系
可与物理系统配合实现碰撞效果
二、LineRender的参数介绍
基础参数表
参数 | 联想 | 作用 | 取值范围 | 示例值 |
---|---|---|---|---|
Positions | 珍珠项链的珍珠 | 定义线段的每个顶点坐标 | Vector3数组 | new Vector3(0,0,0) |
Position Count | 珍珠数量 | 控制线段的分段数量 | ≥2 | 4 |
Loop | 项链扣环 | 是否首尾相连形成闭环 | bool | true |
标系与光照参数
参数 | 联想 | 作用 | 代码示例 | 注意事项 |
---|---|---|---|---|
Use World Space | 地球仪 vs 桌面地球模型 | 控制线段顶点坐标的参考系: - true :使用世界坐标系(绝对位置)- false :使用局部坐标系(相对父物体) | lr.useWorldSpace = false; | 移动物体上的线段建议使用局部坐标系 |
Generate Lighting Data | 日光灯 vs 自发光灯管 | 是否受场景光照影响: - true :接受光照着色计算- false :保持材质原始颜色 | lr.generateLightingData = true; | 需要材质支持光照着色器 |
颜色控制对比表
参数 | 适用场景 | 性能消耗 | 示例效果 |
---|---|---|---|
单色模式startColor /endColor | 简单颜色变化(如激光) | 低 | 从红色渐变到透明红色 |
渐变模式colorGradient | 复杂颜色过渡(如彩虹) | 中 | 红→蓝→绿的多色渐变 |
贴图控制 材质纹理 | 动态纹理效果(如流动岩浆) | 高 | 沿线段运动的纹理图案 |
视觉参数表
参数 | 联想 | 作用 | 代码示例 |
---|---|---|---|
Start Width | 毛笔起笔力度 | 线段起始端宽度 | lr.startWidth = 0.1f |
End Width | 毛笔收笔力度 | 线段末端宽度 | lr.endWidth = 0.5f |
Color Gradient | 彩虹渐变 | 颜色过渡效果 | lr.colorGradient = myGradient |
高级参数表
参数 | 类比说明 | 效果演示 |
---|---|---|
Corner Vertices | 折纸的圆角处理 | 值=5时折角更圆滑 |
End Cap Vertices | 笔尖的形状修饰 | 值=3时端点呈三角锥形 |
Texture Mode | 桌布铺贴方式 | Tile /Stretch 两种模式 |
三、怎么使用LineRender
完整LineRenderer使用示例
Step 1:基础对象创建
// ░▒▓ 创建线对象 ▓▒░
GameObject lineObj = new GameObject("DynamicLine");
lineObj.transform.SetParent(this.transform); // 设置为当前物体的子物体
LineRenderer line = lineObj.AddComponent<LineRenderer>();
看起来像个面片一样。
Step 2:基础参数配置
// ░▒▓ 线段形态设置 ▓▒░
//line.loop = true; // 闭环路径 这个闭环用起来有时候会非常奇怪 注意使用
line.positionCount = 5; // 5个顶点
line.startWidth = 0.5f; // 起始宽度
line.endWidth = 0.1f; // 结束宽度
//line.numCornerVertices = 3; // 转角圆滑度
//line.numCapVertices = 2; // 端点圆滑度
Step 3:材质与光照
// ░▒▓ 材质加载(需提前准备m.mat)▌
Material lineMat = Resources.Load<Material>("m");
line.material = lineMat;
// ░▒▓ 高级材质属性 ▓▒░
lineMat.EnableKeyword("_EMISSION"); // 启用自发光
lineMat.SetColor("_EmissionColor", Color.cyan * 0.8f); // 自发光颜色
// ░▒▓ 光照交互配置 ▓▒░
line.generateLightingData = false; // 受场景光照影响
line.shadowCastingMode = ShadowCastingMode.Off; // 不投射阴影
line.receiveShadows = true; // 接受其他物体阴影
看改掉了人家的材质,同时不受光.高级材质属性这个不会用,一般也很少使用。
Step 4:坐标系与顶点设置
// ░▒▓ 坐标系模式 ▓▒░
line.useWorldSpace = false; // 使用局部坐标系(随父物体移动)
// ░▒▓ 初始化顶点位置 ▓▒░
Vector3[] points = new Vector3[5] {
new Vector3(0, 0, 0),
new Vector3(2, 0, 0),
new Vector3(3, 2, 0),
new Vector3(1, 3, 0),
new Vector3(0, 0, 0) // 闭环终点
};
line.SetPositions(points);
// ░▒▓ 动态修改单个顶点 ▓▒░
line.SetPosition(2, new Vector3(2, 5, 0)); // 修改第三个点位置
这个点,一般来说一两个点就够了,起点和终点,没必要太多的点。
一般不会修改 难以控制
实现一个渐变色:
// ░▒▓ 在Update中实现 ▓▒░
void Update()
{
float pingPong = Mathf.PingPong(Time.time * 2, 1);
// 颜色渐变控制
Gradient gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] {
new GradientColorKey(Color.red, 0),
new GradientColorKey(Color.blue, pingPong)
},
new GradientAlphaKey[] {
new GradientAlphaKey(1, 0),
new GradientAlphaKey(0.5f, 1)
}
);
lr.colorGradient = gradient;
// 自发光强度控制
lr.material.SetColor("_EmissionColor", Color.Lerp(Color.red, Color.blue, pingPong));
}
这个其实是渐变的 可以去试试
四、实战
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;
using Color = UnityEngine.Color;
public class LineRenderFollow : MonoBehaviour
{
[Header("光束设置")]
public float beamLength = 3f; // 光束长度
public float beamWidthStart = 0.2f; // 起始宽度
public float beamWidthEnd = 0.05f; // 结束宽度
[Header("碰撞检测")]
public LayerMask collisionMask; // 碰撞层过滤
public Color collisionColor = Color.yellow; // 碰撞时的颜色
private LineRenderer lineRenderer;
private Gradient originalGradient;
private bool isColliding = false;
void Start() {
InitializeLineRenderer();
CreateColorGradient();
}
void Update() {
UpdateBeam();
HandleCollisionDetection();
}
// 初始化线段渲染器
void InitializeLineRenderer() {
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.useWorldSpace = true;
// 基本参数设置
lineRenderer.positionCount = 2;
lineRenderer.startWidth = beamWidthStart;
lineRenderer.endWidth = beamWidthEnd;
// 材质设置(使用默认材质)
lineRenderer.material = new Material(Shader.Find("Sprites/Default"));
}
// 创建颜色渐变
void CreateColorGradient() {
originalGradient = new Gradient();
originalGradient.SetKeys(
new GradientColorKey[] {
new GradientColorKey(Color.blue, 0f),
new GradientColorKey(Color.red, 1f)
},
new GradientAlphaKey[] {
new GradientAlphaKey(1f, 0f),
new GradientAlphaKey(1f, 1f)
}
);
lineRenderer.colorGradient = originalGradient;
}
// 更新光束状态
void UpdateBeam() {
Vector3 startPoint = transform.position;
Vector3 endPoint = transform.position + transform.forward * beamLength;
lineRenderer.SetPosition(0, startPoint);
lineRenderer.SetPosition(1, endPoint);
}
// 处理碰撞检测
void HandleCollisionDetection() {
RaycastHit hit;
Vector3 direction = transform.forward;
float maxDistance = beamLength;
if (Physics.Raycast(transform.position, direction, out hit, maxDistance, collisionMask)) {
if (!isColliding) {
OnCollisionStart(hit);
}
UpdateCollisionVisual(hit.point);
} else {
if (isColliding) {
OnCollisionEnd();
}
}
}
// 碰撞开始处理
void OnCollisionStart(RaycastHit hit) {
isColliding = true;
Debug.Log("碰撞对象: " + hit.collider.name);
// 调整线段终点到碰撞点
lineRenderer.SetPosition(1, hit.point);
// 改变颜色为警告色
Gradient newGradient = new Gradient();
newGradient.SetKeys(
new GradientColorKey[] {
new GradientColorKey(collisionColor, 0f),
new GradientColorKey(collisionColor, 1f)
},
originalGradient.alphaKeys
);
lineRenderer.colorGradient = newGradient;
}
// 碰撞结束处理
void OnCollisionEnd() {
isColliding = false;
lineRenderer.colorGradient = originalGradient;
}
// 更新碰撞视觉效果
void UpdateCollisionVisual(Vector3 collisionPoint) {
lineRenderer.SetPosition(1, collisionPoint);
}
}
LineRenderer 参数与API完整参考表
一、基础属性
属性/API | 类型/参数 | 返回值 | 示例 | 说明 | 常用度 |
---|---|---|---|---|---|
positionCount | int | - | lr.positionCount = 4; | 设置线段顶点数量 | ★★★★★ |
loop | bool | - | lr.loop = true; | 是否首尾相连 | ★★★★☆ |
useWorldSpace | bool | - | lr.useWorldSpace = false; | 使用世界/局部坐标系 | ★★★★☆ |
startWidth | float | - | lr.startWidth = 0.2f; | 线段起始宽度 | ★★★★★ |
endWidth | float | - | lr.endWidth = 0.05f; | 线段末端宽度 | ★★★★★ |
widthCurve | AnimationCurve | - | lr.widthCurve = myCurve; | 通过曲线控制宽度 | ★★★☆☆ |
startColor endColor | Color | - | lr.startColor = Color.blue; | 起始/结束颜色 | ★★★★☆ |
colorGradient | Gradient | - | lr.colorGradient = myGradient; | 颜色渐变控制 | ★★★★★ |
material | Material | - | lr.material = myMat; | 设置渲染材质 | ★★★★★ |
二、高级属性
属性/API | 类型/参数 | 返回值 | 示例 | 说明 | 常用度 |
---|---|---|---|---|---|
numCornerVertices | int | - | lr.numCornerVertices = 5; | 折角圆滑顶点数 | ★★★☆☆ |
numCapVertices | int | - | lr.numCapVertices = 3; | 端点圆滑顶点数 | ★★★☆☆ |
textureMode | LineTextureMode | - | lr.textureMode = LineTextureMode.Tile; | 贴图映射模式 | ★★☆☆☆ |
shadowCastingMode | ShadowCastingMode | - | lr.shadowCastingMode = ShadowCastingMode.Off; | 阴影投射设置 | ★★☆☆☆ |
generateLightingData | bool | - | lr.generateLightingData = true; | 是否接受光照 | ★★★☆☆ |
alignment | LineAlignment | - | lr.alignment = LineAlignment.View; | 线段对齐方式 | ★☆☆☆☆ |
三、核心API方法
方法 | 参数 | 返回值 | 示例 | 说明 | 常用度 |
---|---|---|---|---|---|
SetPosition | (int index, Vector3 position) | - | lr.SetPosition(0, transform.position); | 设置单个顶点位置 | ★★★★★ |
GetPosition | int index | Vector3 | Vector3 pos = lr.GetPosition(2); | 获取顶点位置 | ★★★★☆ |
SetPositions | Vector3[] positions | - | lr.SetPositions(pointsArray); | 批量设置顶点 | ★★★★★ |
Simplify | (float tolerance) | - | lr.Simplify(0.1f); | 简化线段顶点 | ★★★☆☆ |
BakeMesh | (Mesh mesh, bool useTransform) | - | lr.BakeMesh(myMesh, true); | 生成线段网格 | ★★☆☆☆ |
四、材质相关属性
属性 | 类型 | 示例 | 说明 | 常用度 |
---|---|---|---|---|
material.mainTexture | Texture | lr.material.mainTexture = myTex; | 主贴图设置 | ★★★★☆ |
material.mainTextureScale | Vector2 | lr.material.mainTextureScale = new Vector2(2,1); | 贴图缩放 | ★★★☆☆ |
material.mainTextureOffset | Vector2 | lr.material.mainTextureOffset += Vector2.right * Time.deltaTime; | 贴图偏移 | ★★★☆☆ |
五、性能相关属性
属性 | 类型 | 示例 | 说明 | 常用度 |
---|---|---|---|---|
allowOcclusionWhenDynamic | bool | lr.allowOcclusionWhenDynamic = true; | 动态遮挡优化 | ★★☆☆☆ |
lightProbeUsage | LightProbeUsage | lr.lightProbeUsage = LightProbeUsage.Off; | 光照探针设置 | ★☆☆☆☆ |
receiveShadows | bool | lr.receiveShadows = false; | 是否接收阴影 | ★★☆☆☆ |