在循环内更改游戏对象时实例化不起作用
Instantiate doesn't work when changing GameObject within loop
我有这两个代码,它们在理论上做同样的事情,但在实践中表现非常不同,我想知道 why/how 来修复它。
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
如您所见,我正在实例化一个 GameObject,它是在我的两个 for 循环之外创建的,并且在另一个示例中可以正常工作
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (ReturnBlock (BlockKind), new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
我在做同样的事情,但这次我在循环中获取我的游戏对象,程序只实例化一次(我检查了我的代码,所有的东西都被调用了,returned the way我想要它,only instantiate 没有表现得像它应该的那样)
我从测试中得出的理论是,GameObject 在循环的每一次传递中都被创建,但它在下一次传递时被删除并再次创建,这可能不是真的,但现在,我不有什么更好的。所有游戏对象都是从同一个预制件创建的,因此可能存在一些继承问题。这是 return 我的 GameObject
的代码
GameObject ReturnBlock(BlockType Type){
if (Type == BlockType.Soft) {
GameObject SoftBlock = Resources.Load("GameBorderPrefab") as GameObject;
SoftBlock.name = "SoftBlock";
SoftBlock.tag = "Soft"; //Sets a tag for that gameobject
SoftBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Soft") {
TextureName = GameManager.Bricks [i].TextureName;
SoftBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
SoftBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return SoftBlock;
}if (Type == BlockType.Medium) {
GameObject MediumBlock = Resources.Load("GameBorderPrefab") as GameObject;
MediumBlock.name = "MediumBlock";
MediumBlock.tag = "Medium";
MediumBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Medium") {
TextureName = GameManager.Bricks [i].TextureName;
MediumBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
MediumBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return MediumBlock;
}else{//if (Type == BlockType.Hard) {
GameObject HardBlock = Resources.Load ("GameBorderPrefab") as GameObject;
HardBlock.name = "HardBlock";
HardBlock.tag = "Hard";
HardBlock.AddComponent<HitCounter> ();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Hard") {
TextureName = GameManager.Bricks [i].TextureName;
HardBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse (GameManager.Bricks [i].HitPoints);
}
}
HardBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return HardBlock;
}
}
经过进一步测试,我编写了这段代码,它的行为与我提供的第一段代码一样,希望我能看到创建了三行不同的对象。只有第一个 Instantiate 按预期工作,其他的没有做任何事情,但是 我所有的打印功能都按您预期的那样工作
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
int j = 1;
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 2;
BlockKind = BlockType.Soft;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 3;
BlockKind = BlockType.Medium;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
解决方案在于Unity无法将正在实例化的内容与作为空预制件保存在Resources文件夹中的内容分开,这就是为什么实例化函数会在第二次调用ReturnBlock( ) 功能。我通过为我的每一种块类型从头开始创建一个新的预制件来修复我的错误,它是否优化 no,这是一个好的做法吗no,但现在它已经完成了工作。
TL;DR 不要使用一个预制件来实例化多个对象,否则继承就会开始,你就会遇到麻烦。
我有这两个代码,它们在理论上做同样的事情,但在实践中表现非常不同,我想知道 why/how 来修复它。
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
如您所见,我正在实例化一个 GameObject,它是在我的两个 for 循环之外创建的,并且在另一个示例中可以正常工作
void BlockPlacer(){ //Places breakable objects
BlockType BlockKind = BlockType.Hard;
while(true){
for(int j = 1; j < 4; j++){
for(float i = -width; i < width; i++){
GameObject created = Instantiate (ReturnBlock (BlockKind), new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
}
break;
}
}
我在做同样的事情,但这次我在循环中获取我的游戏对象,程序只实例化一次(我检查了我的代码,所有的东西都被调用了,returned the way我想要它,only instantiate 没有表现得像它应该的那样)
我从测试中得出的理论是,GameObject 在循环的每一次传递中都被创建,但它在下一次传递时被删除并再次创建,这可能不是真的,但现在,我不有什么更好的。所有游戏对象都是从同一个预制件创建的,因此可能存在一些继承问题。这是 return 我的 GameObject
的代码GameObject ReturnBlock(BlockType Type){
if (Type == BlockType.Soft) {
GameObject SoftBlock = Resources.Load("GameBorderPrefab") as GameObject;
SoftBlock.name = "SoftBlock";
SoftBlock.tag = "Soft"; //Sets a tag for that gameobject
SoftBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Soft") {
TextureName = GameManager.Bricks [i].TextureName;
SoftBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
SoftBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return SoftBlock;
}if (Type == BlockType.Medium) {
GameObject MediumBlock = Resources.Load("GameBorderPrefab") as GameObject;
MediumBlock.name = "MediumBlock";
MediumBlock.tag = "Medium";
MediumBlock.AddComponent<HitCounter>();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Medium") {
TextureName = GameManager.Bricks [i].TextureName;
MediumBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse(GameManager.Bricks [i].HitPoints);
}
}
MediumBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return MediumBlock;
}else{//if (Type == BlockType.Hard) {
GameObject HardBlock = Resources.Load ("GameBorderPrefab") as GameObject;
HardBlock.name = "HardBlock";
HardBlock.tag = "Hard";
HardBlock.AddComponent<HitCounter> ();
string TextureName = "";
for (int i = 0; i < GameManager.Bricks.Count; i++) {
if (GameManager.Bricks [i].ID == "Hard") {
TextureName = GameManager.Bricks [i].TextureName;
HardBlock.GetComponent<HitCounter> ().HP = System.Int32.Parse (GameManager.Bricks [i].HitPoints);
}
}
HardBlock.GetComponent<Renderer> ().material = Resources.Load (TextureName) as Material;
return HardBlock;
}
}
经过进一步测试,我编写了这段代码,它的行为与我提供的第一段代码一样,希望我能看到创建了三行不同的对象。只有第一个 Instantiate 按预期工作,其他的没有做任何事情,但是 我所有的打印功能都按您预期的那样工作
BlockType BlockKind = BlockType.Hard;
GameObject Block = ReturnBlock (BlockKind);
int j = 1;
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 2;
BlockKind = BlockType.Soft;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
j = 3;
BlockKind = BlockType.Medium;
Block = ReturnBlock (BlockKind);
for(float i = -width; i < width; i++){
GameObject created = Instantiate (Block, new Vector3 (i, height - j, 10), Quaternion.Euler (0, 0, 0));
print (created.transform.position);
}
解决方案在于Unity无法将正在实例化的内容与作为空预制件保存在Resources文件夹中的内容分开,这就是为什么实例化函数会在第二次调用ReturnBlock( ) 功能。我通过为我的每一种块类型从头开始创建一个新的预制件来修复我的错误,它是否优化 no,这是一个好的做法吗no,但现在它已经完成了工作。
TL;DR 不要使用一个预制件来实例化多个对象,否则继承就会开始,你就会遇到麻烦。