当另一个协程处于活动状态时,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));
}
}
我正在开发一个 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));
}
}