好的,我有一个我正在做的项目,实际上是一个马里奥克隆在Unity 2D中创建的函数。出于某种原因,它调用了OnTrigger/OnCollision方法三次(正如它在OnCollision或OnTrigger被调用三次时中继调试消息所示,即使它只应该这样做一次(请参见所附的图片)),即使我没有为它编写这样的代码。我的代码如下(很抱歉,它很混乱,我对C#和Unity 2D还很陌生)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class playerMovement : MonoBehaviour
{
public float moveSpeed;
private float moveDirection;
public float jumpForce;
[SerializeField] private bool isJumping = false;
private Rigidbody2D rb;
private bool facingRight = true;
public Transform ceilingCheck;
public Transform groundCheck;
public LayerMask groundObjects;
public bool isGrounded;
public float checkRadius;
public GameObject camera;
public AudioSource audioSource;
public AudioClip otherClip;
public float score;
public TextMeshProUGUI scoreCount;
public float health;
public TextMeshProUGUI lifeCount;
public GameObject[] enemy;
public GameObject deathBarrier;
public GameObject nPC;
public GameObject youHaveSoMuchToLiveFor;
public GameObject youCannotEscape;
public bool talking;
public bool bossTimerStart;
//nabs stuff before start so there's no lag and so you don't have to nab it yourself
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
// Start is called before the first frame update
void Start()
{
enemy = GetComponentsInParent<GameObject>(tag == "Enemy");
}
// Update is called once per frame
void Update()
{
//get inputs
ProcessInputs();
//flip
Animate();
StartCoroutine(DoThings());
scoreCount.text = "Score: " + score;
lifeCount.text = "Health: " + health;
if (Input.GetKeyDown(KeyCode.RightShift))
{
moveSpeed = 3;
}
if (Input.GetKeyUp(KeyCode.RightShift))
{
moveSpeed = 8;
}
if (Input.GetKeyDown(KeyCode.LeftShift))
{
moveSpeed = 3;
}
if (Input.GetKeyUp(KeyCode.LeftShift))
{
moveSpeed = 8;
}
}
private void FixedUpdate()
{
//move
if (!talking)
{
Move();
}
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, groundObjects);
}
private void ProcessInputs()
{
moveDirection = Input.GetAxis("Horizontal");
if (Input.GetButtonDown("Jump") && isGrounded)
{
isJumping = true;
}
}
public IEnumerator DoThings()
{
while (talking)
{
rb.velocity = Vector2.zero;
yield return null;
}
}
private void Move()
{
rb.velocity = new Vector2(moveDirection * moveSpeed, rb.velocity.y);
if (isJumping)
{
rb.AddForce(new Vector2(0f, jumpForce));
}
isJumping = false;
}
private void FlipCharacter()
{
facingRight = !facingRight;
transform.Rotate(0f, 180f, 0f);
}
private void Animate()
{
//flip
if (moveDirection > 0 && !facingRight)
{
FlipCharacter();
}
if (moveDirection < 0 && facingRight)
{
FlipCharacter();
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Coin")
{
score += 10;
Destroy(other.gameObject);
}
if (other.tag == "Npc")
{
nPC.gameObject.SetActive(true);
}
if (other.tag == "House")
{
youHaveSoMuchToLiveFor.gameObject.SetActive(true);
talking = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Npc")
{
nPC.gameObject.SetActive(false);
}
if (other.tag == "House")
{
youHaveSoMuchToLiveFor.gameObject.SetActive(false);
}
if (other.gameObject.tag == "BossArea")
{
Debug.Log("uHOH CUTSCENE TIME WOOOOOO");
Destroy(other.gameObject);
youCannotEscape.gameObject.SetActive(true);
}
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "EnemyLeft")
{
Debug.Log("scream but right");
rb.AddForce(new Vector2(5000f, 200f));
if (health > 0)
{
Debug.Log("apparently let's check this");
health -= 1;
}
if (health <= 0)
{
StartCoroutine(Woooo());
StartCoroutine(YouGonDie());
}
}
if (other.gameObject.tag == "EnemyRight")
{
Debug.Log("scream but left");
rb.AddForce(new Vector2(-5000f, 200f));
if (health > 0)
{
health -= 1;
}
if (health <= 0)
{
StartCoroutine(Woooo());
StartCoroutine(YouGonDie());
}
}
if (other.gameObject.tag == "Bullet")
{
Debug.Log("oopsie you got shot UwU");
if (health > 0)
{
health -= 1;
}
if (health <= 0)
{
StartCoroutine(Woooo());
StartCoroutine(YouGonDie());
}
}
if (other.gameObject.tag == "EnemyTop")
{
Debug.Log("bonk");
Destroy(other.transform.parent.gameObject);
score += 5;
}
if (other.gameObject == deathBarrier)
{
StartCoroutine(YouFellLol());
}
IEnumerator Woooo()
{
Debug.Log("istg i think this game is an elaborate moistcritikal reference, truly what i've been waiting for, yeah baby");
yield return new WaitForSecondsRealtime(1.2f);
Destroy(gameObject);
}
IEnumerator YouGonDie()
{
AudioSource.PlayClipAtPoint(otherClip, new Vector3(0, 0, 0));
yield return new WaitForSecondsRealtime(0.001f);
}
IEnumerator YouFellLol()
{
Debug.Log("Hey stinky! You fell uwu");
yield return new WaitForSecondsRealtime(0.001f);
Destroy(gameObject);
}
}
public void TalkingWith()
{
talking = true;
}
public void StopTalkingWith()
{
talking = false;
}
}
它只是在我添加了一个函数后才开始这样做,在与某些对象的交互中,玩家停止移动,直到交互结束(用于NPC交互和过场动画)。我以为它只会打一次电话。相反,它打了三次电话。
1条答案
按热度按时间tcomlyy61#
就像你说的
它应该只被调用一次
是的,是真的-只是稍微修改一下。它的本质是,在启用 OnTrigger 的情况下,对它附近的每个对撞机调用一次。
要解决这个问题,请确保不需要的碰撞器不会干扰触发器,并且它们不都启用了 OnTrigger。