一、前言
本篇博客记录的内容为上篇的延续,将介绍完成的射击反馈震屏、子弹散射等工作内容。实现了子弹击中物体产生弹孔的功能。
二、枪械射击弹孔及音效
在之前导入的特效包中找到Bullet_GoldFire_Small_Impact,然后拖拽到场景中去。
在Weapon文件夹下创建一个Bullet脚本,在其中完成设计弹孔的相关逻辑的编写。由于rigidbody会产生资源的消耗,所用用transform来移动就可以。
using System;
using Unity.Mathematics;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Scripts.Weapon
{
public class Bullet : MonoBehaviour
{
public float BulletSpeed;//子弹速度
public GameObject ImpactPrefab;
public ImpactAudioData ImpactAudioData;
private Transform bulletTransform;
private Vector3 prevPosition;
private void Start()
{
bulletTransform = transform;
prevPosition = bulletTransform.position;//初始化
}
private void Update()
{
prevPosition = bulletTransform.position;
bulletTransform.Translate(0, 0, BulletSpeed * Time.deltaTime);
if (!Physics.Raycast(prevPosition,
(bulletTransform.position - prevPosition).normalized,
out RaycastHit tmp_Hit,
(bulletTransform.position - prevPosition).magnitude)) return;//没有碰撞到物体的话就返回
var tmp_BulletEffect =
Instantiate(ImpactPrefab,
tmp_Hit.point,
Quaternion.LookRotation(tmp_Hit.normal, Vector3.up));
Destroy(tmp_BulletEffect, 3);//特效在3秒后destroy
}
}
}
在AssualtRifle脚本中,实例化子弹,并可以进行子弹速度的调整。测试发现子弹速度低于
private void CreateBullet()
{
GameObject tmp_Bullet = Instantiate(BulletPrefab, MuzzlePoint.position, MuzzlePoint.rotation);
tmp_Bullet.transform.eulerAngles += CalculateSpreadOffset();
var tmp_BulletScript = tmp_Bullet.AddComponent<Bullet>();
tmp_BulletScript.ImpactPrefab = BulletImpactPrefab;
tmp_BulletScript.ImpactAudioData = ImpactAudioData;
tmp_BulletScript.BulletSpeed = 500;
}
制作过程中,使用了debug打印,画线等多种方式来检测子弹的碰撞是否成功。
然后实现一下子弹射中物体的声音。
创建ImpactAudioData脚本,和枪械的射击声音一样,也是继承ScriptableObject。Tag AudioClip下面有若干个声音。
using System.Collections.Generic;
using UnityEngine;
namespace Scripts.Weapon
{
[CreateAssetMenu(menuName = "FPS/Impact Audio Data")]
public class ImpactAudioData : ScriptableObject
{
public List<ImpactTagsWithAudio> ImpactTagsWithAudios;
}
[System.Serializable]
public class ImpactTagsWithAudio
{
public string Tag;
public List<AudioClip> ImpactAudioClips;
}
}
回到unity中,类似于枪械开火声音的设置,也是创建一下Audio,然后将音频拖拽到相应的位置,并且设置好相应的tag。
在Bullet脚本中编写弹孔声音的相关逻辑。在碰撞到对应的tag后,返回tag里面的元素,注意对tag进行判断。
//For Audio
var tmp_TagsWithAudio =
ImpactAudioData.ImpactTagsWithAudios.Find((_audioData) => _audioData.Tag.Equals(tmp_Hit.collider.tag));
if (tmp_TagsWithAudio == null) return;
int tmp_Length = tmp_TagsWithAudio.ImpactAudioClips.Count;
AudioClip tmp_AudioClip = tmp_TagsWithAudio.ImpactAudioClips[Random.Range(0, tmp_Length)];
AudioSource.PlayClipAtPoint(tmp_AudioClip, tmp_Hit.point);//直接用的这个类,不需要使用它的组件。
然后回到AssualtRifle脚本,去添加一下audio的赋值。
tmp_BulletScript.ImpactAudioData = ImpactAudioData;
三、子弹散射
打开枪的父类Firearms
子弹的散射根据相机的fov,因为需要进行瞄准的相关实现。
protected Vector3 CalculateSpreadOffset()
{
float tmp_SpreadPercent = SpreadAngle / EyeCamera.fieldOfView;
return tmp_SpreadPercent * UnityEngine.Random.insideUnitCircle;
}
float tmp_SpreadPercent = SpreadAngle / EyeCamera.fieldOfView;算出散射的百分比。
在上面声明散射角度变量。
public float SpreadAngle;
然后在CreateBullet中获取到子弹的transform和欧拉角。
private void CreateBullet()
{
GameObject tmp_Bullet = Instantiate(BulletPrefab, MuzzlePoint.position, MuzzlePoint.rotation);
tmp_Bullet.transform.eulerAngles += CalculateSpreadOffset();
var tmp_BulletScript = tmp_Bullet.AddComponent<Bullet>();
tmp_BulletScript.ImpactPrefab = BulletImpactPrefab;
tmp_BulletScript.ImpactAudioData = ImpactAudioData;
tmp_BulletScript.BulletSpeed = 500;
}
那么散射就完成了,射中物体的弹孔将会根据散射的角度进行一定程度的随机偏移。