统一更新多维数组

问题描述 投票:0回答:1

我目前正在 Unity 引擎中开发一款三消游戏类型,并为此使用了一些宝石艺术品。我遇到过一种情况,将宝石位置存储在二维数组中并交换它们后,我需要再次更新数组。

我有两个问题:

考虑到已经更新过的二维数组,为什么我们还需要再次更新它? 这个概念在编程中叫什么? 您能推荐一本书或教程来了解更多信息吗?

请注意,无需阅读所有代码;请只关注我在评论中提到的部分

1级:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Board : MonoBehaviour
{
public int width;
public int height;
public GameObject backgroundTilePrefab;

public Gem[] gems;

//this one
public Gem[,] allGems;

public float gemSpeed;

public MatchFinder matchFinder;

private void Awake()
{
    matchFinder = FindObjectOfType<MatchFinder>();
}
private void Start()
{  
    //this one
    allGems = new Gem[width, height];
    
    Setup();
    

}

private void Update()
{
    matchFinder.FindAllMatches();
}
private void Setup()
{
    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            Vector2 pos = new Vector2(x, y);
            GameObject backgroundTile = Instantiate(backgroundTilePrefab,pos,Quaternion.identity);
            backgroundTile.transform.parent = transform;
            backgroundTile.transform.name = "Background Tile " + x + "," + y;

            int gemToUse = Random.Range(0, gems.Length);

            int iterations = 0;
            while (MatchesAt(new Vector2Int(x,y), gems[gemToUse]) && iterations < 100)
            {
                gemToUse = Random.Range(0, gems.Length);
                print("already matched found");
                iterations++;
            }

            SpawnGem(gems[gemToUse],new Vector2Int(x,y));

            
        }
    }
}

private void SpawnGem(Gem gemToSpawn,Vector2Int pos)
{
    Gem gem = Instantiate(gemToSpawn,new Vector3(pos.x,pos.y,0),Quaternion.identity);
    gem.transform.parent = transform;
    gem.transform.name = "Gem " + pos.x + "," + pos.y;

    //this one
    allGems[pos.x, pos.y] = gem;

    gem.SetupGem(pos,this);
}

bool MatchesAt(Vector2Int posToCheck, Gem gemToCheck)
{
    if (posToCheck.x > 1)
    {
        if (allGems[posToCheck.x - 1,posToCheck.y].gemTypes == gemToCheck.gemTypes && allGems[posToCheck.x - 2, posToCheck.y].gemTypes == gemToCheck.gemTypes)
        {
            return true;
        }
    }


    if (posToCheck.y > 1)
    {
        if (allGems[posToCheck.x, posToCheck.y - 1].gemTypes == gemToCheck.gemTypes && allGems[posToCheck.x, posToCheck.y -2].gemTypes == gemToCheck.gemTypes)
        {
            return true;
        }
    }

    return false;
}

public void DestroyMatchesGemAt(Vector2Int pos)
{
    if (allGems[pos.x,pos.y] != null)
    {
        if (allGems[pos.x,pos.y].isMatched)
        {
            Destroy(allGems[pos.x,pos.y].gameObject);
            allGems[pos.x,pos.y] = null;
        }
    }
}

public void DestroyMatches()
{
    for (int i=0; i < matchFinder.currentMatches.Count; i++)
    {
        if (matchFinder.currentMatches[i] != null)
        {
            DestroyMatchesGemAt(matchFinder.currentMatches[i].posIndex);
        }
    }
    StartCoroutine(DecreaseRowCoroutine());
}

public int nullCounter;
IEnumerator DecreaseRowCoroutine()
{
    yield return new WaitForSeconds(0.2f);

    nullCounter = 0;

    for (int x=0; x < width; x++)
    {
        for (int y=0;y<height;y++)
        {
            if (allGems[x,y] == null)
            {
                nullCounter++;

            }else if (nullCounter > 0)
            {
                
                allGems[x, y - nullCounter] = allGems[x, y];
                allGems[x, y - nullCounter].posIndex.y -= nullCounter;
                allGems[x, y] = null;

            }
        }
    }
}

}

2级:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gem : MonoBehaviour
{
public Vector2Int posIndex;
public Board board;
public enum GemTypes { blue, green, red,purple,yellow }
public GemTypes gemTypes;
public bool isMatched;

public Vector2Int previousPos;
// Start is called before the first frame update
void Start()
{
   
}

// Update is called once per frame
void Update()
{

    

    if (mousePressed && Input.GetMouseButtonUp(0))
    {
        mousePressed = false;
        finalTouchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        CalculateAngle();
        

    }

    if (Vector2.Distance(transform.position,posIndex) > 0.01f)
    {
        transform.position = Vector2.Lerp(transform.position, posIndex, board.gemSpeed * Time.deltaTime);
    }else
    {
        transform.position = new Vector3(posIndex.x,posIndex.y);
        board.allGems[posIndex.x,posIndex.y] = this;
    }
}

public void SetupGem(Vector2Int posIndex,Board board)
{
    this.posIndex = posIndex;
    this.board = board;
}

public Vector2 firstTouchPosition;
public bool mousePressed;
public Vector2 finalTouchPosition;
public float swipeAngle;


private void OnMouseDown()
{
    firstTouchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    //Debug.Log(firstTouchPosition);
    mousePressed = true;
}

private void CalculateAngle()
{
    swipeAngle = Mathf.Atan2(finalTouchPosition.y - firstTouchPosition.y, finalTouchPosition.x - firstTouchPosition.x);
    swipeAngle = swipeAngle * 180 / Mathf.PI;
    print(swipeAngle);

    if (Vector2.Distance(firstTouchPosition,finalTouchPosition) > 0.5f)
    {
        MovePieces();
    }
}

Gem otherGem;
private void MovePieces()
{

    previousPos = posIndex;

    //drag left to right
    
    if (swipeAngle < 45 && swipeAngle > -45 && posIndex.x < board.width - 1)
    {
        otherGem = board.allGems[posIndex.x + 1, posIndex.y];
        otherGem.posIndex.x--;
        posIndex.x++;
    }
    //drag down to up

    else if (swipeAngle > 45 && swipeAngle < 135 && posIndex.y < board.height - 1)
    {
        otherGem = board.allGems[posIndex.x , posIndex.y + 1];
        otherGem.posIndex.y--;
        posIndex.y++;
    }

    //drag up to down

    else if (swipeAngle < -45 && swipeAngle > -135 && posIndex.y  > 0)
    {
        otherGem = board.allGems[posIndex.x, posIndex.y - 1];
        otherGem.posIndex.y++;
        posIndex.y--;
    }

    //drag right to left

    else if (swipeAngle > 135 || swipeAngle < -135 && posIndex.x > 0)
    {
        otherGem = board.allGems[posIndex.x - 1, posIndex.y];
        otherGem.posIndex.x++;
        posIndex.x--;

    }
    //my main problem is these 2 following lines

    board.allGems[posIndex.x, posIndex.y] = this;
    board.allGems[otherGem.posIndex.x,otherGem.posIndex.y] = otherGem;

    

    StartCoroutine(CheckMoveCoroutine());

}//MovePieces()

public IEnumerator CheckMoveCoroutine()
{
    yield return new WaitForSeconds(0.5f);

    //board.matchFinder.FindAllMatches();

    if (otherGem != null)
    {
        if (!isMatched && !otherGem.isMatched)
        {
            otherGem.posIndex = posIndex;
            posIndex = previousPos;

            board.allGems[posIndex.x, posIndex.y] = this;
            board.allGems[otherGem.posIndex.x, otherGem.posIndex.y] = otherGem;
        }else
        {
            board.DestroyMatches();
        }
    }
}

}//类

arrays unity-game-engine multidimensional-array 2d game-development
1个回答
0
投票

如果我通过更新数组理解正确的话,你的意思是这部分:

private void SpawnGem(Gem gemToSpawn,Vector2Int pos)
{
    Gem gem = Instantiate(gemToSpawn,new Vector3(pos.x,pos.y,0),Quaternion.identity);
    gem.transform.parent = transform;
    gem.transform.name = "Gem " + pos.x + "," + pos.y;

    //this one
    allGems[pos.x, pos.y] = gem;

    gem.SetupGem(pos,this);
}

我认为您误解了

Instantiate
功能。当你调用
Instantiate
时,你应该给它一个对预制件的引用,然后它会将该预制件克隆到场景中的新游戏对象中。如果你给它一个场景中已经存在的游戏对象,它会做类似的事情(将其克隆到新的游戏对象中),这很可能不是所需的行为。

所以我认为这就是问题所在,

gem
是在这个方法中新创建的,没有人引用它,所以你需要在数组中分配它。实例化后,
gem
gemToSpawn
彼此无关。

或者也许我没有正确理解您的问题,如果是这样,请指定您遇到问题的代码部分,这些是要跟踪的很大一部分代码。

© www.soinside.com 2019 - 2024. All rights reserved.