当另一个协程处于活动状态时,RaycastHit2D 停止工作。 Unity2D 平台游戏,WebGL

RaycastHit2D stops working when another Coroutine is active. Unity2D Platformer, WebGL

我正在开发一个 Unity 项目,它是一款经典的马里奥风格 2D 平台游戏。 出现问题的是一个敌人,已知的蜗牛,它被击晕时可以被踢开。

有两个功能,都可以单独使用,但不能一起使用。项目 Build 已导出为 WebGL,可在浏览器中播放。

1.变化方向:

ChangeDirection() 是一个协程,在 Start-Function 中被调用。当蜗牛到达平台的尽头时,它会翻转蜗牛的外观和移动方向。

2。检查碰撞:

CheckCollision 在 Update-Function 中被调用并检测 4 个游戏对象的碰撞,这些游戏对象附加到蜗牛。

问题描述

当我在 Start-Function 中注释 "StartCoroutine(ChangeDirection());" 时,CheckCollision 工作正常。我可以把蜗牛打晕然后踢开,打晕了。

当我把 ChangeDirection()-Coroutine 放回去时,蜗牛完美地改变了它的方向。也可以检测到 top_Collision。我可以把蜗牛打晕了,它改变了动画,停止了移动,但是左右碰撞似乎停止了,所以我不能把蜗牛踢开,被打晕了.

假设

ChangeDirection() 协程不会完全阻止 CheckCollision() 工作,因为顶部碰撞检测仍然有效。 topHit 是 Collider2D,但 leftHit 和 rightHit 是 RaycastHit2D。 RaycastHit2D 无法与同时激活的 ChangeDirection() 协同程序一起工作。

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

public class SnailScript : MonoBehaviour
{

    public float moveSpeed = 1f;
    private Rigidbody2D myBody;
    private Animator anim;

    public LayerMask playerLayer;

    private bool moveLeft;

    private bool canMove;
    private bool stunned;

    public Transform left_Collision, right_Collision, top_Collision, down_Collision;
    private Vector3 left_Collision_Pos, right_Collision_Pos;

    void Awake()
    {
        myBody = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();

        left_Collision_Pos = left_Collision.position;
        right_Collision_Pos = right_Collision.position;
    }

    void Start()
    {
        moveLeft = true;
        canMove = true;
        StartCoroutine(ChangeDirection());
    }

    void Update()
    {
        if (canMove)
        {
            if (moveLeft)
            {
                myBody.velocity = new Vector2(-moveSpeed, myBody.velocity.y);
            }
            else
            {
                myBody.velocity = new Vector2(moveSpeed, myBody.velocity.y);
            }
        }

        CheckCollision();

    }

    void CheckCollision()
    {
        //ATACHED GAMEOBJECTS FOR COLLISION DETECTION
        RaycastHit2D leftHit = Physics2D.Raycast(left_Collision.position, Vector2.left, 0.1f, playerLayer);
        RaycastHit2D rightHit = Physics2D.Raycast(right_Collision.position, Vector2.right, 0.1f, playerLayer);

        Collider2D topHit = Physics2D.OverlapCircle(top_Collision.position, 0.2f, playerLayer);

        if (topHit != null)
        {
            if (topHit.gameObject.CompareTag(MyTags.PLAYER_TAG))
            {
                if (!stunned)
                {
                    //Player does a little rebounce after jumping on the snail
                    topHit.gameObject.GetComponent<Rigidbody2D>().velocity =
                        new Vector2(topHit.gameObject.GetComponent<Rigidbody2D>().velocity.x, 7f);

                    canMove = false;
                    myBody.velocity = new Vector2(0, 0);

                    anim.Play("Stunned");
                    stunned = true;
                }
            }
        }

        if (leftHit)
        {
            if (leftHit.collider.gameObject.CompareTag(MyTags.PLAYER_TAG))
            {
                if (stunned)
                {
                    //SNAIL KICKED TO THE RIGHT
                    myBody.velocity = new Vector2(15f, myBody.velocity.y);
                }
            }
        }

        if (rightHit)
        {
            if (rightHit.collider.gameObject.CompareTag(MyTags.PLAYER_TAG))
            {
                if (stunned)
                {
                    //SNAIL KICKED TO THE LEFT
                    myBody.velocity = new Vector2(-15f, myBody.velocity.y);
                }
            }
        }
    }

    IEnumerator ChangeDirection()
    {
        if (!Physics2D.Raycast(down_Collision.position, Vector2.down, 0.1f))
        {
            moveLeft = !moveLeft;

            Vector3 tempScale = transform.localScale;

            if (moveLeft)
            {
                //SNAIL LOOKS TO THE LEFT
                tempScale.x = Mathf.Abs(tempScale.x);

                //Changing position of the attached GameObjects for collision detection
                left_Collision.position = left_Collision_Pos;
                right_Collision.position = right_Collision_Pos;

            }
            else
            {
                tempScale.x = -Mathf.Abs(tempScale.x);

                left_Collision.position = right_Collision_Pos;
                right_Collision.position = left_Collision_Pos;
            }

            //new sprite-orientation
            transform.localScale = tempScale;
        }

        yield return new WaitForSeconds(0.5f);

        StartCoroutine(ChangeDirection());
    }
}

正如我最终发现的那样,当您将构建导出为 WebGL 时,RaycastHit2D 不能很好地工作。我假设旧代码应该在没有 WebGL 的情况下工作。

我找到了一种用简单的 OnCollisionEnter2D 替换 RaycastHit2D 的方法,我在其中额外检查了玩家相对于蜗牛的位置,以确定它是左碰撞还是右碰撞。现在可以正常使用了。

    //SNAIL GETS KICKED AWAY
private void OnCollisionEnter2D(Collision2D collision)
{
    if ((collision.gameObject.tag == "Player") && (stunned))
    {
                            //                 Player    -    Snail
        if( ((collision.gameObject.transform.position.x) - (gameObject.transform.position.x)) <= 0f)
        {
            //Player stands left to snail, Snail must be kicked to the right!
            myBody.velocity = new Vector2(15f, myBody.velocity.y);
        }
        else
        {
            myBody.velocity = new Vector2(-15f, myBody.velocity.y);
        }

        if (((collision.gameObject.transform.position.y) - (gameObject.transform.position.y)) >= 0.2f)
        {
            //Player does a little Rebounce, when higher than the snail
            collision.gameObject.GetComponent<Rigidbody2D>().velocity =
                    new Vector2(collision.gameObject.GetComponent<Rigidbody2D>().velocity.x, 7f);
        }

        StartCoroutine(Dead(3f));
    }
}