OnCollisionExit 被调用,但行为异常
OnCollisionExit is called, but behaves strangely
我正在 Unity 中开发 3d FPS 游戏。目前我正在实施 wall-运行ning 机制。这背后的逻辑非常简单——如果玩家向前推,而不是着地,并接触墙壁,我会限制 Y/Z 方向(但玩家仍然可以 运行 向前,因为我忽略了 X 方向) 并关闭重力。它似乎工作正常,有点笨拙,但对我来说还可以。除非,当墙被留在后面时,玩家仍然可以 运行 在半空中,直到他 运行 失去惯性(这里是示例:https://imgur.com/a/LtbWs9J)。这是代码:
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class WallRunning : MonoBehaviour
{
public AudioClip audioClip;
private CharacterMovement cm;
private Rigidbody rb;
private bool isJumping;
public bool isWall;
private bool playAudio;
private AudioSource audioSource;
public float energyLimit = 3.5f;
private void Start()
{
//Get attached components so we can interact with them in our script.
cm = GetComponent<CharacterMovement>();
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
private void FixedUpdate()
{
bool jumpPressed = Input.GetButtonDown("Jump");
float verticalAxis = Input.GetAxis("Vertical");
//Check if the controller is grounded.
if (cm.Grounded)
{
isJumping = false;
isWall = false;
}
//Has the jump button been pressed.
if (jumpPressed)
{
StartCoroutine(Jumping());
}
//If we are pushing forward, and not grounded, and touching a wall.
if (verticalAxis > 0 && isJumping && isWall)
{
StartCoroutine(Energy());
//We constrain the Y/Z direction to defy gravity and move off the wall.
//But we can still run forward as we ignore the X direction.
rb.useGravity = false;
rb.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezeRotation;
//We also telegraph to the player by playing a sound effect on contact.
if (audioClip != null && playAudio == true)
{
audioSource.PlayOneShot(audioClip);
//We block more audio being played while we are on the wall.
playAudio = false;
}
}
else
{
StopCoroutine(Energy());
//We need to make sure we can play audio again when touching the wall.
playAudio = true;
rb.useGravity = true;
rb.constraints = RigidbodyConstraints.FreezeRotation;
}
}
void OnCollisionEnter(Collision other)
{
//Are we touching a wall object?
if (other.gameObject.CompareTag("Walls"))
{
isWall = true;
}
}
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (!other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}
IEnumerator Jumping()
{
//Check for 5 frames after the jump button is pressed.
int frameCount = 0;
while (frameCount < 5)
{
frameCount++;
//Are we airbourne in those 5 frames?
if (!cm.Grounded)
{
isJumping = true;
}
yield return null;
}
}
IEnumerator Energy()
{
yield return new WaitForSeconds(energyLimit);
isWall = false;
}
}
注意: 墙上有盒子碰撞器("Is Trigger" 复选框未选中),玩家有非运动刚体和胶囊碰撞器。墙壁未标记为 "static" 并分配给默认层,而玩家分配给玩家层。
我做错了什么?我确定我搞砸了代码,但无法找出问题所在。
替换
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (!other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}
有
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}
我正在 Unity 中开发 3d FPS 游戏。目前我正在实施 wall-运行ning 机制。这背后的逻辑非常简单——如果玩家向前推,而不是着地,并接触墙壁,我会限制 Y/Z 方向(但玩家仍然可以 运行 向前,因为我忽略了 X 方向) 并关闭重力。它似乎工作正常,有点笨拙,但对我来说还可以。除非,当墙被留在后面时,玩家仍然可以 运行 在半空中,直到他 运行 失去惯性(这里是示例:https://imgur.com/a/LtbWs9J)。这是代码:
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class WallRunning : MonoBehaviour
{
public AudioClip audioClip;
private CharacterMovement cm;
private Rigidbody rb;
private bool isJumping;
public bool isWall;
private bool playAudio;
private AudioSource audioSource;
public float energyLimit = 3.5f;
private void Start()
{
//Get attached components so we can interact with them in our script.
cm = GetComponent<CharacterMovement>();
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
private void FixedUpdate()
{
bool jumpPressed = Input.GetButtonDown("Jump");
float verticalAxis = Input.GetAxis("Vertical");
//Check if the controller is grounded.
if (cm.Grounded)
{
isJumping = false;
isWall = false;
}
//Has the jump button been pressed.
if (jumpPressed)
{
StartCoroutine(Jumping());
}
//If we are pushing forward, and not grounded, and touching a wall.
if (verticalAxis > 0 && isJumping && isWall)
{
StartCoroutine(Energy());
//We constrain the Y/Z direction to defy gravity and move off the wall.
//But we can still run forward as we ignore the X direction.
rb.useGravity = false;
rb.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezeRotation;
//We also telegraph to the player by playing a sound effect on contact.
if (audioClip != null && playAudio == true)
{
audioSource.PlayOneShot(audioClip);
//We block more audio being played while we are on the wall.
playAudio = false;
}
}
else
{
StopCoroutine(Energy());
//We need to make sure we can play audio again when touching the wall.
playAudio = true;
rb.useGravity = true;
rb.constraints = RigidbodyConstraints.FreezeRotation;
}
}
void OnCollisionEnter(Collision other)
{
//Are we touching a wall object?
if (other.gameObject.CompareTag("Walls"))
{
isWall = true;
}
}
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (!other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}
IEnumerator Jumping()
{
//Check for 5 frames after the jump button is pressed.
int frameCount = 0;
while (frameCount < 5)
{
frameCount++;
//Are we airbourne in those 5 frames?
if (!cm.Grounded)
{
isJumping = true;
}
yield return null;
}
}
IEnumerator Energy()
{
yield return new WaitForSeconds(energyLimit);
isWall = false;
}
}
注意: 墙上有盒子碰撞器("Is Trigger" 复选框未选中),玩家有非运动刚体和胶囊碰撞器。墙壁未标记为 "static" 并分配给默认层,而玩家分配给玩家层。
我做错了什么?我确定我搞砸了代码,但无法找出问题所在。
替换
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (!other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}
有
void OnCollisionExit(Collision other)
{
//Did we stop touching the wall object?
if (other.gameObject.CompareTag("Walls"))
{
isWall = false;
}
}