在Unity 2D游戏怪异碰撞的bug [英] Weird collision bug in Unity 2d game

查看:2329
本文介绍了在Unity 2D游戏怪异碰撞的bug的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Github上库(脚本文件夹,在文件的.cs所有代码)

我在团结这个奇怪的碰撞错误,这里是它的一个GIF:

I have this weird collision bug in unity, here's a gif of it:

< A HREF =http://i.stack.imgur.com/02aTe.gif相对=nofollow>

重塑:在GIF,比如,我按下两个<大骨节病>左箭头和<大骨节病>向上箭头< /骨节病>直到速度恢复正常,我也得到了一些为何被困在一个块。

Recreating: In the gif, for example, I press both Left arrow and Up arrow until the velocity normalizes, and I get some why stuck in a block.

我有这跟当我做游戏在我自己的碰撞算法之前。XNA,希望这不会在Unity发生

I've had this before with my own collision algorithm when I did the game in XNA, hoped this would not happen in 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
    }
}

这是玩家当前的对象:

和这是在壁对象(预制为除图像的所有壁是相同的:

And this is the wall object (prefab is the same for all walls except for the image:

这是我的其他错误的GIF:

This is a gif of my other bug:

这是碰撞盒和各界什么样子:

This is how the collision box and circles look like:

这是从检查细节。

因此,与哈姆扎·哈桑说后,他帮我把所有的外壁箱撞机四个继续对撞机,每侧一颗(上,下,左,右)。

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).

有关它的代码是对的 BoardManager 脚本在 CreateWallsColliders 方法。

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:

推荐答案

嗯,首先,从 FixedUpdate 移动你的输入代码更新,否则它会导致应用laggy行为。第二件事情是,你可以通过创建 PhysicsMaterial2D 做到这一点摩擦= 0 反弹力= 0 ,并在材料。 。希望这可以帮助你。

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.

编辑:

下面是一个替代解决方案你,而是采用每块1盒对撞机,使用每方只有1对撞机。 4撞机总。

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 方法的末尾调用它,您可以进一步修改它。

Here is the code, you can add it to your BoardManager class. And call it in at the end of SetUpScene method, you can further modify it.

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

这篇关于在Unity 2D游戏怪异碰撞的bug的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆