等距网格中的夹钳动作距离

问题描述

我目前正在开发一款 2D 等距游戏,玩家将能够控制不同的单位,并通过它们进行交互。

我创建了一个名为 UnitType 的可编写脚本的对象。多亏了这个系统,我可以定义一个动作范围和一个移动范围,即玩家可以移动到或与之交互的单元格中的最大距离。

问题是我不知道如何通过代码实现这一点。这就是我想要实现的,使用 2 个单元格的动作范围进行演示。 This is the goal

和我的一个朋友一起,我们考虑计算这 4 条线的线性方程,以检查光线投射是否在其中,但它不适用于负 x。 This is the current system

最佳做法是什么?

非常感谢您的时间和关注,

解决方法

Mousehit 是一个 Unity 游戏对象,它是角色的孩子。由于 mousePosition 是一个附加到 GameManager 的脚本,所以它的位置被绑定到了 tilemap 单元的中心。

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

public class Interact : MonoBehaviour
{
    [SerializeField] private Sprite upperLeft,upperRight,midLeft,midRight,bottomLeft,bottomMid,bottomRight;
    [SerializeField] private GameObject mouseHit;
    public UnitType unitType;
    private GameObject gameManager;
    private CheckMousePosition mousePosition;
    private bool isInteracting,isAtGoodDistance;
    private SpriteRenderer spriteRenderer;
    private Tilemap tilemap;
    private RaycastHit2D hit;
    //private Transform mouseHit;
    void Start()
    {
        tilemap = GameObject.Find("Tilemap").GetComponent<Tilemap>();
        gameManager = GameObject.FindGameObjectWithTag("GameManager");
        mousePosition = gameManager.GetComponent<CheckMousePosition>();
        spriteRenderer = gameObject.GetComponent<SpriteRenderer>();

        isInteracting = false;
        mouseHit.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        if (isInteracting)
        {
            mouseHit.SetActive(true);
            mouseHit.transform.position = new Vector3(mousePosition.tilemap.GetCellCenterLocal(mousePosition.cellPosition).x,mousePosition.tilemap.GetCellCenterLocal(mousePosition.cellPosition).y,1);

           

            if (Input.GetMouseButtonDown(0))
            {
                Interaction();
            }
        }

        if (isInteracting == false)
        {
            spriteRenderer.sprite = null;
            mouseHit.SetActive(false);
        }
    }

    public void InitInteraction()
    {
        isInteracting = true;
        transform.root.GetComponent<ContextualMenu>().CloseContextualMenu();
    }

    private void Interaction()
    {
        //When the player interacts,we cast a ray that will determine what he is interacting with.
        hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition),Vector2.zero);
        if (hit.collider != null)
        {
            if (isInteracting)
            {
                isInteracting = false; //the player is no longer interacting.

                //If the player is interacting with a farmable cell using the worker.
                if (transform.root.name == "Worker"
                    && hit.collider.GetComponent<FarmableCell>() != null)
                {
                    CheckInteractionDistance();
                    //hit.collider.GetComponent<FarmableCell>().CheckIfFarmed();
                }
            }
        }
    }

    private void CheckInteractionDistance()
    {
        if (mouseHit.transform.localPosition.y <= (-0.5 * (mouseHit.transform.localPosition.x) + unitType.actionDistance / 2)
            && mouseHit.transform.localPosition.x >= (-0.5 * (mouseHit.transform.localPosition.x) - unitType.actionDistance / 2)
            && mouseHit.transform.localPosition.x >= (0.5 * (mouseHit.transform.localPosition.x) - unitType.actionDistance / 2)
            && mouseHit.transform.localPosition.x <= (0.5 * (mouseHit.transform.localPosition.x) + unitType.actionDistance / 2))
        {
            Debug.Log("ok");
        }
        else
        {
            Debug.Log("not ok");
        }
    }
}