如何根据射线命中数量使用LineRenderer绘制多条线段?
解决Unity中根据射线命中数量绘制多条线段的问题
看起来你已经搭好了射线检测的基础框架,现在要实现的就是根据射线命中的数量,用LineRenderer画出对应条数的线段对吧?我来帮你把这个功能整合到现有代码里:
第一步:调整变量,改用更灵活的LineRenderer集合
原来的myLines数组不太适合动态增减的场景,我们换成List<LineRenderer>来管理所有绘制的线段:
// 替换掉原来的GameObject[] myLines; List<LineRenderer> lineRenderers = new List<LineRenderer>();
第二步:写一个创建LineRenderer的辅助方法
这个方法可以帮我们快速生成配置好基础属性的线段,不用每次重复写设置代码:
private LineRenderer CreateLineRenderer() { GameObject lineObj = new GameObject($"HitLine_{lineRenderers.Count}"); LineRenderer lr = lineObj.AddComponent<LineRenderer>(); // 自定义线段的外观,你可以根据需求调整 lr.startWidth = 0.02f; lr.endWidth = 0.02f; lr.material = new Material(Shader.Find("Sprites/Default")); lr.startColor = Color.cyan; lr.endColor = Color.red; lr.positionCount = 2; // 线段只需要两个端点 return lr; }
第三步:整合射线检测与线段绘制逻辑
在Update方法里,先清除上一帧的旧线段,再执行射线检测,最后根据命中结果生成对应数量的线段:
void Update() { // 保留你原来的旋转逻辑,这里不改动 if (nonstopSpin) { foreach (GameObject obj in objectsToRotate) { if (useQuaternion) { obj.transform.rotation = Quaternion.Euler(obj.transform.rotation.eulerAngles + spinDirection * speed); } else { obj.transform.Rotate(spinDirection * speed); } } } // 清除上一帧的旧线段 ClearOldLines(); // 执行射线检测并绘制新线段 DrawLinesFromRaycast(); } private void ClearOldLines() { foreach (var lr in lineRenderers) { Destroy(lr.gameObject); } lineRenderers.Clear(); } private void DrawLinesFromRaycast() { // 生成射线,根据useMouse参数选择不同的射线来源 if (useMouse) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); } else { ray = new Ray(transform.position, to.position - transform.position); } // 获取所有命中结果 hits = Physics.RaycastAll(ray); // 遍历每个命中点,绘制从射线起点到命中点的线段 foreach (RaycastHit hitResult in hits) { LineRenderer newLine = CreateLineRenderer(); newLine.SetPosition(0, ray.origin); newLine.SetPosition(1, hitResult.point); lineRenderers.Add(newLine); } }
完整整合后的代码
把上面的内容合并到你的RotateObjects类里,最终代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateObjects : MonoBehaviour { public GameObject[] objectsToRotate; public Transform to; public float speed = 0.1f; public Vector3 spinDirection; public bool useMouse = false; public bool useQuaternion = false; public bool nonstopSpin = false; Ray ray; RaycastHit hit; RaycastHit[] hits; List<LineRenderer> lineRenderers = new List<LineRenderer>(); void Start() { // 保留你原来的初始化逻辑 } void Update() { // 原有旋转逻辑 if (nonstopSpin) { foreach (GameObject obj in objectsToRotate) { if (useQuaternion) { obj.transform.rotation = Quaternion.Euler(obj.transform.rotation.eulerAngles + spinDirection * speed); } else { obj.transform.Rotate(spinDirection * speed); } } } // 线段绘制逻辑 ClearOldLines(); DrawLinesFromRaycast(); } private void ClearOldLines() { foreach (var lr in lineRenderers) { Destroy(lr.gameObject); } lineRenderers.Clear(); } private void DrawLinesFromRaycast() { if (useMouse) { ray = Camera.main.ScreenPointToRay(Input.mousePosition); } else { ray = new Ray(transform.position, to.position - transform.position); } hits = Physics.RaycastAll(ray); foreach (RaycastHit hitResult in hits) { LineRenderer newLine = CreateLineRenderer(); newLine.SetPosition(0, ray.origin); newLine.SetPosition(1, hitResult.point); lineRenderers.Add(newLine); } } private LineRenderer CreateLineRenderer() { GameObject lineObj = new GameObject($"HitLine_{lineRenderers.Count}"); LineRenderer lr = lineObj.AddComponent<LineRenderer>(); lr.startWidth = 0.02f; lr.endWidth = 0.02f; lr.material = new Material(Shader.Find("Sprites/Default")); lr.startColor = Color.cyan; lr.endColor = Color.red; lr.positionCount = 2; return lr; } }
几个实用小提示
- 如果你的场景需要频繁刷新线段,建议用对象池复用LineRenderer,避免频繁创建销毁带来的性能损耗。
- 确保被射线检测的物体都添加了Collider组件,否则射线会直接穿过,不会产生命中结果。
- 可以根据需求调整LineRenderer的Shader,比如用URP的Lit Shader来获得更好的光照效果。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

