Unity 2D射线检测对象问题

huangapple go评论75阅读模式
英文:

Unity 2D Raycast Detecting Object Problem

问题

它可以检测到光束,即使它经过物体也能检测到。我希望它在光束正好位于物体上时进行检测。

void RaycastSystem()
{
    Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
    Vector2 worldMousePosition = Camera.main.ScreenToWorldPoint(mousePosition);

    Vector2 rayDirection = worldMousePosition - (Vector2)transform.position;

    RaycastHit2D hit = Physics2D.Raycast(transform.position, rayDirection, rayDirection.magnitude, mask);
    Debug.DrawRay(transform.position, rayDirection, Color.red);
    //Debug.Log(worldMousePosition.x + " | " + worldMousePosition.y);

    if (hit.collider != null)
    {
        Debug.Log(hit.collider.gameObject);
    }
}

如何解决这个问题?

英文:

> Unity 2D射线检测对象问题

It detects the beam even if it passes over the object. I want it to detect when it's right on the object.

void RaycastSystem()
{
    Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
    Vector2 worldMousePosition = Camera.main.ScreenToWorldPoint(mousePosition);

    Vector2 rayDirection = worldMousePosition - (Vector2)transform.position;

    RaycastHit2D hit = Physics2D.Raycast(transform.position, rayDirection, rayDirection.magnitude, mask);
    Debug.DrawRay(transform.position, rayDirection, Color.red);
    //Debug.Log(worldMousePosition.x + " | " + worldMousePosition.y);

    if (hit.collider != null)
    {
        Debug.Log(hit.collider.gameObject);
    }
}

How can i solve this problem?

答案1

得分: 1

如果你的意思是只希望在光标直接位于对象上时检测到该对象,而不是当光标穿过对象时也检测到,那么你已经非常接近了。问题在于你正在测试的是从变换到鼠标光标之间是否存在任何碰撞器。而不是从角色变换发射一条射线,你想要从“屏幕”进行射线投射。Unity幸运地内置了这样的方式。

尝试类似这样的代码:

void RaycastSystem()
{
    Ray ray = camera.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;

    if (Physics.Raycast(ray, out hit, Mathf.Infinity, mask))
    {
        Debug.Log(hit.collider.gameObject);
    }
}

基本上,这种方法是从屏幕上的鼠标点向屏幕内投射射线的方向。

英文:

If you mean you only want it to detect the object when the cursor is directly on it and not when there's a line through the object, then you're very close. The issue is what you are testing is if there is any colliders between the transform and the mouse cursor. Instead of casting a Ray from the character transform, you want to raycast from the 'Screen'. Unity has a built in way of doing this thankfully.

Try something like this

void RaycastSystem()
    {
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
    
        if(Physics.Raycast(ray, out hit, Mathf.Infinity, mask))
        {
            Debug.Log(hit.collider.gameObject);
        }
        
    }

Essentially what this approach is doing is casting the ray direction from the mouse point on the screen -into- the screen.

答案2

得分: 0

如果我理解你最近的评论正确的话,你实际上想要进行两个检查:

  • 用户是否正在用鼠标悬停在一个物体上
  • 同一个物体是否可以被玩家对象的射线命中

所以你会将两者结合起来:

void RaycastSystem()
{
    Vectror2 worldMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

    // 首先检查鼠标是否击中了一个物体
    var mouseHit = Physics2D.OverlapPoint(worldMousePosition);
    if(mouseHit != null)
    {
        var rayDirection = worldMousePosition - (Vector2)transform.position;

        // 然后通过射线检查
        var hit = Physics2D.Raycast(transform.position, rayDirection, rayDirection.magnitude, mask);

        if (hit.collider != null)
        {
            if(hit.collider == mouseHit)
            {
                Debug.Log($"击中了 {hit.collider.name}!");
                // 对击中的物体做一些操作
            }
            // 否则介于两者之间的是另一个物体
        }
        // 否则射线没有击中任何东西(例如太远了)
    }
    // 否则鼠标没有击中任何东西
}

当然,你可以反转顺序,首先执行射线投射,然后在内部块中进行鼠标检查 - 根据你的需求/性能检查。

英文:

If I understand your latest comments correctly you actually want to have two checks

  • Is the user hovering an object with the mouse
  • Can the same object be hit by the raycast from the player object

So you would combine both

void RaycastSystem()
{
    Vectror2 worldMousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

    // first check if hitting an object with the mouse
    var mouseHit = Physics2D.OverlapPoint(worldMousePosition);
    if(mouseHit != null)
    {
        var rayDirection = worldMousePosition - (Vector2)transform.position;

        // then check via raycast
        var hit = Physics2D.Raycast(transform.position, rayDirection, rayDirection.magnitude, mask);

        if (hit.collider != null)
        {
            if(hit.collider == mouseHit)
            {
                Debug.Log("HIT {hit.collider.name}!");
                // do something with hit
            }
            // else some other object is in between
        }
        // else not hitting anything with the ray (e.g. too far away)
    }
    // else not hitting anything with the mouse
}

Can of course invert the order and first do the raycast and then in the inner block do the mouse check - according to your needs / performance checks.

huangapple
  • 本文由 发表于 2023年7月11日 04:53:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76657270.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定