我制作了一个预制件,并将其拖放到Tile Prefab插槽中,如图所示
在我的代码中
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameGrid :MonoBehaviour
{
private int width;
private int height;
private int[,] gridArray;
private float cellSize;
[SerializeField]
GameObject tilePrefab;// = default;
public GameGrid(int width, int height, float cellSize)
{
this.width = width;
this.height = height;
this.cellSize = cellSize;
gridArray = new int[width, height];
Debug.Log(width + " " + height);
for(int x = 0; x < gridArray.GetLength(0); x++)
{
for(int z = 0; z < gridArray.GetLength(1); z++)
{
GameObject tile =Instantiate(tilePrefab);
tile.transform.SetParent(transform, false);
tile.transform.localPosition = GetWorldPosition(x,z);
}
}
}
private Vector3 GetWorldPosition(int x, int z, int y = 0)
{
return new Vector3(x, 0, z) * cellSize;
}
}
1。它抛出错误,ArgumentException:您要实例化的对象为null,这很奇怪,因为我在检查器中分配了Prefab,这可能会出错,并且控制台没有告诉您,这很奇怪.我哪一行错了。
2。另一个错误是"您正在尝试使用'new'关键字创建MonoBehaviour。这是不允许的。",这让我感到困惑,因为我什么也没做。
3。这行代码" tile.transform.SetParent(transform,false);" 我从其他我不完全理解的资源中复制了内容,我查看了Unity菜单仍然不了解它的功能,它设置了setParent,但是此函数尝试设置的父属性是试图设置其父对象的转换还是 什么?
非常感谢我仍然是Unity的新手。
编辑: 这是我的testing.cs
public class Testing : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
GameGrid grid = new GameGrid(20, 10, 1);
}
}
1。删除默认分配也不起作用。 2.关于setParent,我没有父母,那么这个child要与哪个父母相连,如果这个函数将实例化一个父母,那么就没有信息提供给父母的创建,仍然很困惑。
最新回答
- 2021-1-41 #
您在这里执行此操作:
GameGrid grid = new GameGrid(20, 10, 1);
通过构造函数创建MonoBehaviour无效,因为它们只能在GameObject的上下文中创建.因此,它们不应具有构造函数. MonoBehaviours应该作为场景的一部分通过编辑器创建,或者如果您真的想通过代码添加它们(如果可以避免,则不应该这样做),您必须使用GameObject.AddComponent
方法如果您仍然尝试通过构造函数创建MonoBehavior,那么Unity将无法填充任何公共变量,这就是为什么稍后会出现NullReferenceException的原因.在检查器中设置的内容无关紧要,因为您没有在检查器中使用该GameGrid.您将在此处创建一个新的单独GameGrid,该GameGrid与检查器之间没有任何连接。
当您的MonoBehaviour需要一些初始化代码时,那么该代码应该在
void Start()
中 方法.您可能会注意到此方法不接受任何参数.当MonoBehaviour初始化需要一些信息时,您需要预先设置该信息.当您将MonoBehaviour附加到GameObject时(建议的做事方式),请使这些变量public
并将它们放在检查器中。如果要在运行时创建具有MonoBehaviour的对象,则:
使用
GameObject newGo = new GameObject()
创建一个新的GameObject .或者,获取对现有GameObject的引用以向其添加MonoBehaviour。创建一个新的MonoBehaviour,并使用
GameGrid grid = newGo.AddComponent<GameGrid>() as GameGrid
将其附加到该新的gameObject上 .这将创建一个新组件,并将所有公共变量设置为默认值,但尚未运行Start方法。像这样设置每个公共变量:
grid.width = 20;
.或者,您也可以创建自己的公共初始化方法并调用它。该新对象的Start方法将在下一帧之前执行。
但是我有点困惑为什么您首先拥有那个Testing.cs脚本,因为您的第一张图片显示您已经创建了一个名为" Grid"的GameObject,并在编辑器中附加了GameGrid组件.因此,没有理由通过代码创建另一个.虽然我不确定您到底要做什么,但是您可能不需要该脚本。
关于这条线:
tile.transform.SetParent(transform, false);
:这会将新实例化的图块附加到实例化它的gameObject上.transform
这里指的是脚本附加到的对象的Transform组件.转换组件也是管理父/子关系的组件.这就是为什么SetParent
期待新父母的转变。