【游戏开发解答】教你在Unity中使用LineRenderer制作行军蚂蚁线(行军 | 虚线 | 路径 | 线段)

一、前言

嗨,大家好,我是新发。
有同学私信我,问了如下的问题,
在这里插入图片描述
这种线我们叫蚂蚁线,那么,我们在Unity中如何实现呢?今天我就来讲讲~

本文最终效果,工程源码见文章末尾,
请添加图片描述

二、实现方案

Unity中有一个LineRenderer组件,可以很方便得进行线段的绘制,比如钢铁侠的激光技能,就可以使用LineRenderer来实现,
请添加图片描述
我之前写过很多篇文章讲过LineRenderer的教程,大家可以看下:
《【游戏开发实战】Unity实现水果忍者切水果的刀痕效果教程(两种实现方式:TrailRenderer、LineRenderer)》

《【游戏开发进阶】玩转贝塞尔曲线,教你在Unity中画Bezier贝塞尔曲线(二阶、三阶),手把手教你推导公式》

《【游戏开发实战】TapTap物理画线游戏,教你使用Unity实现2D物理画线功能,看到我为你画的彩虹了吗》

《【游戏开发实验】Unity音频效果可视化显示(GetSpectrumData接口)》

那么,如何使用LineRenderer实现蚂蚁线的效果呢?
其实只需要在材质上做点文章就可以了,材质属性中有个TilingOffset来操作UV,讲到这里,估计部分小伙伴已经知道如何实现了,如果还没悟透,没关系,继续往下看吧~

三、具体实操

1、图片资源:line.png

我用PhotoShop做了一张线段图片,线段的两边留一些空白,如下,
在这里插入图片描述
保存为lin.png,导入到Unity中,勾选Alpha Is Transparency,点击Apply
在这里插入图片描述
效果如下
在这里插入图片描述

2、制造材质球:line.mat

接着我们创建一个材质球,重命名为line
在这里插入图片描述
选中line材质球,设置shaderUnlit/Transparent,设置贴图为刚刚的line.png,如下,
在这里插入图片描述
这样,我们的材质球就搞定啦~

3、创建LineRenderer

我们在Hierarchy视图中右键鼠标,点击菜单Effects / Line,就可以场景一个带LineRenderer组件的物体啦,
在这里插入图片描述
如下
在这里插入图片描述
接着我们设置LineRenderer的材质为刚刚的line.mat,如下,
在这里插入图片描述
此时我们在场景中就可以看到一条线段了,
在这里插入图片描述

4、调节材质的Tiling和Offset

我们先设置一下LineRenderer的两个坐标点,比如我设置为(0, 0, 0)(10, 0, 0)
在这里插入图片描述
可以看到此时线段变长了,
在这里插入图片描述
上面我们也看到,贴图被拉伸了,没关系,调整一下Tiling,如下,
请添加图片描述
一节一节的小线段就出来了,
在这里插入图片描述
如果我们想让线上的 “小蚂蚁” 动起来,只需要调节Offset参数即可,如下,
请添加图片描述

5、用代码控制Tiling和Offset

上面我们是手动调节TilingOffset,实际运行过程中是需要通过代码来控制的,
需要用到Material的两个方法:

// Material.cs
// 设置Tiling
public void SetTextureScale(int nameID, Vector2 value);
// 设置Offset
public void SetTextureOffset(int nameID, Vector2 value);

我们创建一个LineCtrler.cs脚本,
在这里插入图片描述
代码很简单,如下,

扫描二维码关注公众号,回复: 13334831 查看本文章
using UnityEngine;

public class LineCtrler : MonoBehaviour
{
    
    
    [SerializeField]
    private LineRenderer lineRenderer;
    private Material material;
    private Vector2 tiling;
    private Vector2 offset;
    private int mainTexProperty;

    void Start()
    {
    
    
        // 缓存材质实例
        material = lineRenderer.material;
        // 缓存属性id,防止下面设置属性的时候重复计算名字的哈希
        mainTexProperty = Shader.PropertyToID("_MainTex");

        tiling = new Vector2(20, 0);
        offset = new Vector2(0, 0);
        // 设置Tiling
        material.SetTextureScale(mainTexProperty, tiling);
        // 设置Offset
        material.SetTextureOffset(mainTexProperty, offset);
    }
}

6、挂脚本进行测试

我们给场景中的Line挂上LineCtrler脚本,并设置LineRenderer成员,如下,
在这里插入图片描述
运行测试,可以看到,代码正常工作,
请添加图片描述

7、LineRenderer起始点跟随飞机坐标

上面,我们的线段是静止的,实际需求是根据鼠标点击的目标位置设置线段的坐标,为了演示,我去找个飞机的图标,找图标,推荐在阿里图标库中,我在多篇文章中都安利过,地址:https://www.iconfont.cn/
在这里插入图片描述
把飞机图片导入工程中,设置Texture TypeSprite (2D and UI)
在这里插入图片描述
把飞机放入场景中,
请添加图片描述
然后我们加点代码,让LineRenderer的起始点跟随飞机坐标,如下

using UnityEngine;

public class LineCtrler : MonoBehaviour
{
    
    
	// ... 

	// 飞机
    [SerializeField]
    private Transform airplane;
	
	private void Update() {
    
    
        lineRenderer.SetPosition(0, airplane.position);
    }
}

回到场景中,给LineCtrler脚本设置Airplane对象,如下,
在这里插入图片描述
运行测试,可以看到,LineRenderer的起始坐标已经跟随飞机的坐标了,
请添加图片描述

9、根据线段长度计算Tiling

我们上面看到,线段长度变化的时候,纹理相应的发生拉伸和挤压,这是因为我们没有动态计算Tiling,我们只需要根据长度来计算Tiling即可,改一下代码,如下,

using UnityEngine;

public class LineCtrler : MonoBehaviour
{
    
    
	// ... 
	
    // 线长
    private float lineLen;
    // 密度
    [SerializeField]
    private float density = 2f;

	private void Update() 
	{
    
    
		// ...
		
		// 计算线长度
		lineLen = (lineRenderer.GetPosition(1) - lineRenderer.GetPosition(0)).magnitude;
		// 根据线段长度计算Tiling
		tiling = new Vector2(lineLen * density, 0);
		// 设置Tiling
		material.SetTextureScale(mainTexProperty, tiling);
	}
}

运行测试,可以看到,现在蚂蚁线纹理正常了,
请添加图片描述

10、小蚂蚁爬起来

我们上面看到,蚂蚁线上的 “小蚂蚁” 运行中没有动态地爬起来,我们在Update中加上对Offset的设置即可,如下,

using UnityEngine;

public class LineCtrler : MonoBehaviour
{
    
    
	// ...
	
    // 定时器
    private float timer = 0;
    // 频率间隔
    [SerializeField]
    private float frequency = 0.03f;
    // 小蚂蚁爬行速度
    [SerializeField]
    private float moveSpeed = 0.04f;

	private void Update() 
	{
    
    
		// ...
		
		timer += Time.deltaTime;
        if(timer >= frequency)
        {
    
    
            timer = 0;
            offset -= new Vector2(moveSpeed, 0);
            material.SetTextureOffset(mainTexProperty, offset);
        }
	}
}

运行测试,可以看到,小蚂蚁爬起来了,
请添加图片描述

11、点击设置目标坐标

最后一步就是获取鼠标点击的位置设置为LineRenderer的终点,让飞机飞过去,继续加逻辑,如下,(注意:严格来说,飞机的逻辑不应该写在LineCtrler.cs中,这里只是演示,所以我就不单独写到新的脚本啦)

using UnityEngine;

public class LineCtrler : MonoBehaviour
{
    
    
	// ...
	
    // 主摄像机
    private Camera mainCam;
    // 目标坐标
    private Vector3 targetPos;
    // 飞机飞行速度
    [SerializeField]
    private float flySpeed = 0.01f;
    // 是否到达目标坐标
    private bool reachTargetPos = false;

	private void Update()
	{
    
    
		// ...
		
		// 严格来说,飞机的逻辑不应该写在LineCtrler中
		// 这里只是演示,所以我就不单独写到新的脚本啦
		if (Input.GetMouseButtonDown(0))
		{
    
    
			var screenPos = Input.mousePosition;
			// 屏幕坐标转世界坐标,注意z轴是距离摄像机的距离
			targetPos = mainCam.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 10));
			// 这里用up是因为飞机的朝向的方向是y轴的方向,如果你的飞机的朝向是z轴的,则用forward
			airplane.up = targetPos - airplane.position;
			// 设置LineRenderer的终点
			lineRenderer.SetPosition(1, targetPos);
			reachTargetPos = false;
			lineRenderer.enabled = true;
		}
		if (!reachTargetPos)
		{
    
    
			// 飞机飞向目标的
			airplane.position += airplane.up * flySpeed;
			
			// 检测是否到达目标坐标
			if (Vector3.Dot(airplane.up, targetPos - airplane.position) < 0)
			{
    
    
			    airplane.position = targetPos;
			    reachTargetPos = true;
			    lineRenderer.enabled = false;
			}
		}
	}
}

运行测试,可以看到,我们要的效果已经有了,
请添加图片描述
我们优化一下,加个背景图,换个飞机图片,效果如下
请添加图片描述

四、工程源码

本文Demo工程我已上传到CODE CHINA,感兴趣的同学可自行下载学习,
地址:https://codechina.csdn.net/linxinfa/UnityMarchingAnts
(注意,我使用的Unity版本为2021.1.7f1c1,如果你使用的版本与我不同,可能打开工程会有一些兼容问题)
在这里插入图片描述

五、完毕

好啦,就到这里吧~
我是林新发:https://blog.csdn.net/linxinfa
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,如果有什么技术上的疑问,欢迎留言或私信~

猜你喜欢

转载自blog.csdn.net/linxinfa/article/details/121507619
今日推荐