本节最终效果演示
【独游开发记录】一个人开发的,类森林,七日杀生存游戏
文章目录
- 本节最终效果演示
- 系列目录
- 前言
- 泛型单例
- 添加声音
- 脚步声
- 鸭子动物音效
- 人物各种操作音效
- 砍树音效
- 效果
- 源码
- 完结
系列目录
前言
欢迎来到【制作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是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~