Unity实现残影效果

1、效果展示

效果展示

2、场景搭建

player
残影预制体
残影对象池

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;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44887198/article/details/130430341