"ArgumentException: The object you want to instantiate is null" Unity,我不明白为什么
"ArgumentException: The object you want to instantiate is null" Unity and i can't figure out why
这突然停止工作,当试图实例化抛射物时告诉我抛射物是空的。即使我声明了它的价值。调试告诉我 Start() 是 运行。无法提供更多上下文。
这里的问题不是 "what does this error mean",而是 "why is it null?" 我从 Daedalus 那里得到了很好的回复,他告诉我要远离字符串查找。我会试试看是否有效。
编辑:// 我的老师在我忘记删除的文本中添加了一些代码(他无法找出我为什么得到空值)但是现在删除了,这是不起作用的正确代码. tag没有拼错,外壳等我都检查过了
void Start()
{
targPlayer = GameObject.FindGameObjectWithTag("Player").transform;
projectile = GameObject.Find("Projectile");
Debug.Log("was run");
}
void Update()
{
fire -= Time.deltaTime;
dmg -= Time.deltaTime;
if (fire <= 0)
{
if (Vector2.Distance(transform.position, targPlayer.position) <= detectionRange)
{
// This is where the error happens
Instantiate(projectile, transform.position, Quaternion.identity);
}
fire = fireRate;
}
if (Vector2.Distance(targPlayer.position, transform.position) <= detectionRange && Vector2.Distance(targPlayer.position, transform.position) >= stopRange)
{
transform.position = Vector2.MoveTowards(transform.position, targPlayer.position, movSpeed * Time.deltaTime);
}
}
这里有很多可能的解决方案,所以我将介绍一些我想到的解决方案。
首先,使用字符串查找是我想大多数开发人员客观上认为不好的一件事。将大小写和文化问题放在一边进行比较,打错字非常容易,因为您或其他团队成员后来更改了该对象的名称而没有记住这些查找依赖于它,并且在非平凡的情况下使用时,存在严重的性能问题。对于 Unity 尤其如此,对于基本上所有的查找调用,Unity 将简单地遍历层次结构,直到找到匹配的对象。
如果您的实例化调用失败,肯定会发生类似上述的情况。
您可能希望在某个时候查看 object pooling,但让我们继续进行实例化调用。
要避开字符串查找,您可以将射弹设为变量。
public Transform projectile;
这将允许您在检查器中分配它。很可能不允许其他脚本访问此变量,因此为了加分,您可以使用 SerializeField 属性序列化私有变量,并在检查器中分配它。
[SerializeField] private Transform projectile;
然后您将可以立即访问射弹,而无需任何查找开销,也不用担心中断查找。
你的设计理念肯定会随着你的进步而发生很大变化,我认为你不应该将任何此类数据与逻辑联系起来 类(以防万一有人提到这一点) ,但我认为从更改查找结构开始是朝着正确方向迈出的重要一步。
这突然停止工作,当试图实例化抛射物时告诉我抛射物是空的。即使我声明了它的价值。调试告诉我 Start() 是 运行。无法提供更多上下文。
这里的问题不是 "what does this error mean",而是 "why is it null?" 我从 Daedalus 那里得到了很好的回复,他告诉我要远离字符串查找。我会试试看是否有效。
编辑:// 我的老师在我忘记删除的文本中添加了一些代码(他无法找出我为什么得到空值)但是现在删除了,这是不起作用的正确代码. tag没有拼错,外壳等我都检查过了
void Start()
{
targPlayer = GameObject.FindGameObjectWithTag("Player").transform;
projectile = GameObject.Find("Projectile");
Debug.Log("was run");
}
void Update()
{
fire -= Time.deltaTime;
dmg -= Time.deltaTime;
if (fire <= 0)
{
if (Vector2.Distance(transform.position, targPlayer.position) <= detectionRange)
{
// This is where the error happens
Instantiate(projectile, transform.position, Quaternion.identity);
}
fire = fireRate;
}
if (Vector2.Distance(targPlayer.position, transform.position) <= detectionRange && Vector2.Distance(targPlayer.position, transform.position) >= stopRange)
{
transform.position = Vector2.MoveTowards(transform.position, targPlayer.position, movSpeed * Time.deltaTime);
}
}
这里有很多可能的解决方案,所以我将介绍一些我想到的解决方案。
首先,使用字符串查找是我想大多数开发人员客观上认为不好的一件事。将大小写和文化问题放在一边进行比较,打错字非常容易,因为您或其他团队成员后来更改了该对象的名称而没有记住这些查找依赖于它,并且在非平凡的情况下使用时,存在严重的性能问题。对于 Unity 尤其如此,对于基本上所有的查找调用,Unity 将简单地遍历层次结构,直到找到匹配的对象。
如果您的实例化调用失败,肯定会发生类似上述的情况。
您可能希望在某个时候查看 object pooling,但让我们继续进行实例化调用。
要避开字符串查找,您可以将射弹设为变量。
public Transform projectile;
这将允许您在检查器中分配它。很可能不允许其他脚本访问此变量,因此为了加分,您可以使用 SerializeField 属性序列化私有变量,并在检查器中分配它。
[SerializeField] private Transform projectile;
然后您将可以立即访问射弹,而无需任何查找开销,也不用担心中断查找。
你的设计理念肯定会随着你的进步而发生很大变化,我认为你不应该将任何此类数据与逻辑联系起来 类(以防万一有人提到这一点) ,但我认为从更改查找结构开始是朝着正确方向迈出的重要一步。