子弹碰撞检测,击中特效和音效——Unity随手记(2021.1.31)

文章目录

今天实现的内容:

子弹碰撞检测逻辑

子弹类,子弹类目前只做运动,碰撞检测和冲击特效/音效的处理,运动采用直接修改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秒后销毁。
子弹碰撞检测,击中特效和音效——Unity随手记(2021.1.31)
子弹碰撞检测,击中特效和音效——Unity随手记(2021.1.31)

子弹冲击音效

用了和脚步声有点类似的办法,使用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以及缺陷:

好像有时候射线碰撞检测会失效,讨厌射线。
子弹是没有下坠的,想整一个有下坠效果的子弹。
我需要更多的子弹冲击音效资源,目前只有一套。
子弹碰撞检测,击中特效和音效——Unity随手记(2021.1.31)
既然都开始做子弹了,对象池也该提上日程了。


值得注意的:

冲击音效没有使用挂载到任何物体上的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); }); //找到与碰撞物体对应的那一套音效

上一篇:【HIT】哈工大2021春软件构造复习(6)


下一篇:Hit the Lottery