简体   繁体   English

Unity2D / C#:如何使光线投射忽略它的第一次碰撞?

[英]Unity2D/C#: How do I make a raycast ignore its first collision?

One of the features of the raycast controller for my platformer game is that the player can jump down through 1-way platforms. 我的平台游戏的光线投射控制器的一个特点是玩家可以通过单向平台跳下来。 This works nicely, but I wanted to add additional functionality where the player will only be able to jump down if the platform to which he or she will jump is within a certain distance. 这很好用,但我想添加额外的功能,如果玩家将跳跃的平台在一定距离内,玩家将只能跳下来。

My platform controller's functionality for jumping down works like this: 我的平台控制器的跳跃功能如下所示:

  1. My character shoots a ray from below its box collider, and detects if it's on ground or not. 我的角色从它的盒子对撞机下方射出一束光线,并检测它是否在地面上。
  2. If it is, and if the ground is tagged as a 1-way platform, and the player presses the jump down button, it will jump down to the next platform, regardless of distance. 如果是,并且如果地面被标记为单向平台,并且玩家按下跳下按钮,它将跳到下一个平台,无论距离如何。

I have tried making a jump down method that creates a new raycast from the center of the character's box collider (which is not shown in the code below, as I have been entirely unsuccessful so far), and checks for a collision at a certain distance. 我试过制作一个跳跃方法,从角色的盒子对撞机的中心创建一个新的光线投射(下面的代码中没有显示,因为到目前为止我完全不成功),并检查一定距离的碰撞。 My problem is that it always detects the collider of the platform from which it is about to jump down, and never gets a chance to detect anything else. 我的问题是它总是检测到它将要从中跳下的平台的对撞机,并且永远不会有机会检测到其他任何东西。

How do I get this new raycast to ignore the first collision, potentially detect a collision within the ray's distance, and if it hits something allow my character to jump down? 如何让这个新的光线投射忽略第一次碰撞,可能检测到光线距离内的碰撞,如果碰到某些东西让我的角色跳下来? Also, do I even need to do a new raycast, or can I just use the current raycasts on my controller? 另外,我是否需要进行新的光线投射,或者我可以在控制器上使用当前的光线投射?

Here's a bit of my raycast controller script that hopefully explains some of the functionality: 这里有一些我的raycast控制器脚本,希望能够解释一些功能:

private void MoveVertically(ref Vector3 deltaMovement)
{
    float directionY = Mathf.Sign(deltaMovement.y);
    float rayLength = Mathf.Abs(deltaMovement.y) + skinWidth;

    for (int i = 0; i < verticalRayCount; i++)
    {
        Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
        rayOrigin += Vector2.right * (verticalRaySpacing * i + deltaMovement.x);

        RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);

        Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength, Color.red);

        if (hit)
        {
            if (hit.collider.tag == "platformOneWay")
            {
                if (directionY == 1)
                {
                    State.IsCollidingWithOneWay = true;
                    State.IsCollidingAbove = false;
                    continue;
                }

                if (CanJumpDown)
                {
                    State.IsCollidingBelow = false;
                    continue;
                }
            }

            deltaMovement.y = (hit.distance - skinWidth) * directionY;
            rayLength = hit.distance;

Actually, Unity3D provides an API called Physics2D.RaycastAll that returns not only the first raycast hit but all raycast hits within the maximum distance as an array. 实际上,Unity3D提供了一个名为Physics2D.RaycastAll的API,它不仅返回第一个光线投射命中,而且返回最大距离内的所有光线投射命中数组。
Physics2D.RaycastAll takes two Vector2 as parameters (the raycast origin and direction) and returns an array of RaycastHit2D , which is ordered by the distance from the origin to the hit point. Physics2D.RaycastAll将两个Vector2作为参数(光线投射原点和方向)并返回一个RaycastHit2D数组,该数组按照从原点到命中点的距离排序。
Here is a bit of code that shows you what this function does: 这里有一些代码可以显示这个函数的作用:

public class Raycaster : MonoBehaviour
{
    private void Start()
    {
        RaycastHit2D[] hits = Physics2D.RaycastAll(transform.position, Vector2.down);
        for (int i = 0; i < hits.Length; ++i)
        {
            Debug.LogFormat("The name of collider {0} is \"{1}\".", 
                i, hits[i].collider.gameObject.name);
        }
    }
}

Another way would be to create LayerMasks. 另一种方法是创建LayerMasks。 Create a new layer in the Unity editor and assign the layer to the Game Object where your collider is attached it. 在Unity编辑器中创建一个新图层,并将图层分配给游戏对象,在该游戏对象上连接对撞机。

Get the layer mask ID in your code using LayerMask.GetMask and add it as an parameter. 使用LayerMask.GetMask在代码中获取图层蒙版ID,并将其添加为参数。 Now your Raycast will only cast colliders assigned to the layer. 现在你的Raycast只会投射分配给图层的碰撞者。

var layerMask = LayerMask.GetMask ("myLayerName");
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, 100.0f, layerMask)) {
    Debug.Log ("Got ya!");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM