Unity:协程无法启动,因为游戏对象 'Player' 处于非活动状态
Unity: coroutine couldn't start because the game object 'Player' is inactive
所以,我在 Unity 中遇到了这个问题,我在 GameManager 中创建了一个玩家,然后将其实例化为 BoardManager 并想在 GameManager 中使用回合系统,玩家脚本在另一个名为 PlayerScript.txt 的文件中。我想在 BoardManager 中创建播放器,然后在 GameManager 中使用它。当我尝试调用函数 movement() 时,出现错误“协程无法启动,因为游戏对象 'Player' 处于非活动状态”。
Obs1:我将玩家分配给 instance2,以便我可以在 GameManager 中使用它。
Obs2:问题出在没有初始化的协程中,所有的动作都在工作,调用方法也是,在我看来是玩家不存在之类的所以函数无法调用,我测试了代码不同的方式,但似乎没有任何效果。
在此先感谢您的帮助:)
下面的代码来自 BoardManager:
//map = grid of 50 per 50 of numbers, these numbers says if a floor, wall, player,
//enemies, etc are going to be placed in the grid done from procedural generation
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
if (map[i,j] == 0)
{
GameObject instance = Instantiate(wallTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
}
if (map[i,j] == 1)
{
GameObject instance = Instantiate(floorTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
}
if (map[i,j] == 2)
{
GameObject instance1 = Instantiate(floorTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
GameObject instance2 = Instantiate(player, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
player = instance2;
}
}
}
下一段代码来自 GameManager:
基本上我尝试从地图中的播放器获取脚本并使用此脚本中的移动功能。
public class GameManager : MonoBehaviour
{
public static BoardManager boardScript;
private int PLAYER_TURN = 1;
private int ENEMY_TURN = 2;
private int game_state;
public GameObject player;
void Awake()
{
int[,] map = new int[0,0];
boardScript = GetComponent<BoardManager>();
boardScript.makeMap(map, player);
}
public void Update()
{
game_state = PLAYER_TURN;
if(Input.anyKey)
{
char c = Input.inputString[0];
player.GetComponent<PlayerScript>().movement(c);
game_state = ENEMY_TURN;
}
}
}
}
下一段代码来自PlayerScript
public class PlayerScript : MonoBehaviour
{
private bool isMoving;
private Vector3 origPos, targetPos;
private float timeToMove = 0.2f;
public void movement(char c)
{
if (c == 'w' && !isMoving)
StartCoroutine(movePlayer(Vector3.up));
if (c == 'a' && !isMoving)
StartCoroutine(movePlayer(Vector3.left));
if (c == 's' && !isMoving)
StartCoroutine(movePlayer(Vector3.down));
if (c == 'd' && !isMoving)
StartCoroutine(movePlayer(Vector3.right));
if (c == 'q' && !isMoving)
StartCoroutine(movePlayer(new Vector3(-1, 1, 0)));
if (c == 'e' && !isMoving)
StartCoroutine(movePlayer(new Vector3(1, 1, 0)));
if (c == 'c' && !isMoving)
StartCoroutine(movePlayer(new Vector3(1, -1, 0)));
if (c == 'z' && !isMoving)
StartCoroutine(movePlayer(new Vector3(-1, -1, 0)));
}
private IEnumerator movePlayer(Vector3 direction)
{
isMoving = true;
float elapsedTime = 0;
origPos = transform.position;
targetPos = origPos + direction;
while(elapsedTime < timeToMove)
{
transform.position = Vector3.MoveTowards(origPos, targetPos, (elapsedTime / timeToMove));
elapsedTime += Time.deltaTime;
yield return null;
}
transform.position = targetPos;
isMoving = false;
}
}
问题在于如何将 player
变量传递给 boardscript.MakeMap()
函数。由于函数参数,除非指定,否则按值传递而不是按引用传递。这意味着您实际上是在为要使用的函数制作变量的副本。该函数可以为其局部范围为该变量分配一个值,但它不会影响在函数外部传入的变量。看这里:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
要解决这个问题,您可以使用 void makeMap(int[][] map, ref GameObject player)
,然后您需要调用它 boardScript.makeMap(map, ref player);
参考文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
所以,我在 Unity 中遇到了这个问题,我在 GameManager 中创建了一个玩家,然后将其实例化为 BoardManager 并想在 GameManager 中使用回合系统,玩家脚本在另一个名为 PlayerScript.txt 的文件中。我想在 BoardManager 中创建播放器,然后在 GameManager 中使用它。当我尝试调用函数 movement() 时,出现错误“协程无法启动,因为游戏对象 'Player' 处于非活动状态”。
Obs1:我将玩家分配给 instance2,以便我可以在 GameManager 中使用它。
Obs2:问题出在没有初始化的协程中,所有的动作都在工作,调用方法也是,在我看来是玩家不存在之类的所以函数无法调用,我测试了代码不同的方式,但似乎没有任何效果。
在此先感谢您的帮助:)
下面的代码来自 BoardManager:
//map = grid of 50 per 50 of numbers, these numbers says if a floor, wall, player,
//enemies, etc are going to be placed in the grid done from procedural generation
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
if (map[i,j] == 0)
{
GameObject instance = Instantiate(wallTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
}
if (map[i,j] == 1)
{
GameObject instance = Instantiate(floorTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
}
if (map[i,j] == 2)
{
GameObject instance1 = Instantiate(floorTile, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
GameObject instance2 = Instantiate(player, new Vector3(i, j, 0f), Quaternion.identity) as GameObject;
player = instance2;
}
}
}
下一段代码来自 GameManager: 基本上我尝试从地图中的播放器获取脚本并使用此脚本中的移动功能。
public class GameManager : MonoBehaviour
{
public static BoardManager boardScript;
private int PLAYER_TURN = 1;
private int ENEMY_TURN = 2;
private int game_state;
public GameObject player;
void Awake()
{
int[,] map = new int[0,0];
boardScript = GetComponent<BoardManager>();
boardScript.makeMap(map, player);
}
public void Update()
{
game_state = PLAYER_TURN;
if(Input.anyKey)
{
char c = Input.inputString[0];
player.GetComponent<PlayerScript>().movement(c);
game_state = ENEMY_TURN;
}
}
}
}
下一段代码来自PlayerScript
public class PlayerScript : MonoBehaviour
{
private bool isMoving;
private Vector3 origPos, targetPos;
private float timeToMove = 0.2f;
public void movement(char c)
{
if (c == 'w' && !isMoving)
StartCoroutine(movePlayer(Vector3.up));
if (c == 'a' && !isMoving)
StartCoroutine(movePlayer(Vector3.left));
if (c == 's' && !isMoving)
StartCoroutine(movePlayer(Vector3.down));
if (c == 'd' && !isMoving)
StartCoroutine(movePlayer(Vector3.right));
if (c == 'q' && !isMoving)
StartCoroutine(movePlayer(new Vector3(-1, 1, 0)));
if (c == 'e' && !isMoving)
StartCoroutine(movePlayer(new Vector3(1, 1, 0)));
if (c == 'c' && !isMoving)
StartCoroutine(movePlayer(new Vector3(1, -1, 0)));
if (c == 'z' && !isMoving)
StartCoroutine(movePlayer(new Vector3(-1, -1, 0)));
}
private IEnumerator movePlayer(Vector3 direction)
{
isMoving = true;
float elapsedTime = 0;
origPos = transform.position;
targetPos = origPos + direction;
while(elapsedTime < timeToMove)
{
transform.position = Vector3.MoveTowards(origPos, targetPos, (elapsedTime / timeToMove));
elapsedTime += Time.deltaTime;
yield return null;
}
transform.position = targetPos;
isMoving = false;
}
}
问题在于如何将 player
变量传递给 boardscript.MakeMap()
函数。由于函数参数,除非指定,否则按值传递而不是按引用传递。这意味着您实际上是在为要使用的函数制作变量的副本。该函数可以为其局部范围为该变量分配一个值,但它不会影响在函数外部传入的变量。看这里:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
要解决这个问题,您可以使用 void makeMap(int[][] map, ref GameObject player)
,然后您需要调用它 boardScript.makeMap(map, ref player);
参考文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref