unity 如何使用LineRenderer 动态划线
作者:小小De程序员 发布时间:2021-10-27 03:42:50
我就废话不多说了,大家还是直接看代码吧~
private LineRenderer line1;
//画线
line1 = this.gameObject.AddComponent<LineRenderer>();
//只有设置了材质 setColor才有作用
line1.material = new Material(Shader.Find("Particles/Additive"));
line1.SetVertexCount(2);//设置两点
line1.SetColors(Color.yellow, Color.red); //设置直线颜色
line1.SetWidth(5f, 10f);//设置直线宽度
//设置指示线的起点和终点
line1.SetPosition(0, A.transform.position);
line1.SetPosition(1, B.transform.position);
Destroy(this.gameObject.GetComponent<LineRenderer>());
补充:Unity LineRenderer绘制物体行走路线
我是用的角色控制器(Character Controller)+LineRenderer做的
下面是代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerTest : MonoBehaviour
{
public GameObject clone;//这是个空物体 只添加了一个LineRenderer组件
public float speed = 5;
public float jumpSpeed = 10f;
public float luodi = 15;
private Vector3 movePos = Vector3.zero;
public CharacterController controller;
private LineRenderer line;
Vector3[] path;
private float time = 0;
List<Vector3> pos=new List<Vector3> ();
void Awake()
{
path = pos.ToArray();//初始化
line = clone.GetComponent<LineRenderer>();//获得该物体上的LineRender组件
line.SetColors(Color.blue, Color.red);//设置颜色
line.SetWidth(0.2f, 0.1f);//设置宽度
}
void Update()
{
time += Time.deltaTime;
if (time>0.1)//每0.1秒绘制一次
{
time = 0;
pos.Add(transform.position);//添加当前坐标进链表
path = pos.ToArray();//转成数组
}
if (controller.isGrounded)//判断人物是否落地
{
movePos = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
movePos = transform.TransformDirection(movePos);
movePos *= speed;
if (Input.GetButton("Jump")) {
movePos.y = jumpSpeed;
}
}
movePos.y -= luodi * Time.deltaTime;
controller.Move(movePos * Time.deltaTime);
if (path.Length!=0)//有数据时候再绘制
{
line.SetVertexCount(path.Length);//设置顶点数
line.SetPositions(path);//设置顶点位置
}
}
}
补充:Unity组件 — LineRenderer动态添加碰撞
基础知识:
选中要添加组件的gameObject,在Inspector面板,点击“Add Component”按钮,选中LineRenderer组件,添加。
cast Shadows : 蒙上阴影
Receive Shadows : 是否接受阴影
Dynamic Occludee : 是否动态遮罩
Materials 中的属性:
size : 材质球的数量
Element : 具体的材质球
Positions 中的属性:
size : 位置的数量
Element : 具体的位置
Use World Space : 是否使用世界坐标系,还是使用相对坐标系
Width : 线条的宽度
Color : 线条的颜色,注:如果没有赋值材质,无论怎样改变Color的值,颜色都不会有改变。
Corner Vertices : 可形成线条的圆角效果
End Cap Vertices : 影响线条的两端的圆角效果。
注:当line Renderer拥有了材质,可以通过修改Color来改变颜色。当时当修改了Color后,line的颜色没有改变,应该是Material和Color属性结合不好。将Material修改为Sprites/Default,Color的颜色就可以成功的显示在line上面了。
动态添加碰撞器(Polygon Collider2D)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseTrack : MonoBehaviour
{
/// <summary>
/// 获取LineRenderer组件
/// </summary>
[Header("获得LineRenderer组件")]
public LineRenderer lineRenderer;
//获得鼠标跟踪位置
private Vector3[] mouseTrackPositions = new Vector3[20];
private Vector3 headPosition; //头位置
private Vector3 lastPosition; //尾位置
private int positionCount = 0; //位置计数
[Header("设置多远距离记录一个位置")]
public float distanceOfPositions = 0.01f;
private bool firstMouseDown = false; //第一次鼠标点击
private bool mouseDown = false; //鼠标点击
PolygonCollider2D polygonCollider; //添加多边形碰撞
void Start()
{
polygonCollider = gameObject.GetComponent<PolygonCollider2D>();
}
void Update()
{
//鼠标点击的时候
if (Input.GetMouseButtonDown(0))
{
polygonCollider.enabled = true;
lineRenderer.positionCount = 20;
firstMouseDown = true;
mouseDown = true;
}
if (Input.GetMouseButtonUp(0))
{
mouseDown = false;
//ClearColliderAndLineRenderer();
}
OnDrawLine();
firstMouseDown = false;
}
//画线
private void OnDrawLine()
{
if (firstMouseDown == true)
{
positionCount = 0;
//头坐标
headPosition = Camera.main.ScreenToViewportPoint(Input.mousePosition + new Vector3(0, 0, 11));
lastPosition = headPosition;
}
if (mouseDown == true)
{
headPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition + new Vector3(0, 0, 11));
//判断头坐标到尾坐标的距离是否大于记录点位
if (Vector3.Distance(headPosition, lastPosition) > distanceOfPositions)
{
//用于保存位置
SavePosition(headPosition);
positionCount++;
}
lastPosition = headPosition;
}
//设置线性渲染器的位置
SetLineRendererPosition(mouseTrackPositions);
}
//保存位置
private void SavePosition(Vector3 pos)
{
pos.z = 0;
if (positionCount <= 19)
{
for (int i = positionCount; i < 20; i++)
{
mouseTrackPositions[i] = pos;
}
}
else
{
for (int i = 0; i < 19; i++)
{
mouseTrackPositions[i] = mouseTrackPositions[i + 1];
}
}
mouseTrackPositions[19] = pos;
//创建碰撞路径
List<Vector2> colliderPath = GetColliderPath(mouseTrackPositions);
polygonCollider.SetPath(0, colliderPath.ToArray());
}
//计算碰撞体轮廓
float colliderWidth;
List<Vector2> pointList2 = new List<Vector2>();
List<Vector2> GetColliderPath(Vector3[] pointList3)
{
//碰撞体宽度
colliderWidth = lineRenderer.startWidth;
//Vector3转Vector2
pointList2.Clear();
for (int i = 0; i < pointList3.Length; i++)
{
pointList2.Add(pointList3[i]);
}
//碰撞体轮廓点位
List<Vector2> edgePointList = new List<Vector2>();
//以LineRenderer的点位为中心, 沿法线方向与法线反方向各偏移一定距离, 形成一个闭合且不交叉的折线
for (int j = 1; j < pointList2.Count; j++)
{
//当前点指向前一点的向量
Vector2 distanceVector = pointList2[j - 1] - pointList2[j];
//法线向量
Vector3 crossVector = Vector3.Cross(distanceVector, Vector3.forward);
//标准化, 单位向量
Vector2 offectVector = crossVector.normalized;
//沿法线方向与法线反方向各偏移一定距离
Vector2 up = pointList2[j - 1] + 0.5f * colliderWidth * offectVector;
Vector2 down = pointList2[j - 1] - 0.5f * colliderWidth * offectVector;
//分别加到List的首位和末尾, 保证List中的点位可以围成一个闭合且不交叉的折线
edgePointList.Insert(0, down);
edgePointList.Add(up);
//加入最后一点
if (j == pointList2.Count - 1)
{
up = pointList2[j] + 0.5f * colliderWidth * offectVector;
down = pointList2[j] - 0.5f * colliderWidth * offectVector;
edgePointList.Insert(0, down);
edgePointList.Add(up);
}
}
//返回点位
return edgePointList;
}
//设置线条渲染器位置
private void SetLineRendererPosition(Vector3[] position)
{
lineRenderer.SetPositions(position);
}
//用于清除碰撞和线性渲染
void ClearColliderAndLineRenderer()
{
if (polygonCollider)
{
polygonCollider.enabled = false;
}
lineRenderer.positionCount = 0;
}
}
效果图:
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。
来源:https://blog.csdn.net/weixin_43705303/article/details/93197334


猜你喜欢
- 官网教程一、翻转(镜像)头文件 quick_opencv.h:声明类与公共函数#pragma once#include <opencv
- 一、代码结构:二、数据实体类:using System;using System.Collections.Generic;using Sys
- 1,从System.String[]转到List<System.String>System.String[] str={&quo
- 生命周期速览优先级servlet 的声明周期由 tomcat 服务器自行管辖,程序员无法插手;只要没有通过 url 访问 servlet,那
- 本文实例为大家分享了android水平循环滚动控件的具体代码,供大家参考,具体内容如下CycleScrollView.javapackage
- kafka消费不到数据的排查集群上新安装并启动了3个kafka Broker,代码打包上传至集群,运行后发现一直消费不到数据,本地
- 前言众所周知,在多个项目中可能会相同的模块,如果每个项目都去创建一遍的话,这样开发效率会很低。比如在开发一个APP应用的时候,有供APP使用
- 一、引言在移动应用程序的架构设计中,界面与数据即不可分割又不可混淆。在绝大部分的开发经历中,我们都是使用Fragment来进行界面编程,即使
- android读取assets文件下的内容,一般都是使用getAsset.open()方法,并将文件的路径作为参数传入,而当我们解析一个目录
- java 接口回调实例详解首先官方对接口回调的定义是这样的,所谓回调:就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,
- 我们先来看看公众号发放现金红包的效果:需要调用商户平台的接口,接口发放规则如下:1.发送频率限制——默认1800/min 2.发送个数上限—
- 问题描述 在某一天打开电脑后,idea里的代码无缘无故地就爆红了,不但spring框架爆红,就
- 本文实例为大家分享了java实现斗地主发牌系统的具体代码,供大家参考,具体内容如下玩家类package com.softeem.exampl
- 一、增删改1、增加<!-- 添加用户--><insert id="saveUser" paramete
- 在使用spring提供的JpaTemplate进行查询时,如果数据量超过100 条,查询效率就会明显降低。由于开始时使用JPA内部的双向关联
- Stream.Read 方法当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数。语法:public abstract
- 鼠标事件监听机制的三个方面:1.事件源对象:事件源对象就是能够产生动作的对象。在Java语言中所有的容器组件和元素组件都是事件监听中的事件源
- 由于对运算符重载不是多么理解诶,于是就百度了一下,结果发现一个解释很有趣的百度知道,分享看看。回答:+-*/这样的运算符重定义,比如你自定义
- namespace ConsoleTest{ class Program  
- 这篇文章需要一定Vue和SpringBoot的知识,分为两个项目,一个是前端Vue项目,一个是后端SpringBoot项目。后端项目搭建我使