👨💻个人主页:@元宇宙-秩沅
👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 秩沅 原创
👨💻 收录于专栏:Unity基础实战
⭐🅰️⭐
文章目录
- ⭐🅰️⭐
- ⭐让音符踩着音乐节奏被我们击打⭐
- 🎶(==1==) 音符对象池的介绍
- 🎶(==2==) 音符对象池的创建
- 🎶(==3==) 音符对象的位置的创建
- 🎶(==4==) 音符对象的精灵的赋值
- 🎶(==5==) 音符对象的在轨道的初步运行
- 🎶(==6==) 音符特效的制作
- 🎶(==7==) 音符预制体的逻辑
- ⭐🅰️⭐
⭐让音符踩着音乐节奏被我们击打⭐
🎶(1) 音符对象池的介绍
在Unity中,对象池是一种常用的设计模式,它的思想是提前创建一些对象并保存起来,当需要使用这些对象时,直接从对象池中取出,使用完毕后再放回对象池,而不是频繁地创建和销毁对象。
对象池在游戏中的应用非常广泛,特别是在需要频繁创建和销毁对象的情况下,使用对象池可以显著减少性能开销,提高游戏的性能和流畅度。
在Unity中,可以通过以下步骤实现对象池的思想:
-
- 创建一个对象池类,该类负责创建和管理对象池。可以使用List或Queue等数据结构来保存对象池中的对象。对象池类应该具有创建对象、获取对象和回收对象的方法。
-
- 在对象池类中,使用Unity的Instantiate方法来创建一定数量的对象,并将这些对象保存到对象池中。
-
- 在需要使用对象的地方,通过对象池类的获取对象方法获取对象。如果对象池中没有可用的对象,则可以选择创建新的对象或者等待对象池中有可用对象为止。
-
- 使用完对象后,将对象通过对象池类的回收对象方法放回对象池中,以便重复使用。
使用对象池可以避免频繁地创建和销毁对象,减少内存的分配和释放,提高游戏的性能。同时,对象池还可以控制对象的数量,防止过多的对象创建导致内存溢出。
🎶(2) 音符对象池的创建
//音符块对象池(栈)声明
private Stack<NoteObject> noteObjectsPool = new Stack<NoteObject>();
//从对象池中取音符对象
public NoteObject GetNotePooling()
{
NoteObject note;
if (noteObjectsPool.Count > 0)
{
note = noteObjectsPool.Pop(); //出栈
}
else
{
note = Instantiate(noteObject);//实例化音符预制体
}
//上保险(保证note自身 和其组件都为激活状态)
note.gameObject.SetActive(true);
note.enabled = true;
return note;
}
//将音符对象放入对象池
public void ReturnNotePooling(NoteObject note)
{
if(note != null )
{
note.enabled = false;
note.gameObject.SetActive(false);
noteObjectsPool.Push(note); //压栈
}
}
🎶(3) 音符对象的位置的创建
构建音符的上下界(产生和消失的位置)
🎶(4) 音符对象的精灵的赋值
🎶(5) 音符对象的在轨道的初步运行
- NoteObject (音符脚本)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SonicBloom.Koreo;
//-------------------------------
//-------功能: 音符脚本
//-------创建者: -------
//------------------------------
public class NoteObject : MonoBehaviour
{
//精灵渲染变量
public SpriteRenderer spriteRenderer;
//所有精灵图集数组
public Sprite[] noteSprites;
//对应的音乐插件事件
KoreographyEvent trackedEvent;
//是否是长音符
public bool isLongNote;
//是否是长音符的结尾
public bool isLongNoteEnd;
//音轨管理器脚本
STrackContorller strackController;
//游戏管理器脚本
RythmGameContorller gameController;
public int hitOffset;
void Start()
{
}
void Update()
{
//一直更新音符的位置
UpdatePosition();
}
/// <summary>
/// 初始化音符的方法
/// </summary>
/// <param name="evt">音符插件中的事件类</param>
/// <param name="noteNum">当前音符的索引</param>
/// <param name="STackIndex">当前所在的音轨脚本</param>
/// <param name="gameContorl">游戏管理器脚本</param>
/// <param name="isLongNoteStart">是否是长音符的开始</param>
/// <param name="isLongNoteEnd">是否是长音符的结尾</param>
public void Initialize(KoreographyEvent evt ,int noteIndex ,STrackContorller sTrackController,
RythmGameContorller gameContorl ,bool isLongNoteStart ,bool isLongNoteEnd)
{
//初始化
trackedEvent = evt;
strackController = sTrackController;
gameController = gameContorl;
isLongNote = isLongNoteStart;
isLongNoteEnd = isLongNoteEnd;
int spriteIndex= noteIndex;
//精灵图集一共有18个前6个是短音符,中间6个是长音符,后面6个是长音符结尾
if (isLongNote)
{
spriteIndex += 6;
}
else if (isLongNoteEnd)
{
spriteIndex += 12;
}
//精灵图的索引是从0开始的
try
{
spriteRenderer.sprite = noteSprites[spriteIndex - 1];
}
catch
{
Debug.Log(spriteIndex);
}
}
//音符Note对象返回对象池,需要重置
public void ResetNote()
{
//讲两个控制者和自身的轨道事件置空即可
trackedEvent = null;
strackController = null;
gameController = null;
}
//音符返回对象池
private void ReturnPool()
{
//调用游戏管理器脚本呢中的入池方法
gameController.ReturnNotePooling(this);
//重置Note对象
ResetNote();
}
//击中音符也返回对象池
public void OnHit()
{
ReturnPool();
}
//更新音符位置的方法
private void UpdatePosition()
{
Vector3 position = strackController.TargetPosition;
//-= (样本点的位置差值) / 采样率 <等于时间> * 字符速度
position.z -= (gameController.DelayedSampingTime - trackedEvent.StartSample) / (float)gameController .SamplingRate *gameController .noteSpeed ;
transform.position = position;
}
}
🎶(6) 音符特效的制作
- 击打特效
- 按下特效
- “”
🎶(7) 音符预制体的逻辑
- 于音轨管理器脚本中创建(STrackContorller)
#region 特效预制体的创建
//创建按下特效预制体
private void CreateDownEffect()
{
//获取RythmGameControl脚本中 获取特效对象的方法(按下特效)
GameObject downEffectGo = gameContorller.GetEffectObject(gameContorller.downEffectPool, gameContorller.downEffect);
//该特效出生的地点 = 目标位置
downEffectGo.transform.position = targetEffectPosition.position;
}
//创建击打特效预制体
private void CreateHitEffect()
{
//获取RythmGameControl脚本中 获取特效对象的方法(击中特效)
GameObject hitEffectGo = gameContorller.GetEffectObject(gameContorller.downEffectPool , gameContorller.hitEffect);
//该特效出生的地点 = 目标位置
hitEffectGo.transform.position = targetEffectPosition.position;
}
//创建击长击打特效预制体
private void CreateHitLongEffect()
{
//获取RythmGameControl脚本中 获取特效对象的方法(击中特效)
GameObject hitEffectGo = gameContorller.GetEffectObject(gameContorller.longEffectPool, gameContorller.longHitEffect);
//该特效出生的地点 = 目标位置
hitEffectGo.transform.position = targetEffectPosition.position;
}
#endregion
⭐🅰️⭐
⭐【Unityc#专题篇】之c#进阶篇】
⭐【Unityc#专题篇】之c#核心篇】
⭐【Unityc#专题篇】之c#基础篇】
⭐【Unity-c#专题篇】之c#入门篇】
⭐【Unityc#专题篇】—进阶章题单实践练习
⭐【Unityc#专题篇】—基础章题单实践练习
⭐【Unityc#专题篇】—核心章题单实践练习
你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!、