【Unity学习心得】如何使用Unity制作更多类型的射击武器(记得看上一篇文章)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

想要了解这篇文章再讲什么,要先看前一篇文章,在前一篇文章中,我们完成了制作地图,实现人物动画和移动脚本,制作单例模式和对象池,制作手枪pistol和子弹bullet和子弹壳bulletShell,制作散弹枪shotgun的功能。接下来我们要做的是扩展武器库制作火箭筒,镭射枪,冲锋枪。事不宜迟立刻开始这期学习吧。


一、导入素材

把上一期内容素材再放一遍:

https://o-lobster.itch.io/simple-dungeon-crawler-16x16-pixel-pack

https://humanisred.itch.io/weapons-and-bullets-pixel-art-asset

二、制作流程

1.制作火箭筒RocketLanucher和火箭Rocket

代码如下(示例):

同样作为一个Gun的Varient生成一个预制体prefab:

通用制作动画:

创建一个同名脚本让它继承自Gun:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RocketLauncher : Gun
{
    public int rocketNum = 4;
    public float rocketAngle = 30;

    protected override void Fire()
    {
	animator.SetTrigger("Shoot");
	StartCoroutine(DelayFire(0.2f));
    }

    private IEnumerator DelayFire(float delay)
    {
	yield return new WaitForSeconds(delay);
	int med = rocketNum / 2;
	for (int i = 0; i < rocketNum; i++)
	{
	    GameObject rocket = ObjectPool.Instance.GetObject(bulletPrefab);
	    rocket.transform.position = muzzleTrans.position;
	    if (rocketNum % 2 == 1)
	    {
		rocket.transform.right = Quaternion.AngleAxis(rocketAngle * (i - med), Vector3.forward) * direction;
	    }
	    else
	    {
		rocket.transform.right = Quaternion.AngleAxis(rocketAngle * (i - med) + rocketAngle / 2f, Vector3.forward) * direction;
	    }
	    rocket.GetComponent<Rocket>().SetTarget(mousePos);
	}
    }
}

 可以看到,我们在重写Fire()方法时使用了协程延迟火箭弹的发射时间,而且我们并没有接着使用bullet预制体也不需要bulletshell,而是新建一个游戏对象rocket:

给它创建一个同名脚本rocket.cs:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rocket : MonoBehaviour
{
    public float lerp;
    public GameObject explosionPrefab;
    public float speed = 15f;
    private Rigidbody2D rb2d;
    private Vector3 targetPos;
    private Vector3 direction;
    private bool arrived; //用arrived来判断是否到达终点坐标

    private void Awake()
    {
	rb2d = GetComponent<Rigidbody2D>();
    }

    private void FixedUpdate()
    {
	direction = (targetPos - transform.position).normalized;
	if(!arrived)
	{
//在两个向量之间进行球面插值,tran.position和targetPos离得越远速度越快
	    transform.right = Vector3.Slerp(transform.right, direction, lerp / Vector2.Distance(transform.position, targetPos));
	    rb2d.velocity = transform.right * speed;
	}
	if(Vector2.Distance(transform.position, targetPos) < 1f && !arrived)
	{
	    arrived = true;
	}
    }
//可以看到我们用SetTarget取代了以往的SetSpeed,将鼠标位置=target即终点坐标
    public void SetTarget(Vector2 target)
    {
	    arrived = false;
	    targetPos = target;
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
	if(other.gameObject.layer == LayerMask.NameToLayer("Wall"))
	{
	    GameObject exp = ObjectPool.Instance.GetObject(explosionPrefab);
	    exp.transform.position = transform.position;
	    rb2d.velocity = Vector2.zero;
	    StartCoroutine(PushObject(0.3f));  
	}
    }
//延迟自身对象进入对象池
    private IEnumerator PushObject(float delay)
    {
	yield return new WaitForSeconds(delay);
	ObjectPool.Instance.PushObject(gameObject);
    }
}

这个Slerp的解释我看了一下,反正感觉是绕着一个轴(这里我们设置的是X轴)做插值运动,这解释能看懂你也不会来看我这篇文章了 

最后我们设置好参数:

2.制作镭射枪LaserGun和火箭Rocket

这是个有个性的枪,因为它既不需要子弹又不需要子弹壳,要实现这种效果我们可以使用LineRenderer来实现激光效果:

给它制作动画,和之前用trigger参数不同,这次我们使用bool来控制动画转换:

我们想要激光变得更多样化还得使用URP插件编写shader graph

在Package Manager中找到URP并下载导入:

回到project中创建New Renderer Data

在project setting中设置graphics

记得保存好后升级整个项目:

回到camera中勾选后处理选项Post Processing:

为项目创建一个Global Volume:

然后到哦我们编写shader graph的时候了:

有了shader graph就到我们创建material的时候:

回到LineRenderer中赋值Material:

给LaserGun创建一个同名脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LaserGun : Gun
{
    private GameObject effect;
    private LineRenderer line;
    private bool isShooting;

    protected override void Start()
    {
    	base.Start();
	    line = muzzleTrans.GetComponent<LineRenderer>();
	    effect = transform.Find("Effect").gameObject;
    }

    protected override void Shoot()
    {
	direction = (mousePos - new Vector2(transform.position.x, transform.position.y)).normalized;
	transform.right = direction;
	if(Input.GetKeyDown(KeyCode.Mouse0))
	{
	    isShooting = true;
	    line.enabled = true; //注意:我们要在项目运行游戏前将line的组件关闭掉!
	    effect.SetActive(true);
	}
	if (Input.GetKeyUp(KeyCode.Mouse0))
	{
	    isShooting = false;
	    line.enabled = false;
	    effect.SetActive(false);
	}
	animator.SetBool("Shoot", isShooting);
	if (isShooting)
	{
	    Fire();
	}
    }

    protected override void Fire()
    {
	    RaycastHit2D hit2d = Physics2D.Raycast(muzzleTrans.position, direction, 30f);
	    line.SetPosition(0, muzzleTrans.position); //射线起点是muzzleTrans的位置
	    line.SetPosition(1, hit2d.point); //将射线终端位置设置为hit2d碰到的那个点位置
	    effect.transform.position = hit2d.point;
	    effect.transform.forward = -direction;
    }


}

这里我们还差一个effect即Partical System没实现:

直接给你们上参数:

 

3.制作冲锋枪Rifle和冲锋枪子弹RifleBullet

        最终是冲锋枪,按道理来说它的pistol实现的原理都差不多所以我们只需要重写Fire函数即可

        

给它一个同名脚本并继承自Gun.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rifle : Gun
{
    protected override void Fire()
    {
	animator.SetTrigger("Shoot");
	RaycastHit2D hit2d = Physics2D.Raycast(muzzleTrans.position, direction, 30f);
	GameObject bullet = ObjectPool.Instance.GetObject(bulletPrefab);
	LineRenderer line = bullet.GetComponent<LineRenderer>();
	line.enabled = true;
	line.SetPosition(0, muzzleTrans.position);
	line.SetPosition(1, hit2d.point);
	GameObject bulletShell = ObjectPool.Instance.GetObject(bulletShellPrefab);
	bulletShell.transform.position = bulletShellTrans.position;
	bulletShell.transform.rotation = bulletShellTrans.rotation;
    }
}

我们可以使用LineRenderer来实现Bullet预制体的效果:

给它一个同名脚本BulletTracer:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletTracer : MonoBehaviour
{
    public float fadeSpeed = 0.1f;
    private LineRenderer line;
    private float alpha;

    private void Awake()
    {
	line = GetComponent<LineRenderer>();
	alpha = line.endColor.a;
    }

    private void OnEnable()
    {
	line.endColor = new Color(line.endColor.r, line.endColor.g, line.endColor.b, alpha);
	StartCoroutine(Fade());
    }

    private IEnumerator Fade()
    {
//LineRenderer淡出效果实现,每固定帧line.endColor.a - fadeSpeed即可
	while (line.endColor.a > 0f)
	{
	    line.endColor = new Color(line.endColor.r, line.endColor.g, line.endColor.b, line.endColor.a - fadeSpeed);
	    yield return new WaitForFixedUpdate();
	}
//回收该对象
	ObjectPool.Instance.PushObject(gameObject);
    }
}

 最后的最后,别忘了把这三把新武器添加到PlayerController.cs的Guns[]数组中:


总结

最终效果如下所示:

made这个冲锋枪的LineRenderer消失太快了我截图不到,反正你们自己做的时候看得到即可(我这地上有弹壳的):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值