You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D销毁玩家对象并实例化带装备预制体后动画无限循环问题

问题分析与解决方案

问题根源

  1. 动画参数设置错误:Update方法的else分支每帧都在设置PickST布尔值为true,如果该动画是循环状态,会导致无限重复播放。
  2. 触发逻辑持续执行:OnTriggerStay2D会在碰撞体接触期间持续触发,反复将TorchSwordBool设为true,加剧动画循环问题。
  3. 销毁逻辑未触发:DestroyPlayer方法未被调用,原玩家对象一直存在,持续执行拾取动画的设置逻辑。

修复步骤

1. 将拾取动画改为触发型(Trigger)

在Unity Animator面板中,把PickST参数的类型从Bool改为Trigger。Trigger只需触发一次,动画播放完成后自动停止,不会循环。

2. 替换触发检测方法

把OnTriggerStay2D改为OnTriggerEnter2D,确保只在首次接触火把剑时触发逻辑,避免重复执行:

void OnTriggerEnter2D(Collider2D coll)
{
    if(coll.gameObject.tag == "TorchSword" && isGrounded && !TorchSwordBool)
    {
        TorchSwordBool = true;
        sprite.flipX = false;
        rb.constraints = RigidbodyConstraints2D.FreezePosition;
        transform.position = TorchSword.position;
        // 仅触发一次拾取动画
        animationPlayer.SetBool("Walking", false);
        animationPlayer.SetTrigger("PickST");
        DestroyTorchNSword();
    }
}

3. 简化Update中的动画逻辑

移除Update分支中重复设置PickST的代码,避免每帧执行无效操作:

else
{
    animationPlayer.SetBool("Walking", false);
}

4. 通过动画事件触发玩家销毁

打开拾取动画的Clip,在时间线末尾添加动画事件,绑定到脚本的DestroyPlayer方法。这样动画播放完成后,才会实例化新玩家并销毁旧玩家,避免逻辑冲突。

5. 检查新玩家预制体

确保CharacterSword预制体没有挂载相同的PlayerMovementNoSword脚本,或已将其TorchSwordBool初始值设为false,防止新玩家误触发拾取逻辑。


修改后的完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovementNoSword : MonoBehaviour
{
    private float move;

    [SerializeField] private bool TorchSwordBool = false;
    [SerializeField] private Transform TorchSword;
    [SerializeField] private GameObject CharacterSword;

    [SerializeField] private float moveSpeed = 3f;

    [SerializeField]private bool jumping; 
    [SerializeField] private float jumpSpeed = 4.8f;

    [SerializeField] private float ghostJump;

    [SerializeField] private bool isGrounded;
    public Transform feetPosition;
    [SerializeField] private Vector2 sizeCapsule;
    [SerializeField] private float angleCapsule = -90;
    public LayerMask whatIsGround;

    Rigidbody2D rb;
    SpriteRenderer sprite;
    Animator animationPlayer;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        sprite = GetComponent<SpriteRenderer>();
        animationPlayer = GetComponent<Animator>();

        sizeCapsule = new Vector2 (0.302f, 0.01f);
    }

    void Update()
    {
        if(TorchSwordBool == false)
        {
            isGrounded = Physics2D.OverlapCapsule(feetPosition.position, sizeCapsule, CapsuleDirection2D.Horizontal, angleCapsule, whatIsGround);

            move = Input.GetAxis("Horizontal");

            if (move !=0) {
                moveSpeed += 15f * Time.deltaTime;
                if (moveSpeed >= 3.0f)
                {
                    moveSpeed = 3.0f;
                }
            }
            else
            {
                moveSpeed = 0;
            }

            if(Input.GetButtonDown("Jump") && ghostJump > 0)
            {
                jumping = true;
            }

            if(move < 0)
            {
                sprite.flipX = true;
            }
            else if(move > 0)
            {
                sprite.flipX = false;
            }

            if (isGrounded)
            {
                ghostJump = 0.05f;

                animationPlayer.SetBool("JumpingV", false);
                animationPlayer.SetBool("FallingV", false);
                animationPlayer.SetBool("JumpingH", false);

                if (rb.velocity.x != 0 && move != 0)
                {
                    animationPlayer.SetBool("Walking", true);
                }
                else
                {
                    animationPlayer.SetBool("Walking", false);  
                }
            }
            else
            {
                ghostJump -= Time.deltaTime;
                if(ghostJump <= 0)
                {
                    ghostJump = 0;
                }   

                animationPlayer.SetBool("Walking", false);

                if (rb.velocity.x == 0)
                {
                    if (rb.velocity.y > 0)
                    {
                        animationPlayer.SetBool("JumpingV", true);
                        animationPlayer.SetBool("FallingV", false);
                        animationPlayer.SetBool("JumpingH", false);
                    }
                    if (rb.velocity.y < 0)
                    {
                        animationPlayer.SetBool("JumpingV", false);
                        animationPlayer.SetBool("FallingV", true);
                        animationPlayer.SetBool("JumpingH", false);
                    }
                }
                else
                {
                    if (rb.velocity.y > 0)
                    {
                        animationPlayer.SetBool("JumpingV", false);
                        animationPlayer.SetBool("FallingV", false);
                        animationPlayer.SetBool("JumpingH", true);
                    }
                    if (rb.velocity.y < 0)
                    {
                        animationPlayer.SetBool("JumpingV", false);
                        animationPlayer.SetBool("FallingV", true);
                        animationPlayer.SetBool("JumpingH", false);
                    }
                }   
            } 
        }
        else
        {
            animationPlayer.SetBool("Walking", false);
        }
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = new Color(1, 0, 0, 0.5f);
        Gizmos.DrawCube(feetPosition.position, sizeCapsule);
    }

    void FixedUpdate()
    {
        if(TorchSwordBool == false)
        {
            rb.velocity = new Vector2(move * moveSpeed, rb.velocity.y);

            if(jumping)
            {
                rb.velocity = Vector2.up * jumpSpeed;
                jumping = false;
            }
        }
    }

    void OnTriggerEnter2D(Collider2D coll)
    {
        if(coll.gameObject.tag == "TorchSword" && isGrounded && !TorchSwordBool)
        {
            TorchSwordBool = true;
            sprite.flipX = false;
            rb.constraints = RigidbodyConstraints2D.FreezePosition;
            transform.position = TorchSword.position;
            animationPlayer.SetTrigger("PickST");
            DestroyTorchNSword();
        }
    }

    void DestroyTorchNSword()
    {
        Destroy(TorchSword.gameObject);
    }

    void DestroyPlayer()
    {
        Instantiate(CharacterSword, transform.position, Quaternion.identity);
        Destroy(gameObject);
    }
}

内容的提问来源于stack exchange,提问作者Matthew Pina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:47:50