Unity实现残影效果
1、效果展示
2、场景搭建
3、代码
1、PlayerMovement.cs:挂载在角色身上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("人物移动速度")]
public float moveSpeed = 5;
private Rigidbody2D rb;
private Vector2 moveDir;
private Animator anim;
[Header("冲锋时长")]
public float dashTime = 0.5f;//冲锋时长
private float dashTimeLeft;//冲锋剩余时间
[Header("冲锋时的速度")]
public float dashSpeed = 10;//冲锋时的速度
[Header("冲锋冷却时间")]
public float dashCoolDown = 1;//冲锋冷却时间
private float lastDash = -10;
private bool isDashing;//是否冲锋
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
InputManagement();
if (Input.GetKeyDown(KeyCode.J))
{
if (Time.time >= (lastDash + dashCoolDown))
{
ReadyToDash();
}
}
}
private void FixedUpdate()
{
Dash();
if (isDashing)
{
return;
}
Move();
}
private void InputManagement()
{
float moveX = Input.GetAxisRaw("Horizontal");
moveDir = new Vector2(moveX, 0f);
if (moveDir.x != 0)
{
anim.SetBool("Run", true);
SpriteDirectionChecker();
}
else
{
anim.SetBool("Run", false);
}
}
private void Move()//人物移动
{
rb.velocity = new Vector2(moveDir.x * moveSpeed, 0f);
}
private void SpriteDirectionChecker()//人物转向
{
if (moveDir.x < 0)
{
transform.localScale = new Vector3(-1, 1, 1);
}
else
{
transform.localScale = new Vector3(1, 1, 1);
}
}
private void ReadyToDash()
{
isDashing = true;
dashTimeLeft = dashTime;
lastDash = Time.time;
}
private void Dash()
{
if (isDashing)
{
if (dashTimeLeft > 0)
{
rb.velocity = new Vector2(dashSpeed * gameObject.transform.localScale.x, rb.velocity.y);
dashTimeLeft -= Time.deltaTime;
ShadowPool.Instance.GetFormPool();
}
else
{
isDashing = false;
}
}
}
}
2、ShadowSprite.cs:挂载在残影预制体上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShadowSprite : MonoBehaviour
{
private Transform player;
private SpriteRenderer thisSprite;
private SpriteRenderer playerSprite;
private Color color;
[Header("残影显示时间设置")]
public float activeTime = 2;//显示时间
private float activeStart;//开始显示的时间
private float alpha;
[Header("残影透明度设置")]
public float alphaStart = 1;//刚开始的透明度
[Header("残影衰变指数设置")]
public float alphaMultiplier = 0.95f;//衰变指数
private void OnEnable()//物体每次激活时都会调用此生命周期函数
{
player = GameObject.FindGameObjectWithTag("Player").transform;//记得将场景中的Player的标签设置为Player
thisSprite = GetComponent<SpriteRenderer>();
playerSprite = player.GetComponent<SpriteRenderer>();
alpha = alphaStart;
thisSprite.sprite = playerSprite.sprite;
transform.position = player.position;
transform.localScale = player.localScale;
transform.rotation = player.rotation;
activeStart = Time.time;
}
// Update is called once per frame
void Update()
{
alpha *= alphaMultiplier;
color = new Color(0.5f, 0.5f, 1, alpha);
thisSprite.color = color;
if (Time.time >= activeStart + activeTime)
{
ShadowPool.Instance.ReturnPool(this.gameObject);
}
}
}
3、ShadowPool.cs:挂载在残影对象池上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShadowPool : MonoBehaviour
{
private static ShadowPool _instance;//单例模式
[Header("残影预制体")]
public GameObject shadowPrefab;
[Header("生成预制体的数量")]
public int shadowCount = 10;
private Queue<GameObject> availableObjects = new Queue<GameObject>();//用队列来存储生成的预制体
public static ShadowPool Instance
{
get
{
return _instance;
}
}
private void Awake()
{
if (Instance == null)
{
_instance = this;
}
CreateShadow();
}
public void CreateShadow()//生成残影
{
for (int i = 0; i < shadowCount; i++)
{
GameObject newShadow = Instantiate(shadowPrefab);
newShadow.transform.SetParent(transform);
ReturnPool(newShadow);
}
}
public void ReturnPool(GameObject gameObject)//进入对象池
{
gameObject.SetActive(false);
availableObjects.Enqueue(gameObject);//入队
}
public GameObject GetFormPool()//从对象池中取出
{
if (availableObjects.Count == 0)//如果队列中的预制体不够用就继续创建
{
CreateShadow();
}
GameObject outShadow = availableObjects.Dequeue();//出队
outShadow.SetActive(true);
return outShadow;
}
}