【Unity小技巧】3D人物移动脚步和跳跃下落音效控制

news2024/9/25 5:21:56

文章目录

  • 单脚步声
  • 多脚步声,跳跃落地音效
  • 播放不同材质的多脚步声
  • 完结

单脚步声

public AudioClip walkingSound;
public AudioClip runningSound;

//移动音效
public void MoveSound()
{
    // 如果在地面上并且移动长度大于0.9
    if (isGround && moveDirection.sqrMagnitude > 0.9f)
    {
        audioSource.clip = isRun ? runningSound : walkingSound;
        if (!audioSource.isPlaying) audioSource.Play();
    }
    else
    {
        if (audioSource.isPlaying) audioSource.Pause();
    }
}

多脚步声,跳跃落地音效

[SerializeField] private float m_StepInterval; // 脚步声间隔

[SerializeField] private AudioClip[] m_FootstepSounds; // 脚步声音效数组
[SerializeField] private AudioClip m_JumpSound; // 跳跃声音效
[SerializeField] private AudioClip m_LandSound; // 落地声音效

private void Update()
{
    if (!m_Jump)
    {
        m_Jump = Input.GetButtonDown("Jump"); // 检测跳跃输入
    }

	ProgressStepCycle(speed); // 更新步行声音

    //判断角色是否落地,这个判断非常巧妙,假设角色起跳,m_PreviouslyGrounded和m_CharacterController.isGrounded肯定都是false,
    //执行到下一步时角色到达地上,m_CharacterController.isGrounded变为true,因为m_PreviouslyGrounded还未执行,所以还是false,及此时角色刚落地
    if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
    {
        PlayLandingSound(); // 播放落地声音
    }

if (m_CharacterController.isGrounded)
    {
        if (m_Jump)
        {
            PlayJumpSound(); // 播放跳跃声音
        }
    }

    m_PreviouslyGrounded = m_CharacterController.isGrounded;
}
private void PlayLandingSound()
{
    m_AudioSource.clip = m_LandSound; // 设置落地声音
    m_AudioSource.Play();
    //播放落地声音后延迟0.5s再播放脚步声
    m_NextStep = m_StepCycle + .5f;
}

private void PlayJumpSound()
{
    m_AudioSource.clip = m_JumpSound; // 设置跳跃声音
    m_AudioSource.Play();
}

private void ProgressStepCycle(float speed)
{
    //判断角色是否在移动。
    if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
    {
        //如果角色在移动,根据角色当前的速度和行走/奔跑状态来更新步行声音循环计数器 m_StepCycle 的值。
        m_StepCycle += (m_CharacterController.velocity.magnitude + (speed * (m_IsWalking ? 1f : m_RunstepLenghten))) * Time.fixedDeltaTime;
    }

    //然后,检查是否到达了下一个播放脚步声音的时间点。如果没有到达,就直接返回
    if (!(m_StepCycle > m_NextStep))
    {
        return;
    }
    //如果到达了下一个播放脚步声音的时间点,就更新 m_NextStep 的值
    m_NextStep = m_StepCycle + m_StepInterval;
    PlayFootStepAudio(); // 播放脚步声音
}

private void PlayFootStepAudio()
{
    if (!m_CharacterController.isGrounded)
    {
        return;
    }
    int n = UnityEngine.Random.Range(1, m_FootstepSounds.Length);
    m_AudioSource.clip = m_FootstepSounds[n]; // 随机选择一个脚步声音
    m_AudioSource.PlayOneShot(m_AudioSource.clip);
    
    //播放过的脚步声放置第一位,避免连续播放相同的脚步声
    m_FootstepSounds[n] = m_FootstepSounds[0];
    m_FootstepSounds[0] = m_AudioSource.clip;
}

播放不同材质的多脚步声

using System.Collections.Generic;
using UnityEngine;

public class FootStepSound : MonoBehaviour
{
	public RaycastHit hit;  // 射线检测结果
	public GameObject RayGo;  // 射线起点对象
	public AudioClip[] clipsMetal, clipsTree, clipsGrass, clipsDirt, clipsWater;  // 不同类型表面的声音剪辑数组
	public float dist = 2;  // 射线的长度
	private string tagProv;  // 上一次射线检测到的地面标签
							 
	private int go = 0;  // 控制播放声音的变量,0表示重新播放,1表示继续播放
	public AudioSource AS;  // 声音源组件
	public float PitchWalk, PitchRun;  // 行走和奔跑时的音调

	// 创建一个列表用于存储之前选择过的音效索引
	private List<int> playedIndexes = new List<int>();

	void Update()
	{
		float horizontal = Input.GetAxisRaw("Horizontal");
    	float vertical = Input.GetAxisRaw("Vertical");

		if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.W))
			AS.pitch = PitchRun;  // 如果同时按下左Shift和W键,则设置为奔跑音调
		else
			AS.pitch = PitchWalk;  // 否则设置为行走音调

		if (horizontal != 0 || vertical != 0)
		{
			if (Physics.Raycast(RayGo.transform.position, Vector3.down, out hit, dist))  // 向下发射射线检测地面
			{
				if (hit.collider)
				{
					if (hit.collider.tag != tagProv) go = 0;
					tagProv = hit.collider.tag;

					switch (hit.collider.tag)  // 根据地面的标签选择对应的声音类型
					{
						case "Metal":
							PlayRandomSound(clipsMetal);  // 播放金属声音
							break;
						case "Tree":
							PlayRandomSound(clipsTree);  // 播放树木声音
							break;
						case "Grass":
							PlayRandomSound(clipsGrass);  // 播放草地声音
							break;
						case "Dirt":
							PlayRandomSound(clipsDirt);  // 播放土地声音
							break;
						case "Water":
							PlayRandomSound(clipsWater);  // 播放水声音
							break;
						default:
							StopSound();  // 停止播放声音
							break;
					}
				}
			}
		}
		else
		{
			StopSound();  // 停止播放声音
		}
	}

	// 从给定的声音剪辑数组中随机播放一个声音
	void PlayRandomSound(AudioClip[] clips)
	{
		if (go == 0)  // 如果需要重新设置音频剪辑
		{
			AS.clip = null;
			go = 1;
		}
		if (!AS.isPlaying)  // 如果当前没有正在播放的声音
		{
			// AS.clip = clips[Random.Range(0, clips.Length)];  // 随机选择一个声音剪辑
			int randomIndex = GetUniqueRandomIndex(clips.Length);  // 获取一个未播放过的随机索引
			AS.clip = clips[randomIndex];  // 根据索引选择一个声音剪辑
			AS.Play();  // 播放声音
		}
	}

	// 获取一个未播放过的随机索引
	int GetUniqueRandomIndex(int arrayLength)
	{
		int randomIndex;
		do
		{
			randomIndex = Random.Range(0, arrayLength);  // 生成一个随机索引
		} while (playedIndexes.Contains(randomIndex));  // 循环判断该索引是否已经播放过

		playedIndexes.Add(randomIndex);  // 将新的索引添加到已播放列表中
		if (playedIndexes.Count >= arrayLength)
		{
			playedIndexes.Clear();  // 如果已播放列表包含所有索引,则清空列表,重新开始播放
		}

		return randomIndex;
	}

	// 停止播放声音并重置go变量
	void StopSound()
	{
		AS.clip = null;  // 清空音频剪辑
		AS.Stop();  // 停止播放声音
		go = 0;  // 重置go变量
	}
}

解释:
go 的这个逻辑保证了只有在需要重新设置音频剪辑时才会执行,避免了声音的混叠和中断。如果去除这个逻辑,可能会导致声音播放不正常。

AS.pitch是用来控制音频的音调(pitch)的属性。音调指的是声音的高低,可以用数字表示,其中1.0表示原始音调,小于1.0表示降低音调,大于1.0表示提高音调。
通过改变音调,可以实现音频的加速或减速播放。较高的音调会使音频听起来更快,而较低的音调则会使音频听起来更慢。

大致参数配置
在这里插入图片描述

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1403769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

命令模式介绍

目录 一、命令模式介绍 1.1 命令模式定义 1.2 命令模式原理 1.2.1 命令模式类图 1.2.2 模式角色说明 二、命令模式的应用 2.1 需求说明 2.2 需求实现 2.2.1 抽象命令接口 2.2.2 订单类 2.2.3 厨师类 2.2.4 服务员类 2.2.5 具体命令类 2.2.6 测试类 三、命令模式总…

Ubuntu20.04输入法异常导致的黑屏:fcitx和ibus输入法的卸载与安装

Ubuntu20.04输入法异常导致的黑屏&#xff1a;fcitx和ibus输入法的卸载与安装_ubuntu卸载fcitx-CSDN博客 问题背景 系统&#xff1a;Ubuntu20.04 由于fcitx的不完整配置&#xff0c;导致fcitx输入法无法正常工作。决心卸载所有输入法&#xff0c;重新安装。但是由于在没有完整…

C#使用DateAndTime.DateDiff方法计算年龄

目录 一、计算年龄的方法 二、 DateAndTime类 1.定义 2.常用方法 3.DateDiff(DateInterval, DateTime, DateTime, FirstDayOfWeek, FirstWeekOfYear) 三、使用DateAndTime.DateDiff方法计算年龄 一、计算年龄的方法 使用DateDiff方法计算系统时间与员工生日之间相隔的年…

python-自动篇-办公-用Excel画画

文章目录 代码所遇问题ModuleNotFoundError: No module named xlsxwriterFileNotFoundError: [Errno 2] No such file or directory: 111.jpg 效果附件图片excel 代码 # coding: utf-8from PIL import Image from xlsxwriter.workbook import Workbookclass ExcelPicture(obje…

linux性能优化-磁盘I_O优化

1.文件系统 1.1.文件系统的工作原理 文件系统是在磁盘的基础上&#xff0c;提供了一个用来管理文件的树状结构。 接下来我们就看看Linux 文件系统的工作原理。 1.1.1索引节点和目录项 在 Linux 中一切皆文件 ,文件系统,本身是对存储设备上的文件&#xff0c;进行组织管理的…

TDSQL-PG高可用原理与方案设计

笔记主要是把架构具像化到机架图上。 TDSQL-PG的高可用方案主要通过每个部件的多副本冗余来实现&#xff0c;当一个部件的主部件出现故障不可恢复&#xff0c;系统将会自动重新选出对应的备份部件取代原来的主部件。而强同步复制是在节点级保证每个节点的主从数据完全一致&…

Facebook的区块链之路:探秘数字货币的未来

近年来&#xff0c;Facebook一直在积极探索区块链技术&#xff0c;并逐渐将目光聚焦在数字货币领域。从推出Libra项目到改名为Diem&#xff0c;Facebook一直在寻求在数字货币领域取得突破性进展。本文将深入探讨Facebook的区块链之路&#xff0c;揭示其对数字货币未来发展的影响…

Web开发:新建一个WebAPI的demo

一、新建一个api项目&#xff0c;并设置为启动项目 二、控制器目录新建一个控制器&#xff0c;命名为TestController&#xff0c;并且添加如下代码 添加后 代码&#xff1a; using Microsoft.AspNetCore.Mvc;namespace WebApplication1.Controllers {public class TestControl…

【Electron】Electron是什么

1. Electron是什么 Electron是使用JavaScript、HTML和CSS构建跨平台&#xff08;Windows、MacOs、Linux&#xff09;的桌面应用。Electron其实就是一个可以展示网页内容的壳子&#xff0c;相当于一个独立的浏览器&#xff0c;可以提供给你一些接口&#xff0c;去调用系统的资源…

电脑 wifi 常断

问题 电脑wifi网络经常断。 详细问题 笔者使用笔记本电脑&#xff0c;发现每过三五分钟&#xff0c;wifi便会自动断开。 解决方案 步骤1、搜索框搜索设备管理器。 步骤2、找到网络适配器并点击。 步骤2、找到网络适配器菜单中的Wireless相关内容&#xff0c;右键&#x…

超优秀的三维模型轻量化、格式转换、可视化部署平台!

1、基于 HTML5 和 WebGL 技术&#xff0c;可在主流浏览器上进行快速浏览和调试&#xff0c;支持PC端和移动端 2、自主研发 AMRT 展示框架和9大核心技术&#xff0c;支持3D模型全网多端流畅展示与交互 3、提供格式转换、减面展UV、烘焙等多项单模型和倾斜摄影模型轻量化服务 4、…

计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

从 Vscode 中远程连接 WSL 服务器:可以本地操作虚拟机

从 Vscode 中远程连接 WSL 服务器&#xff1a;可以本地操作虚拟机 1.下载 Vscode Visual Studio Code - Code Editing. Redefined 2.搜索框中输入>wsl&#xff0c;点击 WSL&#xff1a;Connect to WSL using Distro... 3.点击下载好的Ubuntu&#xff0c;当左下角出现图片同…

Maven《四》-- 基于Idea进行Maven工程构建

目录 &#x1f436;4.1 构建概念和构建过程 &#x1f436;4.2 命令方式项目构建 1. &#x1f959;编译&#xff1a;mvn compile 2. &#x1f959;清理&#xff1a;mvn clean 3. &#x1f959;打包&#xff1a;mvn package 4. &#x1f959;安装&#xff1a;mvn install …

51单片机1-6

目录 单片机介绍 点亮一个LED 流水灯参考代码 点亮流水LEDplus版本 独立按键 独立按键控制LED亮灭 静态数码管 静态数码管显示 动态数码管显示 模块化编程 调试工具 矩阵键盘 矩阵键盘显示数据 矩阵键盘密码锁 学习B站江协科技课程笔记。 安装keil&#xff0c;下…

dubbo:深入理解Apache Dubbo与实战

dubbo核心组件 层次名 作 用 Service 业务层。包括业务代码的接口与实现&#xff0c;即开发者实现的业务代码 config 配置层。主要围绕ServiceConfig &#xff08;暴露的服务配置&#xff09;和ReferenceConfig &#xff08;引用的服务配置&#xff09;两个实现类展开&#xf…

NetSuite 文心一言(Ernie)的AI应用

有个故事&#xff0c;松下幸之助小时候所处的年代是明治维新之后&#xff0c;大量引用西洋技术的时期。当时大家对“电”能干什么事&#xff0c;充满好奇。“电能干什么&#xff1f;它能帮我们开门么&#xff1f;” 松下幸之助的爷爷对电不屑&#xff0c;于是就问他。松下幸之助…

ORBSLAM3安装

0. C11 or C0x Compiler sudo apt-get install gccsudo apt-get install gsudo apt-get install build-essentialsudo apt-get install cmake1. 依赖 在该目录终端。 1. 1.Pangolin git clone https://github.com/stevenlovegrove/Pangolin.git sudo apt install libglew-d…

Java实现超市账单管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统设计3.1 总体设计3.2 前端设计3.3 后端设计在这里插入图片描述 四、系统展示五、核心代码5.1 查询供应商5.2 查询商品5.3 新增超市账单5.4 编辑超市账单5.5 查询超市账单 六、免责说明 一、摘要 1.1 项目介绍 基于…

1、Seaborn可视化库

你的数据可视化编程初体验! Seaborn是一个基于matplotlib的图形可视化Python库,它提供了一种高级的API接口,使得制作统计图形更加容易。 Seaborn的目标是使可视化成为探索和理解数据的核心部分,它面向数据集的绘图功能对整个数据集进行操作,并在内部执行必要的语义映射和统…