Unity 2D平台游戏:玩家对象转Prefab后跳跃动画失效求解决
2D平台游戏转为Prefab后跳跃动画失效问题
我正在Unity中开发一款2D平台游戏,遵循Brackeys的教程制作,所有功能原本正常,但将玩家对象转为Prefab后,跳跃动画突然失效。不确定是编程问题还是Unity本身的问题,求解决方案。
相关信息
- 参考教程:Brackeys的2D平台游戏教程(共2部分)
- 问题演示:左侧玩家角色为存在动画问题的Prefab实例
- 补充演示视频
- 已尝试操作:修改部分代码、基于Prefab重新制作动画、搜索网上类似问题,均未解决
- 怀疑方向:问题可能与CharacterController2D.cs中的UnityEvent相关
代码展示
PlayerMovement.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public CharacterController2D controller; float horizontalMove = 0f; public float runSpeed = 40f; bool jump = false; bool crouch = false; public Animator animator; public float coyoteTime = 0.2f; public float coyoteTimeCounter = 0; public float jumpBufferTime = 0.2f; public float jumpBufferCounter; // Update is called once per frame void Update() { horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed; animator.SetFloat("Speed", Mathf.Abs(horizontalMove)); if (controller.m_Grounded) { coyoteTimeCounter = coyoteTime; } else { coyoteTimeCounter -= Time.deltaTime; } if (Input.GetButtonDown("Jump")) { jump = true; animator.SetBool("IsJumping", true); jumpBufferCounter = jumpBufferTime; } else { jumpBufferCounter -= Time.deltaTime; } if (Input.GetButtonUp("Jump")) { coyoteTimeCounter = 0f; } if (Input.GetButtonDown("Crouch")) { crouch = true; } else if (Input.GetButtonUp("Crouch")) { crouch = false; } } public void OnLanding() { animator.SetBool("IsJumping", false); } public void OnCrouching(bool isCrouching) { animator.SetBool("IsCrouching", isCrouching); } private void FixedUpdate() { controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump, jumpBufferCounter); jump = false; } }
CharacterController2D.cs
using Unity.VisualScripting; using UnityEngine; using UnityEngine.Events; public class CharacterController2D : MonoBehaviour { [SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps. [Range(0, 1)] [SerializeField] private float m_CrouchSpeed = .36f; // Amount of maxSpeed applied to crouching movement. 1 = 100% [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f; // How much to smooth out the movement [SerializeField] private bool m_AirControl = false; // Whether or not a player can steer while jumping; [SerializeField] private LayerMask m_WhatIsGround; // A mask determining what is ground to the character [SerializeField] private Transform m_GroundCheck; // A position marking where to check if the player is grounded. [SerializeField] private Transform m_CeilingCheck; // A position marking where to check for ceilings [SerializeField] private Collider2D m_CrouchDisableCollider; // A collider that will be disabled when crouching const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded public bool m_Grounded; // Whether or not the player is grounded. const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up private Rigidbody2D m_Rigidbody2D; private bool m_FacingRight = true; // For determining which way the player is currently facing. private Vector3 m_Velocity = Vector3.zero; private PlayerMovement player; [Header("Events")] [Space] public UnityEvent OnLandEvent; [System.Serializable] public class BoolEvent : UnityEvent<bool> { } public BoolEvent OnCrouchEvent; private bool m_wasCrouching = false; private void Awake() { m_Rigidbody2D = GetComponent<Rigidbody2D>(); player = GetComponent<PlayerMovement>(); if (OnLandEvent == null) OnLandEvent = new UnityEvent(); if (OnCrouchEvent == null) OnCrouchEvent = new BoolEvent(); } private void FixedUpdate() { bool wasGrounded = m_Grounded; m_Grounded = false; // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground // This can be done using layers instead but Sample Assets will not overwrite your project settings. Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround); for (int i = 0; i < colliders.Length; i++) { if (colliders[i].gameObject != gameObject) { m_Grounded = true; if (!wasGrounded) OnLandEvent.Invoke(); } } } private void OnTriggerStay2D(Collider2D other) { if (other.CompareTag("Water")) { m_Grounded = true; m_JumpForce = 800; m_Rigidbody2D.gravityScale = 0.8f; } } private void OnTriggerExit2D(Collider2D other) { if (other.CompareTag("Water")) { m_Rigidbody2D.gravityScale = 3f; m_JumpForce = 800; } } public void Move(float move, bool crouch, bool jump, float jumpBufferTimer) { // If crouching, check to see if the character can stand up if (!crouch) { // If the character has a ceiling preventing them from standing up, keep them crouching if (Physics2D.OverlapCircle(m_CeilingCheck.position, k_CeilingRadius, m_WhatIsGround)) { crouch = true; } } //only control the player if grounded or airControl is turned on if (m_Grounded || m_AirControl) { // If crouching if (crouch) { if (!m_wasCrouching) { m_wasCrouching = true; OnCrouchEvent.Invoke(true); } // Reduce the speed by the crouchSpeed multiplier move *= m_CrouchSpeed; // Disable one of the colliders when crouching if (m_CrouchDisableCollider != null) m_CrouchDisableCollider.enabled = false; } else { // Enable the collider when not crouching if (m_CrouchDisableCollider != null) m_CrouchDisableCollider.enabled = true; if (m_wasCrouching) { m_wasCrouching = false; OnCrouchEvent.Invoke(false); } } // Move the character by finding the target velocity Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y); // And then smoothing it out and applying it to the character m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing); // If the input is moving the player right and the player is facing left... if (move > 0 && !m_FacingRight) { // ... flip the player. Flip(); } // Otherwise if the input is moving the player left and the player is facing right... else if (move < 0 && m_FacingRight) { // ... flip the player. Flip(); } } // If the player should jump... if (player.coyoteTimeCounter > 0f && jumpBufferTimer > 0f) { // Add a vertical force to the player. m_Grounded = false; m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce)); player.jumpBufferCounter = 0f; } } private void Flip() { // Switch the way the player is labelled as facing. m_FacingRight = !m_FacingRight; // Multiply the player's x local scale by -1. Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; } }
内容的提问来源于stack exchange,提问作者Yeriwen
相关产品推荐
相关产品推荐

