如何检测玩家在网格中的位置?

时间:2019-09-11 13:39:11

标签: c# unity3d

我正在开发战术RPG,但有一个名为Map的空游戏对象,该对象由36个图块组成。

Map对象附加了以下脚本:

using System.Collections.Generic;
using UnityEngine;

public class GridMap : MonoBehaviour
{
    private GameObject[] MyVector = new GameObject[36];
    public GameObject[,] GridMatrix = new GameObject[6,6];

    public GameObject Map;

    // Start is called before the first frame update
    void Awake()
    {
        for (int i = 0; i < 36; i++)
        {
            try
            {
                MyVector[i] = Map.transform.GetChild(i).gameObject;
            }
            catch
            {
                print("Something is wrong!");
            }
        }
    }

    void Start()
    {
        int Counter = 0;

        for (int i = 0; i < 6; i++)
        {
            for (int j = 0; j < 6; j++)
            {
                GridMatrix[i, j] = MyVector[Counter];
                Counter;
            }
        }
    }

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

    }
}

每个图块都有此脚本:

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

public class Tile : MonoBehaviour
{
    public bool Current = false;
    public bool Selectable = false;

    public bool MouseOver = false;
    public bool Clicked = false;

    // Start is called before the first frame update
    void Start()
    {

    }

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

    }

    void OnMouseOver()
    {
        MouseOver = true;
        if (Clicked == false)
        {
            GetComponent<Renderer>().material.color = Color.red;

        }

        if (Input.GetMouseButton(0))
        {
            Clicked = true;
            GetComponent<Renderer>().material.color = Color.green;


        }
    }

    void OnMouseExit()
    {
        MouseOver = false;
        Clicked = false;

        GetComponent<Renderer>().material.color = Color.white;
    }


    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "Player")
        {
            GetComponent<Renderer>().material.color = Color.magenta;
            Current = true;

        }


    }

    private void OnTriggerExit(Collider other)
    {
        GetComponent<Renderer>().material.color = Color.white;
        Current = false;

    }

}

就实例而言,我想检测玩家所在的图块:如果玩家位于矩阵中位置为0,0的图块中,我想在控制台中显示以下内容: “玩家的位置为0,0'。

我已经创建了此脚本并将其附加到播放器上,以获取其在地图(网格)中的位置,但是不起作用:

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

public class GetPlayerPosition : MonoBehaviour
{
    private GameObject mapgrid;
    GridMap map;



    float tileX, tileY;
    // Start is called before the first frame update
    void Start()
    {

        mapgrid = GameObject.FindGameObjectWithTag("map");
        map = mapgrid.GetComponent<GridMap>();

        for (int i = 0; i < 6; i++)
        {
            for (int j = 0; j < 6; j++)
            {
                Tile tile = map.GridMatrix[i, j].GetComponent<Tile>();

                if (tile.Current)
                {
                    tileX = i;
                    tileY = j;

                    Debug.Log(tileX);
                    Debug.Log(tileY);
                }
            }
        }
    }

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

    }
}

我该怎么做才能解决这个问题? Print of the project. The black cylinder is the player

1 个答案:

答案 0 :(得分:0)

  1. 首先,我要输入

    private Tile[] MayVector = new Tile[36];
    public Tile[,] GridMatrix = new Tile[6,6];
    

    因此您可以避免所有昂贵的GetComponent<Tile>通话,而只需拨打一次。

  2. 我也宁愿使用OnTriggerEnter,它只调用一次,而不是OnTriggerStay,每帧都调用一次。而OnMouseEnter的第一部分是OnMouseOver,因为仅需设置一次即可。

  3. 我将使用FindObjectOfType或什至更好(如果可能)通过Inspector引用所有内容,而不是使用GameObject.FindGameObjectWithTagGetComponent

  4. 还应该填充GridMatrix中的Awake数组。否则,可能会在Start的{​​{1}}方法之前之前执行GetPlayerPosition的{​​{1}},因此请尝试在不存在的时候访问该数组。尚未填写,仅包含Start个元素→ GridMap

    我对nullNullReferenceException的一般经验法则:

    • Awake:做所有不依赖他人的事情,设置自己的引用和值,使用Start等来查找场景引用

    • Awake:根据已设置的引用来执行操作。就像其他人的访问字段一样。

  5. 然后,我将使整个事件更多地受事件驱动,而不是让玩家一直在所有磁贴之间循环,而是让磁贴设置玩家的位置:


类似

GetComponent

然后在 GridMap 中告诉Start他们的位置

public class Tile : MonoBehaviour
{
    // maybe not needed anymore
    public bool Current = false;

    public bool Selectable = false;

    public bool MouseOver = false;
    public bool Clicked = false;

    // Will be assigned by the GridMap script
    // so every tile will know it's own position
    // you could also assign this via the Inspector
    // but maybe a lot overhead for 36 tiles ;)
    public Vector2Int TilePosition;

    // The player will register itself here
    // you could even already reference this via the Inspector
    // select all tiles and simply drag the player object here
    public GetPlayerPosition getPlayerPosition;

    // would even be better to already reference this via the Inspector
    // but maybe a bit overhead for 36 tiles 
    // except this is a prefab (what it probably should be ;) )
    [SerializeField] private Renderer renderer;

    private void Awake ()
    {
        // do this only once
        if(!renderer) renderer = GetComponent<Renderer>();
    }

    private void OnMouseEnter()
    {
        // do this only once .. no need to do it every frame
        MouseOver = true;
        renderer.material.color = Color.red;
    }

    private void OnMouseOver()
    {
        // skip further API calls if already Clicked
        if(Clicked) return;

        if (Input.GetMouseButton(0))
        {
            Clicked = true;
            renderer.material.color = Color.green;
       }
    }

    private void OnMouseExit()
    {
        MouseOver = false;
        Clicked = false;

        renderer.material.color = Color.white;
    }

    private void OnTriggerEnter(Collider other)
    {
        // do all these only once .. no need to do it every frame

        if(other.tag != "Player") return;

        renderer.material.color = Color.magenta;
        // Tell the player it's current position
        playerPosition.GridPosition = TilePosition;
        // probably not needed anymore
        Current = true;
    }

    private void OnTriggerExit(Collider other)
    {
        if(other.tag != "Player") return;

        renderer.material.color = Color.white;
        // probably not needed anymore
        Current = false;
    }
}

现在剩下的就是玩家必须注册到Tiles:

Tile