为什么组件会在 Unity 的碰撞事件中自动移除?
Why the component automatically was removed on collision event of the Unity?
我的英语水平很差,我的母语不是英语。
请理解。
我想做检测碰撞的逻辑
为此,我制作了一个角色class。 Character class继承了Unity系统的MonoBehaviour,具有如下特点
- class有容器放技能被自己撞到
- class有协程来显示容器的状态。当字符 class 启动时,此协同程序启动。
- class覆盖了Unity系统的OnTriggerEnter2D函数。在这个函数中,将与自己碰撞的技能添加到容器中。
我用下面的代码做了上面的功能。
public class Character : MonoBehaviour
{
private ConcurrentDictionary<Skill, float> _skills = new ConcurrentDictionary<Skill, float>();
protected virtual void Start()
{
StartCoroutine(Check());
}
private IEnumerator Check()
{
float delayTime = 0.1f;
First:
yield return new WaitForSeconds(delayTime);
foreach (var skill in _skills.Keys.ToList())
{
Debug.Log($"_skills: {skill}");
}
goto First;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag != "cold_wind") return;
var skill = collision.GetComponent<Skill>();
_skills.TryAdd(skill, 100);
}
}
然后我将 BoxCollider2D 组件添加到预制件中以添加上述角色 class。
然后我做了技能class。我省略了技能 class,因为技能 class 还没有功能。我将 BoxCollider2D 和 RigidBody2D 组件添加到预制件中以添加技能 class.
最后检查了RigidBody2D接收碰撞事件的Simulated函数
程序按以下顺序执行。
- 技能生成3秒,与角色碰撞
- Character的OnTriggerEnter2D函数被调用,碰撞的技能被添加到容器中。 (并发<技能, 浮动>)
- 检查协程显示技能被包含在容器中。
这里,我遇到了问题。逻辑上我认为容器中包含的技能 class 不能自动删除。
但3秒后(技能效果出现3秒)如果技能效果消失则容器中包含的技能class被移除。结果 Check 协程显示 null,如下所示。
谁能告诉我我做错了什么?
如有任何建议,我们将不胜感激。
感谢阅读。
很可能您所做的一切都按预期工作。一个错误是 TryAdd
的意外行为,其中添加的值可以是 null
.
在您的 OnTriggerEnter2D
函数中,添加一个检查以确定您与什么发生碰撞以仅检查法术。最简单的方法是检查对象的 tag
。对于你所有的法术,添加一个你可以检查的标签,然后改变你的碰撞代码看起来像
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag == "SpellTagHere")
{
// the issue is this line can result in NULL if another object collides with your player
var skill = collision.GetComponent<Skill>();
// meaning a null is added here
_skills.TryAdd(skill, 100);
}
}
我的英语水平很差,我的母语不是英语。 请理解。
我想做检测碰撞的逻辑
为此,我制作了一个角色class。 Character class继承了Unity系统的MonoBehaviour,具有如下特点
- class有容器放技能被自己撞到
- class有协程来显示容器的状态。当字符 class 启动时,此协同程序启动。
- class覆盖了Unity系统的OnTriggerEnter2D函数。在这个函数中,将与自己碰撞的技能添加到容器中。
我用下面的代码做了上面的功能。
public class Character : MonoBehaviour
{
private ConcurrentDictionary<Skill, float> _skills = new ConcurrentDictionary<Skill, float>();
protected virtual void Start()
{
StartCoroutine(Check());
}
private IEnumerator Check()
{
float delayTime = 0.1f;
First:
yield return new WaitForSeconds(delayTime);
foreach (var skill in _skills.Keys.ToList())
{
Debug.Log($"_skills: {skill}");
}
goto First;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag != "cold_wind") return;
var skill = collision.GetComponent<Skill>();
_skills.TryAdd(skill, 100);
}
}
然后我将 BoxCollider2D 组件添加到预制件中以添加上述角色 class。
然后我做了技能class。我省略了技能 class,因为技能 class 还没有功能。我将 BoxCollider2D 和 RigidBody2D 组件添加到预制件中以添加技能 class.
最后检查了RigidBody2D接收碰撞事件的Simulated函数
程序按以下顺序执行。
- 技能生成3秒,与角色碰撞
- Character的OnTriggerEnter2D函数被调用,碰撞的技能被添加到容器中。 (并发<技能, 浮动>)
- 检查协程显示技能被包含在容器中。
这里,我遇到了问题。逻辑上我认为容器中包含的技能 class 不能自动删除。
但3秒后(技能效果出现3秒)如果技能效果消失则容器中包含的技能class被移除。结果 Check 协程显示 null,如下所示。
谁能告诉我我做错了什么?
如有任何建议,我们将不胜感激。
感谢阅读。
很可能您所做的一切都按预期工作。一个错误是 TryAdd
的意外行为,其中添加的值可以是 null
.
在您的 OnTriggerEnter2D
函数中,添加一个检查以确定您与什么发生碰撞以仅检查法术。最简单的方法是检查对象的 tag
。对于你所有的法术,添加一个你可以检查的标签,然后改变你的碰撞代码看起来像
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag == "SpellTagHere")
{
// the issue is this line can result in NULL if another object collides with your player
var skill = collision.GetComponent<Skill>();
// meaning a null is added here
_skills.TryAdd(skill, 100);
}
}