【问题标题】:Unity 2D Colliders Stuck to Walls?Unity 2D 碰撞器粘在墙上?
【发布时间】:2015-08-11 19:41:28
【问题描述】:

我今天早上刚刚将 Unity 从 5.0.0 更新到 5.2.1 版本,我遇到了一些问题。在 Unity 将游戏翻译为适用于新版本后,我对游戏进行了测试。一切都很好,除了当我在游戏中射出一颗子弹时,它们会粘在墙上而不是从墙上弹开,但仅限于特定的角度和距离。就好像子弹太快了,它跳过了对撞机,卡在了对撞机里面。这有点道理,但奇怪的是我有一个用于游戏中慢动作的 C# 脚本。每当我打开慢动作然后再次将其关闭时,子弹卡住的问题就会消失。我似乎无法弄清楚是什么导致了问题,而且在我更新软件之前它肯定不存在。谁能帮我解决这个问题?谢谢。我将在下面发布子弹脚本和慢动作脚本。顺便说一下,子弹是在播放器脚本中实例化的。

子弹脚本:

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {

public float bulletSpeed;
public float bulletOpacity;
public bool fadeOut;

Animator anim;
Rigidbody2D rigidbod;
SpriteRenderer spriterend;

public GameObject player;
public float aimRotation;

// Use this for initialization
void Start () {

    anim = GetComponent<Animator> ();
    rigidbod = GetComponent<Rigidbody2D> ();
    spriterend = GetComponent<SpriteRenderer> ();

    rigidbod.velocity = transform.right * bulletSpeed;
    rigidbod.gravityScale = 0;

    bulletOpacity = 1;

}

// Update is called once per frame
void Update () {

    Destroy (gameObject, 3f);

    spriterend.color = new Color (1f, 1f, 1f, bulletOpacity);

    if (fadeOut == true)
        bulletOpacity -= 0.03f;

    if (bulletOpacity <= 0)
        Destroy (gameObject);

    aimRotation = player.GetComponent<Player> ().aimRotation;

}

void OnTriggerEnter2D (Collider2D bulletHit) {

    /*if (bulletHit.gameObject.layer == LayerMask.NameToLayer ("vulnerableLayer")) {

    }*/
    rigidbod.gravityScale = 1;
    rigidbod.drag = 1;
    fadeOut = true;

}

}

慢动作脚本:

using UnityEngine;
using System.Collections;

public class SlowMotion : MonoBehaviour {

public float currentLongevity = 0f;
public float slowAmount = 0.2f;
public float normalTime = 1f;
public float slowLongevity = 0.4f;


// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

    if (Input.GetMouseButtonDown (1)) {
        Time.fixedDeltaTime = 0.0f * Time.timeScale;
        if (Time.timeScale == normalTime)
            Time.timeScale = slowAmount;
    }

    if (Time.timeScale == slowAmount) {
        currentLongevity += Time.deltaTime;
    }

    if (currentLongevity > slowLongevity) {
        currentLongevity = 0;
        Time.timeScale = normalTime;
    }

}
}

【问题讨论】:

  • 你正在处理OnTriggerEnter2D,所以看起来你必须手动创建弹跳效果(虽然我有时不确定它是如何工作的)。
  • 它以前工作过,我怀疑这就是问题所在。我可以通过将rigidbody2D的碰撞检测从离散更改为连续来解决这个问题,但这仍然不能解决为什么它在运行慢动作脚本@Hopeless时突然工作的问题

标签: c# unity3d 2d collision-detection physics


【解决方案1】:

由于您表示在运行 SlowMotion 脚本后“奇怪”的项目符号行为会停止,因此我建议问题与设置 Time.fixedDeltaTime 相关,就像您在 SlowMotion 脚本的 Update() 方法中所做的那样。您后来的评论也支持这一点,即当您将rigidBody2D 的碰撞检测设置为连续(我假设是子弹的 RigidBody2D)时,不再出现“奇怪”行为。

Continuous RididBody2D 碰撞检测能够确定更新之间是否发生接触,而Discrete 碰撞检测在物理更新期间记录碰撞。在您的慢动作脚本中,以下行(在 Update() 方法中)将 fixedDeltaTime 设置为 zero

Time.fixedDeltaTime = 0.0f * Time.timeScale;

由于Time.fixedDeltaTime执行物理和其他固定帧速率更新的间隔(以秒为单位),因此必须有一个实际运行帧速率的最小值,(0.0 不能一个实际的帧率更新间隔)。当 Time.fixedDeltaTime == 0.0 时,Unity 可能会使用默认最小值或使用它来指示帧更新尽可能频繁地运行(尽管我没有对此进行测试)。由于 Bullet 脚本调用的是 Update() 而不是 FixedUpdate(),因此无法保证实际的 interval between the frame updates is uniform。我怀疑当您运行 SlowMotion 脚本并将 Time.fixedDeltaTime 设置为 0.0 时,Unity 会以尽可能小的帧更新间隔运行,并且在此之后,它确实会呈现预期的子弹行为。

对此进行测试的一种方法是在编辑器中将您的初始 Time.fixedDeltaTime 设置为 0.0(并将您的碰撞检测行为重新设置为子弹的 RididBody2D 的离散)。

在编辑器中设置Time Manager fixedDeltaTime主菜单 -> 编辑 -> 项目设置 -> 时间

如果您发现一个可行的 fixedDeltaTime,您可以在编辑器中设置它并在您的 SlowMotion 脚本中的 Awake() 方法中检索初始值,以初始化基本的 fixedDeltaTime。我不建议使用 fixedDeltaTime == 0.0,因为文档中没有说明 0.0 时间间隔的一致行为,它可能更多地绑定到底层硬件,并可能导致更多意外行为。

希望这会有所帮助,干杯!

【讨论】:

  • 谢谢。前一阵子想通了,忘记发这个了。不过,我真的很感谢你帮助我!再次感谢!
猜你喜欢
  • 2020-12-31
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
相关资源
最近更新 更多