【制作100个unity游戏之23】实现类似七日杀、森林一样的生存游戏16(附项目源码)

本节最终效果演示

【独游开发记录】一个人开发的,类森林,七日杀生存游戏


文章目录

  • 本节最终效果演示
  • 系列目录
  • 前言
  • 泛型单例
  • 添加声音
    • 脚步声
    • 鸭子动物音效
    • 人物各种操作音效
    • 砍树音效
  • 效果
  • 源码
  • 完结

系列目录

前言

欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第23篇中,我们将探索如何制作一个类似于七日杀和森林的生存游戏。

本篇内容会比较多,我会分几篇来实现,感兴趣的可以关注一下,以免错过内容更新。

本节主要引入泛型单例和添加各种游戏音效。

泛型单例

随着脚本越来越多,重复配置单例无疑是相对麻烦的,这里写一个通用的泛型单例脚本,节约时间,优化带

//简单的泛型单例
public class Singleton<T> : MonoBehaviour where T : Component
{private static T instance;public static T Instance{get{if (instance == null){instance = FindObjectOfType<T>();if (instance == null){GameObject newInstance = new GameObject();instance = newInstance.AddComponent<T>();}}return instance;}}public void Awake(){instance = this as T;}
}

使用参考

public class AudioManager : Singleton<AudioManager> {}

添加声音

声音就大家自行去找了,网上都挺多的

脚步声

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

获取人物移动状态,修改PlayerState

[Header("判断人物状态")]
public bool isMove;//是否在移动
public bool isWalking;//是否正在行走
public bool isRuning; //是否正在奔跑
public bool isCrouching; //是否正在下蹲//。。。private void Update()
{isMove = MovementScript.Instance.isGround && MovementScript.Instance.moveDirection.sqrMagnitude > 0;isRuning = MovementScript.Instance.isRun && isMove;isCrouching = MovementScript.Instance.isCrouching;isWalking = !isRuning && !isCrouching && isMove;//。。。
}

脚步声控制

//脚步声
public class FootStepSound : MonoBehaviour
{public LayerMask layerMask; // 检测层级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;  // 声音源组件//该属性控制音频的播放速度,1.0 表示正常速度,小于 1.0 表示慢速播放,大于 1.0 表示快速播放。public float PitchRun, PitchWalk, PitchCrouch;// 创建一个列表用于存储之前选择过的音效索引private List<int> playedIndexes = new List<int>();//判断child是否是parent的子集bool IsChildOf(Transform child, Transform parent){while (child != null){if (child == parent){return true;}child = child.parent;}return false;}void Update(){if (PlayerState.Instance.isRuning)AS.pitch = PitchRun;  //则设置为奔跑音调else if(PlayerState.Instance.isWalking){AS.pitch = PitchWalk;}else{AS.pitch = PitchCrouch;}if (PlayerState.Instance.isMove){if (Physics.Raycast(RayGo.transform.position, Vector3.down, out hit, dist, layerMask))  // 向下发射射线检测地面{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.Stop();  // 停止播放声音go = 0;  // 重置go变量}
}

配置地面层级和标签,目前先只有一个地面Grass
在这里插入图片描述

配置代码
在这里插入图片描述

鸭子动物音效

本来打算开启直接播放音效的,但是声音太过密集了,所以这里用修改代码随机播放声音

配置因为鸭子的声音是3D的,所以需要修改AudioSource配置
在这里插入图片描述

代码随机默认声音,修改AI_Movement

[Header("声音")]
public AudioSource callAudioSource;void Start()
{//。。。StartCoroutine(PlaySound());
}IEnumerator PlaySound()
{while (true){yield return new WaitForSeconds(Random.Range(3, 10));callAudioSource.Play();}
}

配置
在这里插入图片描述

人物各种操作音效

可以看看之前这篇文章:【unity小技巧】Unity音乐和音效管理器

public class AudioManager : Singleton<AudioManager>
{//定义音乐和音效的Sound数组public Sound[] musicSounds, sfxSounds;//音乐和音效的AudioSourcepublic AudioSource musicSource, sfxSource;private void Start() {PlayMusic("森林环境");}//播放音乐的方法,参数为音乐名称public void PlayMusic(string name) {//从音乐Sounds数组中找到名字匹配的Sound对象Sound s = Array.Find(musicSounds, x => x.name == name);//如果找不到对应的Sound,输出错误信息if (s == null) {Debug.Log("没有找到音乐");}//否则将音乐源的clip设置为对应Sound的clip并播放else {musicSource.clip = s.clip;musicSource.Play();}}//播放音效的方法,参数为音效名称public void PlaySFX(string name) {//从音效Sounds数组中找到名字匹配的Sound对象Sound s = Array.Find(sfxSounds, x => x.name == name);//如果找不到对应的Sound,输出错误信息if (s == null) {Debug.Log("没有找到音效");}//否则播放对应Sound的clipelse {sfxSource.PlayOneShot(s.clip);}}
}

配置参数
在这里插入图片描述
调用案例

AudioManager.Instance.PlaySFX("制作");

砍树音效

新增TreeSound,控制树声

//树声控制
public class TreeSound : MonoBehaviour
{[SerializeField] private AudioClip[] hitSounds; // 击中树声音数组[SerializeField] private AudioClip fallSound; // 倒下声音private AudioSource audioSource;private void Start(){audioSource = GetComponent<AudioSource>();}//击中树声音public void PlayHitAudio(){int n = UnityEngine.Random.Range(1, hitSounds.Length);audioSource.clip = hitSounds[n]; // 随机选择一个声音audioSource.PlayOneShot(audioSource.clip);//播放过的脚步声放置第一位,避免连续播放相同的脚步声hitSounds[n] = hitSounds[0];hitSounds[0] = audioSource.clip;}//倒下声音public void PlayFallAudio(){audioSource.clip = fallSound;audioSource.Play();}
}

挂载在树预制体上
在这里插入图片描述

修改ChoppableTree,调用

private TreeSound treeSound;treeSound = GetComponent<TreeSound>();treeSound.PlayHitAudio();treeSound.PlayFallAudio();

效果

【独游开发记录】一个人开发的,类森林,七日杀生存游戏

源码

源码不出意外的话我会放在最后一节

完结

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

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

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

在这里插入图片描述

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

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

相关文章

[经验] 喉咙沙哑的原因及应对方法是什么 #学习方法#其他#媒体

喉咙沙哑的原因及应对方法是什么 生活中&#xff0c;喉咙不舒服是很常见的情况&#xff0c;尤其是喉咙沙哑&#xff0c;让人感到特别难受&#xff0c;影响睡眠和生活质量。那么喉咙沙哑怎么办呢&#xff1f;接下来我会分享一些简单易行的方法&#xff0c;帮助你缓解这种不适感…

政安晨:示例演绎机器学习中(深度学习)神经网络的数学基础——快速理解核心概念(一){两篇文章讲清楚}

进入人工智能领域免不了与算法打交道&#xff0c;算法依托数学基础&#xff0c;很多小伙伴可能新生畏惧&#xff0c;不用怕&#xff0c;算法没那么难&#xff0c;也没那么玄乎&#xff0c;未来人工智能时代说不得人人都要了解算法、应用算法。 本文试图以一篇文章&#xff0c;…

《CSS 简易速速上手小册》第2章:CSS 布局与定位(2024 最新版)

文章目录 2.1 Flexbox&#xff1a;灵活的布局解决方案2.1.1 基础知识2.1.2 重点案例&#xff1a;创建一个响应式导航菜单2.1.3 拓展案例 1&#xff1a;卡片布局2.1.4 拓展案例 2&#xff1a;中心对齐的登录表单 2.2 Grid 布局&#xff1a;网格系统的魔力2.2.1 基础知识2.2.2 重…

数字孪生:构建未来智慧社区的关键技术

随着科技的快速发展&#xff0c;数字孪生技术作为构建未来智慧社区的关键技术&#xff0c;正逐渐受到广泛关注。数字孪生技术能够实现物理世界与数字世界的交互映射&#xff0c;为智慧社区的建设提供强有力的支持。本文将探讨数字孪生技术在构建未来智慧社区中的作用和意义&…

枚举(Java)

一、概念 枚举是一种特殊的类。 格式&#xff1a; 修饰符 enum 枚举类名{ 对象名称1&#xff0c;对象名称2&#xff0c;....; 其他成员... } 二、枚举类的特点 1.枚举类的第一行只能罗列一些名称&#xff0c;并且这些名称都是常量&#xff0c;每个常量记住一个枚举类对象…

vue3 之 Pinia数据持久化

持久化用户数据说明 1️⃣用户数据中有一个关键的数据叫做token&#xff08;用来标识当前用户是否登陆&#xff09;&#xff0c;而token持续一段时间才会过期 2️⃣Pinia的存储是基于内存&#xff0c;刷新就丢失&#xff0c;为了保持登陆状态就要做到刷新不丢失&#xff0c;需要…

【芯片设计- RTL 数字逻辑设计入门 番外篇 9 -- SOC 中PL端与PS端详细介绍】

文章目录 Programmable Logic and Processing SystemPL&#xff08;Programmable Logic&#xff09;特点PS和PL之间的协同设计和开发工具 Programmable Logic and Processing System 在系统级芯片&#xff08;SoC&#xff09;的上下文中&#xff0c;“PL” 通常指的是可编程逻…

Qt可视化大屏布局

科技大屏现在非常流行&#xff0c;这里分享一下某个项目的大屏布局&#xff08;忘了源码是哪个博主的了&#xff09; 展示 这个界面整体是垂直布局&#xff0c;分为两个部分&#xff0c;标题是一个部分&#xff0c;然后下面的整体是一个layout布局&#xff0c;为另外一部分。 l…

学习Android的第五天

目录 Android ConstraintLayout 约束布局 简介 ConstraintLayout 约束布局分类 1、相对定位 (Relative positioning) 2、边距 ( Margins ) 3、居中定位和偏向 ( Centering positioning and bias ) 4、环形定位 ( Circular positioning ) 5、对可见性的处理 ( Visibilit…

利用知识图谱构建医疗问答

1、准备数据集 数据集下载地址&#xff1a;https://github.com/wangle1218/QASystemOnMedicalKG/blob/master/data/medical.json 2、导入相关包 from py2neo import Graph,Node,Relationship # 在cmd中&#xff0c;输入neo4j.bat console并回车 import pandas as pd3、连接N…

Rust基础拾遗--核心功能

Rust基础拾遗 前言1.所有权与移动1.1 所有权 2.引用3.特型与泛型4.实用工具特型5.闭包 前言 通过Rust程序设计-第二版笔记的形式对Rust相关重点知识进行汇总&#xff0c;读者通读此系列文章就可以轻松的把该语言基础捡起来。 1.所有权与移动 谈及内存管理&#xff0c;我们希望…

力扣hot100 -- 双指针

目录 &#x1f382;移动零 &#x1f319;盛最多水的容器 &#x1f33c;三数之和 &#x1f33c;接雨水 前缀和 辅助数组 双指针 单调栈 &#x1f382;移动零 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 关于swap #include <iostream> #include <vec…

[SAP] ABAP设置非系统关键字代码提示功能

在事务码SE38(ABAP编辑器)屏幕右下角&#xff0c;点击【Options选项】图标 勾选【代码完成】|【建议文本中的非关键字】&#xff0c;并点击【保存】按钮 在下面的程序代码中&#xff0c;当我需要输入在11行的位置输入非关键字lv_str的时候&#xff0c;会有非关键字代码提示的功…

STM32 cubemx配置DMA+空闲中断接收不定长数据

文章目录 前言一、串口空闲中断二、DMA空闲中断接收不定长数据实现思路三、STM32Cubemx配置DMA空闲中断接收不定长数据四、代码编写总结 前言 本篇文章给大家讲解一下DMA串口空闲中断接收串口不定长数据&#xff0c;之前我们也是讲解过串口接收不定长数据的&#xff0c;那么本…

从Socket中解析Http协议实现通信

在网络协议中&#xff0c;Socket是连接应用层和运输层的中间层&#xff0c;主要作用为了通信。Http协议是应用层上的封装协议。我们可以通过Http协议的规范解析Socket中数据&#xff0c;完成Http通信。 首先&#xff0c;我们先回顾一下Http协议的规范。主要复习一下&#xff0c…

“OLED屏幕,色彩绚丽,画面清晰,让每一帧都生动无比。“#IIC协议【下】

"OLED屏幕&#xff0c;色彩绚丽&#xff0c;画面清晰&#xff0c;让每一帧都生动无比。"#IIC协议【下】 前言预备知识1. OLED显示一个点代码实现1.1 OLED显示一个点代码实现核心思路1.2和LCD1602一样需要初始化&#xff0c;看手册&#xff0c;写初识化函数1.3选择Pag…

知到答案在哪搜? #微信#笔记#其他

学习工具是我们的得力助手&#xff0c;帮助我们更好地组织学习内容和时间。 1.试题猪 这是一个公众号 总体来说还是很不错的&#xff0c;题库虽然不是特别全&#xff0c;但是大部分网课答案能够查询到&#xff0c;最重要的是免费的 下方附上一些测试的试题及答案 1、实验室…

C语言函数的栈帧与销毁(面试亮点)

目录 如果你能熟练的掌握函数的栈帧与销毁在面试中是及其亮眼的加分项&#xff0c;所以我们来以实例来将解函数是如何实现栈帧与销毁的。 一. 函数栈帧 二.寄存器 三. 用例题讲解创建栈帧的过程 3.1 main 函数的反汇编代码。 第一步&#xff1a;给调用main函数的函数分配…

STL之list容器的介绍与模拟实现+适配器

STL之list容器的介绍与模拟实现适配器 1. list的介绍2. list容器的使用2.1 list的定义2.2 list iterator的使用2.3 list capacity2.4 list element access2.5 list modifiers2.6 list的迭代器失效 3. list的模拟实现3.1 架构搭建3.2 迭代器3.2.1 正向迭代器3.2.2反向迭代器适配…

大脑是宇宙中最复杂的物体——科学家们试图破译它,读懂人们的思想

2023年&#xff0c;德克萨斯大学HuthLab进行的一项研究在神经科学和技术领域引发了震动。通过人工智能(AI)和脑成像技术的结合&#xff0c;无法与外界交流的人的思想首次被翻译成连续的自然语言。 这是迄今为止最接近读心术的科学方法。在过去的二十年里&#xff0c;神经成像技…