问题,OnCollisionStay上有冲突的bools



问题是,当我按E来初始化Hole对象,而他们按F来初始化树时,如果玩家仍在与Hole碰撞,当我按下F时,holeColling将变为false。

公共类CreateHole:MonoBehavior{

public GameObject gameObject2;
public GameObject gameObject1;
public bool holeColliding;
public Transform playerPosition;
public bool facingRight1 = true;
public Vector3 holePosition;
public bool treeColliding;
void Update()
{
facingRight1 = GetComponent<PlayerMovement>().facingRight;
if (Input.GetKeyDown(KeyCode.E) && holeColliding == false && facingRight1 == true)
{
Instantiate(gameObject1, playerPosition.position + new Vector3(0.6f, -1f, 0f), Quaternion.identity);
}
else if (Input.GetKeyDown(KeyCode.E) && holeColliding == false && facingRight1 == false)
{
Instantiate(gameObject1, playerPosition.position + new Vector3(-0.6f, -1f, 0f), Quaternion.identity);
}
if (Input.GetKeyDown(KeyCode.F) && holeColliding == true && treeColliding == false)
{
Instantiate(gameObject2, holePosition + new Vector3(0f, 0.5f), Quaternion.identity);
}
}
void OnTriggerStay2D(Collider2D other)
{
if(other.tag == "Hole")
{
holePosition = other.transform.position;
holeColliding = true;
Debug.Log("true");
}
else
{
holeColliding = false;
Debug.Log("false");
}
if(other.tag == "Tree")
{
treeColliding = true;
}
else
{
treeColliding = false;
}
}

gameObject2似乎没有被标记为"Hole",所以OnTriggerStay中的else设置了holeColliding = false。。。

由于OnTriggerStay2D是每帧执行的,但一次只为一个对撞机执行,所以你的bool总是一团糟!(不幸的是,API并不清楚它是只为另一个对象调用还是为每个对象调用,我假设/期待稍后调用-但这在这里并不重要(


我宁愿不使用重复的OnTriggerStay2D,而是将其分为OnTriggerEnter2DOnTriggerExit2D。无论如何,这是有道理的,因为否则你可以进入一个洞,离开它,但holeColliding将永远留在true

void OnTriggerEnter2D (Collider2D other)
{
if(other.CompareTag("Hole"))
{
holePosition = other.transform.position;
holeColliding = true;
Debug.Log("true");
}
else if(other.CompareTag("Tree"))
{
treeColliding = true;
}
}
void OnTriggerExit2D(Collider2D other)
{
if(other.CompareTag("Hole"))
{
holeColliding = false;
}
else if(other.CompareTag("Tree"))
{
treeColliding = false;
}
}

注意,在上面的代码中,我建议使用CompareTag,而不是直接将字符串与==进行比较。如果提供的标记拼写错误或根本不存在,CompareTag将抛出异常。一个"bug",它会被==悄悄隐藏,只需返回false,就可以花费开发时间和精力;(


另外两点:

  • 永远不要Update中使用GetComponent或重复使用-这是一个非常昂贵的调用。而是将引用存储一次并重复使用
  • 您检查E的输入两次,这也是多余的,而且针头昂贵。由于在两个代码块中执行的操作几乎相同,您甚至可以使用?运算符(当只以不同方式分配一个变量时,这基本上是if - else的简写(来缩短它

我会将您的代码修改为

// Best would be you already reference this via the Inspector
// Then you can skip the GetComponent completely
[SerializeField] private PlayerMovement playerMovement;
private void Awake ()
{
// Otherwise get it at runtime and store it for later
if(! playerMovement) playerMovement = GetComponent<PlayerMovement>();
}
void Update()
{
// Now reuse the already stored reference
facingRight1 = playerMovement.facingRight;
if (Input.GetKeyDown(KeyCode.E) && !holeColliding)
{
// Since in both code blocks you do exactly the same
// .. the only changing is a `-` you can shorten your code a lot
var x = 0.6f * (facingRight1 ? 1 : -1);
Instantiate(gameObject1, playerPosition.position + new Vector3(x, -1f, 0f), Quaternion.identity);
}
if (Input.GetKeyDown(KeyCode.F) && holeColliding && !treeColliding)
{
Instantiate(gameObject2, holePosition + Vector3.up * 0.5f, Quaternion.identity);
}
}

最新更新