【问题标题】:Unity: coroutine couldn't start because the game object 'Player' is inactiveUnity:协程无法启动,因为游戏对象“玩家”处于非活动状态
【发布时间】:2022-01-22 22:47:04
【问题描述】:

所以,我在 Unity 中遇到了这个问题,我在 GameManager 中创建了一个玩家,然后我将它实例化到 BoardManager 并想在 GameManager 中使用回合系统,玩家脚本位于另一个名为 PlayerScript 的文件中。我想在 BoardManager 中创建玩家,然后在 GameManager 中使用它。当我尝试调用函数 move() 时,我收到一个错误“协程无法启动,因为游戏对象 'Player' 处于非活动状态”。

Obs1:我将玩家分配给 instance2,以便我可以在 GameManager 中使用它。

Obs2:问题出在 Coroutine 没有初始化,所有动作都在工作,调用方法也在,在我看来,播放器不存在或无法调用函数,我用不同的方式测试了代码但似乎没有任何效果。

提前感谢您的帮助:)

以下代码来自 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;
    }
}

【问题讨论】:

    标签: c# unity3d coroutine gameobject


    【解决方案1】:

    问题在于您如何将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

    【讨论】:

    • 这解决了我的问题。我不知道我们可以传递对函数的引用。它有很大帮助。谢谢:)
    • Since function parameters, unless specified, pass by value instead of passing by reference. .. 不!这完全取决于参数类型是值类型(所有struct,例如intboolstring 等)还是引用类型(所有class,包括OP 的GameObject 和@987654335 @)。您的意思是在这种情况下,OP 试图在方法内重新分配 player 的值,默认情况下在方法范围之外不会产生任何影响,因此您需要使用 ref
    猜你喜欢
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多