如何通过脚本在 Unity 中重新定位和调整游戏对象的大小?

Posted

技术标签:

【中文标题】如何通过脚本在 Unity 中重新定位和调整游戏对象的大小?【英文标题】:How do I reposition and resize gameObjects in Unity via scripting? 【发布时间】:2021-09-27 10:36:38 【问题描述】:

所以我试图在 Unity 中构建一个类似于 Snakes and Ladders 游戏的游戏,但是当多个玩家令牌落在同一个方格上时,我发现很难处理。

我的场景中有以下游戏对象:

单击 Player1 按钮后,其中一个玩家标记(圆柱形游戏对象)前进到第一个方格(骰子被硬编码为每次掷 1 以进行测试),如下所示:

现在,当单击 Player2 按钮时,另一个玩家令牌应该会前进到第一个方格,但是它会与第一个玩家令牌重叠,看起来现在场景中只有一个玩家令牌,如下所示:

我正在尝试找到一种方法来调整两个标记的大小和位置,以便它们之间有足够的空间并且它们仍然保持在同一个正方形上。

此外,一旦玩家令牌离开方格并前进到另一个方格,我需要根据每个方格上是否存在其他玩家令牌(当然,如果超过 2 名玩家)来调整两个方格上的玩家令牌的大小,或者不是

我在单击按钮时调用的方法中尝试了以下方法:

public void MovePlayerToken(GameObject currentPlayer)
    
        var startingSquare = currentPlayer.GetComponent<PlayerToken>().StartingSquare;

        var landingSquare = GetLandingSquare(startingSquare);

        var existingPlayerTokensOnLandingSquare = GetExistingPlayerTokens(playerTokens, landingSquare);
        //var existingPlayerTokensOnStartingSquare = GetExistingPlayerTokens(playerTokens, startingSquare);

        if (existingPlayerTokensOnLandingSquare.Count > 0)
        
            TransformPlayerTokens(existingPlayerTokensOnLandingSquare, landingSquare, SquareType.LandingSquare);

            if (currentPlayer.transform.localScale == new Vector3(1, 1, 1))
            
                currentPlayer.transform.localScale = new Vector3(currentPlayer.transform.localScale.x / 2,
                    currentPlayer.transform.localScale.y / 2,
                    currentPlayer.transform.localScale.z / 2);
            

            switch (existingPlayerTokensOnLandingSquare.Count)
            
                case 1:
                    existingPlayerTokensOnLandingSquare[0].transform.position = new Vector3(landingSquare.transform.localPosition.x + 0.25f, landingSquare.transform.localPosition.y, landingSquare.transform.localPosition.z + 0.25f);
                    currentPlayer.transform.position = new Vector3(landingSquare.transform.localPosition.x + -0.25f, landingSquare.transform.localPosition.y, landingSquare.transform.localPosition.z + -0.25f);
                    break;
                case 2:
                    existingPlayerTokensOnLandingSquare[0].transform.position = new Vector3(landingSquare.transform.localPosition.x + 0.25f, landingSquare.transform.localPosition.y, landingSquare.transform.localPosition.z + 0.25f);
                    existingPlayerTokensOnLandingSquare[1].transform.position = new Vector3(landingSquare.transform.localPosition.x + -0.25f, landingSquare.transform.localPosition.y, landingSquare.transform.localPosition.z + -0.25f);
                    currentPlayer.transform.position = landingSquare.transform.position;
                    break;
            
        
        else
        
            currentPlayer.transform.position = landingSquare.transform.position;
        

        currentPlayer.GetComponent<PlayerToken>().StartingSquare = landingSquare;
    

    private Square GetLandingSquare(Square startingSquare)
    
        Square landingSquare = startingSquare;

        for (int i = 0; i < _stateManager.DiceTotal; i++)
        
            if (landingSquare.NextSquares.Length > 1)
                landingSquare = landingSquare.NextSquares[Random.Range(0, landingSquare.NextSquares.Length)];
            else
                landingSquare = landingSquare.NextSquares[0];
        

        return landingSquare;
    

    private List<PlayerToken> GetExistingPlayerTokens(PlayerToken[] playerTokens, Square square)
    
        List<PlayerToken> existingPlayerTokens = new List<PlayerToken>();

        foreach (var playerToken in playerTokens)
        
            if (playerToken.transform.position == square.transform.position ||
                playerToken.transform.position == new Vector3(square.transform.localPosition.x + 0.25f, square.transform.localPosition.y, square.transform.localPosition.z + 0.25f) ||
                playerToken.transform.position == new Vector3(square.transform.localPosition.x + -0.25f, square.transform.localPosition.y, square.transform.localPosition.z + -0.25f))
            
                existingPlayerTokens.Add(playerToken);
            
        

        return existingPlayerTokens;
    

    private void TransformPlayerTokens(List<PlayerToken> existingPlayerTokens, Square landingSquare, SquareType squareType)
    
        foreach (var playerToken in existingPlayerTokens)
        
            if(playerToken.transform.localScale == new Vector3(1, 1, 1))
            
                playerToken.transform.localScale = new Vector3(
                    playerToken.transform.localScale.x / 2,
                    playerToken.transform.localScale.y / 2,
                    playerToken.transform.localScale.z / 2
                    );
            
        
    

这种方法的问题在于,玩家代币越多,需要的硬编码就越多……我真的不喜欢这种方法,我相信有更好的方法可以使用物理引擎或一些东西(顺便说一句,我是一个完整的新手,以前从未使用过 Unity - 这是我的第一个项目,所以请期待我对物理引擎知之甚少)

谢谢。

【问题讨论】:

不确定这是否适用于物理(尤其是所需的收缩部分)。但可以肯定的是,您可以创建一种算法,将它们放在正方形内的网格上。 1x1 网格上的 1 名球员,2x2 网格上的 2-4 名球员,3x3 上的 5-9 名球员,依此类推。这种方式没有硬编码,单个算法可以解决所有数量的玩家。 @PmDuda 谢谢.. 我会统一研究网格! 【参考方案1】:

您可以使用 GameObject.transform.position =(此处为新位置)重新定位。

【讨论】:

如果你真的阅读了这个问题,你会意识到 OP 已经知道这一点,而这不是问题所在。【参考方案2】:

对于调整大小,您可以这样做

var players = existingPlayerTokensOnLandingSquare.Count + 1;
currentPlayer.transform.localScale = new Vector3(currentPlayer.transform.localScale.x / players,
                    currentPlayer.transform.localScale.y / players,
                    currentPlayer.transform.localScale.z / players);

不知道重新定位,或者现在无法考虑。希望其他人可以回答这个问题。

【讨论】:

定位可以用物理学来完成。在它们上面放置对撞机和刚体,然后在正方形区域周围建造墙壁,或者如果它们离开该区域,则使用脚本将它们移回,无论我猜哪个可行。太大了,我在这里回答,希望你能弄清楚。 或者你可以把它们放在一个网格中,就像我刚刚注意到的其他评论一样。 我确实给了我的方格刚体,并且当玩家令牌前进到方格时,我在掷骰子时能够在 onTriggerEnter 方法中获取当前玩家令牌对象,但不知道如何以识别特定方格上是否存在其他玩家棋子。

以上是关于如何通过脚本在 Unity 中重新定位和调整游戏对象的大小?的主要内容,如果未能解决你的问题,请参考以下文章

unity游戏自定义分辨率 教你如何自定义

如何让约束自动调整大小和重新定位横向键盘键

Unity 游戏用XLua的HotFix实现热更原理揭秘

unity的PUN如何同步自定义脚本

Unity3D:如何确定游戏对象的角以便根据它定位其他游戏对象?

unity摄像头怎么随着游戏对象移动