Unity 2d游戏中的奇怪碰撞错误

吉奥拉·古赛(Giora Guttsait)

Github存储库(脚本文件夹,所有代码均位于.cs文件中)

我有一个奇怪的碰撞错误,这是它的一个gif图像:

GIF

重新创建:例如,在gif中,我同时按下Left arrowUp arrow直到速度归一化为止,然后我知道为什么会卡在块中。

在XNA上进行游戏时,我曾使用自己的碰撞算法来解决这个问题,希望这不会在Unity中发生。

这是播放器脚本PlayerMovement

using UnityEngine;
using UnityEngine.UI;

namespace Assets.Scripts
{
    public enum Directions
    {
        Back,
        Left,
        Front,
        Right,
        Idle = -1
    }

    public class PlayerMovement : MonoBehaviour
    {
        #region Public Members

        /// <summary>
        /// Maximum speed of the player (Accelerated to over a period of time)
        /// </summary>
        public float speed;

        /// <summary>
        /// Debug UI.Text element
        /// </summary>
        public Text debugText;

        #endregion

        #region Constants

        /// <summary>
        /// Constant for decaying the velocity on updates
        /// </summary>
        private const float VELOCITY_DECAY_FACTOR = 0.85f;

        /// <summary>
        /// Constant to convert normal speed sizes to fit the scale
        /// Of UnityEngine.Vector2
        /// </summary>
        private const float HUMAN_TO_VECTOR_SCALE_FACTOR = 850f;

        /// <summary>
        /// Constant to set the base speed of the player animation
        /// </summary>
        private const float BASE_ANIM_SPEED = 0.7f;

        /// <summary>
        /// Constant to slightly reduce the animation speed after 
        /// It is multiplied by the velocity of the player
        /// </summary>
        private const float POST_VELOCITY_MULTIPLICATION_ANIM_SPEED_FACTOR = 0.5f;

        /// <summary>
        /// Constant to set the animation speed
        /// </summary>
        private const float ANIM_SPEED_MODIFIER = BASE_ANIM_SPEED * POST_VELOCITY_MULTIPLICATION_ANIM_SPEED_FACTOR;

        /// <summary>
        /// Epsilon before velocity zerofication
        /// </summary>
        private const float VELOCITY_EPSILON = 0.1f;

        #endregion

        #region Private Members

        private Rigidbody2D rb2D;
        private Vector2 velocity;
        private Animator animator;
        private Directions dir = Directions.Idle;

        #endregion

        #region Game Loop Methods

        private void Awake()
        {
            animator = GetComponent<Animator>();
            rb2D = GetComponent<Rigidbody2D>();
        }

        private void FixedUpdate()
        {
            float vertical = Input.GetAxisRaw("Vertical");
            float horizontal = Input.GetAxisRaw("Horizontal");
            UpdateVelocity(horizontal, vertical);
            UpdateAnimation(horizontal, vertical);
            UpdateMovment();
        }

        #endregion

        #region Animation Methods

        private void UpdateAnimation(float horizontal, float vertical)
        {
            UpdateAnimation(new Vector2(horizontal, vertical));
        }

        private void UpdateAnimation(Vector2 input)
        {
            Directions direction;

            if (input.y > 0)
                direction = Directions.Back;
            else if (input.y < 0)
                direction = Directions.Front;
            else if (input.x > 0)
                direction = Directions.Right;
            else if (input.x < 0)
                direction = Directions.Left;
            else
                direction = Directions.Idle;

            SetDirection(direction);
        }

        private void SetDirection(Directions value)
        {
            animator.SetInteger("Direction", (int)value);
            dir = value;
        }

        #endregion

        #region Movement Methods

        private void UpdateMovment()
        {
            rb2D.MovePosition(rb2D.position + velocity * Time.fixedDeltaTime);
            KinematicsDebugPrints();
            ApplySpeedDecay();
        }

        private string GetDebugPrintDetails()
        {
            return string.Format("HOR : {0}\nVER : {1}\nDIR : {2}:{3}\nX : {4}\nY : {5}",
                velocity.x,
                velocity.y,
                animator.GetInteger("Direction").ToString().PadLeft(2),
                (Directions)animator.GetInteger("Direction"),
                rb2D.position.x,
                rb2D.position.y);
        }

        private void KinematicsDebugPrints()
        {
            var details = GetDebugPrintDetails();
            debugText.text = details;
            Debug.Log(details);
        }

        private void UpdateVelocity(float horizontal, float vertical)
        {
            if (vertical != 0)
                velocity.y += Mathf.Sign(vertical) * speed / HUMAN_TO_VECTOR_SCALE_FACTOR;
            if (horizontal != 0)
                velocity.x += Mathf.Sign(horizontal) * speed / HUMAN_TO_VECTOR_SCALE_FACTOR;
            animator.speed = ANIM_SPEED_MODIFIER * velocity.MaxOfXandY() ;
        }

        private void ApplySpeedDecay()
        {
            if (velocity == Vector2.zero) return;

            velocity *= VELOCITY_DECAY_FACTOR;
            velocity = velocity.ZerofiyTinyValues(0.1f);
        }

        #endregion
    }
}

当前是玩家对象:

播放器

这就是墙对象(除图像外,所有墙的预制件都是相同的:

壁

这是我其他bug的gif:

错误二

这是碰撞盒和圆圈的样子:

新的碰撞箱

这是检查员的详细信息

新检查员


So after speaking with Hamza Hasan, he helped me to turn all the outer wall box colliders into four continues colliders, one per side(top, bottom, left, right).

The code for it is on the BoardManager script in the CreateWallsColliders method.

This is how the scene currently looks like in the scene editor:

新场景编辑器

Hamza Hasan

Well, first of all move your input code from FixedUpdate to Update otherwise it leads app to laggy behaviour. Second thing is you can do this by creating PhysicsMaterial2D with Friction = 0 and Bounciness = 0 and attach it to the player as well as walls collider in Material. Hope this helps you.

EDIT:

Here is an alternative solution for you, instead of using 1 box collider per block, use only 1 collider per side. 4 Colliders in total.

这是代码,您可以将其添加到您的BoardManager课程中。并在SetUpScene方法末尾调用它,您可以进一步对其进行修改。

void CreateWallsColliders ()
        {
            GameObject colliders = new GameObject ("Colliders");
            colliders.transform.position = Vector3.zero;

            GameObject leftCollider = new GameObject ("LeftCollider");
            leftCollider.transform.position = Vector3.zero;
            BoxCollider2D bcLeftCollider = leftCollider.AddComponent<BoxCollider2D> ();
            leftCollider.transform.parent = colliders.transform;

            GameObject rightCollider = new GameObject ("RightCollider");
            rightCollider.transform.position = Vector3.zero;
            BoxCollider2D bcRightCollider = rightCollider.AddComponent<BoxCollider2D> ();
            rightCollider.transform.parent = colliders.transform;

            GameObject topCollider = new GameObject ("TopCollider");
            topCollider.transform.position = Vector3.zero;
            BoxCollider2D bcTopCollider = topCollider.AddComponent<BoxCollider2D> ();
            topCollider.transform.parent = colliders.transform;

            GameObject bottomCollider = new GameObject ("BottomCollider");
            bottomCollider.transform.position = Vector3.zero;
            BoxCollider2D bcBottomCollider = bottomCollider.AddComponent<BoxCollider2D> ();
            bottomCollider.transform.parent = colliders.transform;

            // Assuming 15 x 15 tiles. Make it dynamic if you need.
            // Assuming -1 and 15 are the limits on both sides

            int rows = 15;
            int cols = 15;

            int lowerLimit = -1;
            int upperLimit = 15;

            leftCollider.transform.position = new Vector3 (lowerLimit, rows / 2);
            leftCollider.transform.localScale = new Vector3 (1, cols, 1);

            rightCollider.transform.position = new Vector3 (upperLimit, rows / 2);
            rightCollider.transform.localScale = new Vector3 (1, cols, 1);

            topCollider.transform.position = new Vector3 (cols / 2, upperLimit);
            topCollider.transform.localScale = new Vector3 (rows, 1, 1);

            bottomCollider.transform.position = new Vector3 (cols / 2, lowerLimit);
            bottomCollider.transform.localScale = new Vector3 (rows, 1, 1);
        }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章