目录
效果展示
实现思路
残影代码
对象池代码
控制冲刺产生残影
CD冷却图标
效果展示
实现思路
对象池,有想要用的物体时可以从池子里取,用完再放回去。
因为在生成残影再销毁,这个过程中创建和销毁都需要耗费大量资源,因此尽量避免这样的浪费资源。
实现残影的思路如下:其实很简单
当人物按下冲刺键时,让此时人物突然加速,在加速的过程中并且每隔X帧就生成一个sprite,这个sprite的图像、位置、旋转角度和当前玩家所处位置一样,这样就相当于一个影分身。
在冲刺的过程中就会留下分身,然后让这些生成的分身在隔一段时间后自动销毁即可。
那使用对象池的思路用图来表示如下:
当需要使用残影时,便从对象池中取出,然后将该物体的位置设定为玩家当前位置,当时间到后自动将该物体放回池中。
具体代码如下:
残影代码
先写残影预制体的代码,它包含如下功能:
当它被启用时,设定它的位置为玩家的位置,并且过了一段时间后会消失,就是将其返回对象池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GhostImage : MonoBehaviour
{
[Header("残影参数")]
SpriteRenderer thisSprite;
SpriteRenderer playerSprite;
GameObject player;
Color spriteColor;
float alpha=1;
float startAlpha;
float alphaMultiplyRation = 0.9f;
[SerializeField] public float activeTime=0.5f;//残影所持续的时间
float startTime;
//事实上,由于其是单例模式,无需用代码去unity中搜寻该物体,就可以直接从该脚本.instance的方式获取该物体
//GhostImagePool poolInstance;
private void OnEnable()
{
player = GameObject.FindGameObjectWithTag("Player");
playerSprite = player.GetComponent<SpriteRenderer>();
thisSprite = GetComponent<SpriteRenderer>();
thisSprite.sprite = playerSprite.sprite;
transform.position = player.transform.position;
transform.rotation = player.transform.rotation;
transform.localScale = player.transform.localScale;
startTime = Time.time;
}
private void Update()
{
ImageDisappear();
}
void ImageDisappear()
{
thisSprite.color = new Color(0.5f, 0.5f, 1f, alpha*alphaMultiplyRation);
if (Time.time > startTime + activeTime)
{
GhostImagePool.instance.ReturnPool(this.gameObject);
}
}
}
该物体被激活后,在该物体的OnEnable函数中会自动设定该物体的位置。时间一到后该物体会自动将自己放回对象池。
对象池代码
对象池的代码如下:
为了场景中只有一个残影对象池,我们使用单例模式
其包含几个功能,
接收与存储对象的方式通过Queue<GameObject>来存储
1.初始时便生成残影预制体并作为该对象池的子物体
2.某个对象不用时,对象池可以接受该物体。(将该对象加入Queue,并取消激活,即setActive(false)
3.需要使用物体时,便从该对象池中取出物体(通过在Queue中取,并激活,即setActive(true)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GhostImagePool : MonoBehaviour
{
public static GhostImagePool instance;
int ghostImageGroupCount = 10;//对象池中的影子不够用时会多生成一组影子,这是一组影子的数量
public GameObject ghostImagePrefab;
void Awake()
{
instance = this;
}
Queue<GameObject> pool=new Queue<GameObject>();
private void Start()
{
FillPool();
}
void Update()
{
}
void FillPool()
{
for(int i = 0; i < ghostImageGroupCount; i++)
{
var ghostImage = Instantiate(ghostImagePrefab, transform);
ReturnPool(ghostImage);
}
}
public void ReturnPool(GameObject ghostImage)
{
pool.Enqueue(ghostImage);
ghostImage.SetActive(false);
}
public GameObject GetGhostImageFromPool()
{
if(pool.Count <= 0)
{
FillPool();
}
GameObject ghostImage= pool.Dequeue();
ghostImage.SetActive(true);
return ghostImage;
}
}
控制冲刺产生残影
然后在playerController中加入以下代码:
注意人物使用技能是有CD的
通过冲刺时来激活对象池中的物体,
#region 冲刺及残影
[Header("残影参数")]
[SerializeField] public float dashContinueTime=0.5f;//冲刺持续时间
[SerializeField] public float dashCD=2f;//冲刺技能的CD
[SerializeField] public float dashSpeed=30;//冲刺的速度
public Image CDImage;
float dashLeftTime;//剩余可以用来冲刺的时间,初始为其赋值后让时间不断减少
float lastDashTime=-10f;//上次冲刺的时间,用于设定cd(初始设定为负值是为了初始时也能调用)
public bool isDashing = false;
void CheckIfCanDash()
{
CDImage.fillAmount -= 1.0f / dashCD * Time.deltaTime;//实现CDImage自动减少的情况
if (Time.time > lastDashTime + dashCD)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
isDashing = true;
lastDashTime = Time.time;
dashLeftTime = dashContinueTime;
CDImage.fillAmount = 1;//使用技能时开始计算冷却,将图标设为满填充,当图标减少时代表cd正在减少
}
}
}
void Dashing()
{
if (isDashing)
{
if(transform.localScale.x==-1)
rigidBody.velocity = new Vector2(dashSpeed, rigidBody.velocity.y);
else if (transform.localScale.x == 1)
rigidBody.velocity = new Vector2(-dashSpeed, rigidBody.velocity.y);
dashLeftTime -= Time.deltaTime;
if(dashLeftTime <= 0)
{
isDashing = false;
}
GhostImagePool.instance.GetGhostImageFromPool();
}
}
#endregion
其中CheckIfCanDash()和Dashing()函数在update中调用
CD冷却图标
实现CD图标旋转
在unity中FillAmount自动代表了填充效果,我们只需要在代码中随着时间流动调整这个填充的FillAmount即可
开始使用技能时设定CD图标的填充为1,
之后让其随时间自动削减。按照如下的公式即可
dashCD即为技能冷却CD
完整如下