文章目录
今天实现的内容:
子弹碰撞检测逻辑
子弹类,子弹类目前只做运动,碰撞检测和冲击特效/音效的处理,运动采用直接修改transform的方式,没有下坠弹道效果。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Scripts.Weapon
{
// 没有基于物理的子弹
public class Bullet : MonoBehaviour
{
// 子弹速度
public float bulletSpeed;
// 子弹的冲击预制体 主要是冲击粒子特效
public GameObject impactPrefab;
// 子弹冲击音效
public ImpactAudioData impactAudioData;
// 子弹的Transform引用 专门给this.transform取个别名罢了
private Transform bulletTransform;
// 子弹上一帧的位置 用于碰撞的射线检测
private Vector3 prevPosition;
private void Start()
{
bulletTransform = transform;
prevPosition = bulletTransform.position;
}
private void Update()
{
// 无下坠效果
bulletTransform.Translate(0, 0, bulletSpeed * Time.deltaTime);
// 发射射线
if (Physics.Raycast(bulletTransform.position,
(bulletTransform.position - prevPosition).normalized,//射线发射方向为从上一帧的位置发射到这一帧的位置
out RaycastHit temp_hit,
(bulletTransform.position - prevPosition).magnitude))//射线最大长度为这两个位置之间的长度
{
//Debug.DrawRay(transform.position, transform.forward, Color.red, 0.1f);
//Debug.Log(temp_hit.collider.name);
// 如果碰到东西了 就生成ImpactPrefab
var temp_impact = Instantiate(impactPrefab, temp_hit.point,
Quaternion.LookRotation(temp_hit.normal, Vector3.up));
// 播放音效
var temp_impactTagWithAudios =
impactAudioData.impactTagsWithAudios.Find(temp_AudioData => //这是lambda表达式?
{ return temp_AudioData.tag.Equals(temp_hit.collider.tag); }); //找到与碰撞物体对应的那一套音效
if (temp_impactTagWithAudios != null) //如果找到了 才播放音频 这是为了代码鲁棒性
{
int temp_length = temp_impactTagWithAudios.impactAudioClips.Count; //获得这一套音效的长度
var temp_audioClip = temp_impactTagWithAudios.impactAudioClips[Random.Range(0, temp_length)]; //随机获取其中的一个Clip
AudioSource.PlayClipAtPoint(temp_audioClip, temp_hit.point, 0.4f); //直接在碰撞点播放
}
// 3秒以后销毁物体
Destroy(temp_impact, 3f);
}
// 最后 更新上一次的位置为当前位置
prevPosition = bulletTransform.position;
}
}
}
子弹冲击粒子效果
使用资源包里面的粒子效果,如同。这是一个Prefab,生成在碰撞点,3秒后销毁。
子弹冲击音效
用了和脚步声有点类似的办法,使用ScriptableObject来存储资源,接着在子弹脚本中引用,能根据子弹碰到的物体的Tag随机播放对应的的音效列表中的音效。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Scripts.Weapon
{
// 子弹冲击音效
[CreateAssetMenu(menuName = "FPS/Bullet Impact Audio Data")]
public class ImpactAudioData : ScriptableObject
{
// 根据碰撞的不同材料 播放不同类型的子弹冲击音效
public List<ImpactTagWithAudios> impactTagsWithAudios;
}
// 该类用于区分子弹打到不同类型物体上时的不同音效 类似脚步声的分类方式
[System.Serializable]
public class ImpactTagWithAudios
{
// 用于标记这一套音效的类型 最好和场景中的物体Tag名相同
public string tag;
//
public List<AudioClip> impactAudioClips;
}
}
BUG以及缺陷:
好像有时候射线碰撞检测会失效,讨厌射线。
子弹是没有下坠的,想整一个有下坠效果的子弹。
我需要更多的子弹冲击音效资源,目前只有一套。
既然都开始做子弹了,对象池也该提上日程了。
值得注意的:
冲击音效没有使用挂载到任何物体上的AudioSource来播放,而是使用方法PlayClipAtPoint来直接在碰撞点播放。
AudioSource.PlayClipAtPoint(temp_audioClip, temp_hit.point); //直接在碰撞点播放
找到对应音效列表用的是C#提供的Find方法
var temp_impactTagWithAudios =
impactAudioData.impactTagsWithAudios.Find(temp_AudioData => //这是lambda表达式?
{ return temp_AudioData.tag.Equals(temp_hit.collider.tag); }); //找到与碰撞物体对应的那一套音效