0
\$\begingroup\$

It's quite possible I'm missing something obvious (I'm still rather new to this) despite checking the documentation, but I'm at my wit's end with this issue.

I'm attempting to add simple linecast collisions to my 2D movement system that checks if there's a wall on the relevant layer to disallow movement, but I cannot get the distance parameter to function properly. It's responding as if my distance is set to the default MathF.Infinity, despite me feeding a float variable into it.

Furthermore, unity keeps giving me this error after I moved my layermask declaration into the Start function: "The name 'mask' does not exist in the current context." I'm unsure why this is happening.

Here's the relevant code:

float distance = 1f;

void Start()
{
    LayerMask mask = LayerMask.GetMask("BlockingLayer");

}
void FixedUpdate()
{
    // Move up IF !isMoving and No collision detected.
    if (Input.GetKey(KeyCode.W) && !isMoving && Physics2D.Linecast(transform.position, Vector2.up, mask, distance))
            StartCoroutine(MovePlayer(Vector2.up));
}

Alright, after working with the helpful people responding, I've updated my code. Unfortunately, my issue seems to have inverted. Rather than detecting collision always, collision does not seem to be detected ever. Here's the new code (Edited to reflect small change):

    float maxDistance = 2f;
RaycastHit2D hitU;

void FixedUpdate()
{
     hitU = Physics2D.Raycast(transform.position, Vector2.up, LayerMask.GetMask("BlockingLayer"));
    // Move up IF !isMoving and No collision detected.
    if ((hitU.collider != null && (hitU.distance < maxDistance)))
    {
        if (Input.GetKey(KeyCode.W) && !isMoving)
        {
            StartCoroutine(MovePlayer(Vector2.up));
            Debug.DrawRay(transform.position, Vector2.up, Color.red);
        }

    }
\$\endgroup\$
2
  • 1
    \$\begingroup\$ In your updated code, you only ever check the ray once: when the object first loads Then you never ever cast a ray again. How are you expecting the value of hitU to change if you never assign a new value to it? \$\endgroup\$
    – DMGregory
    Jun 29 at 16:34
  • \$\begingroup\$ I feel remarkably stupid now and have moved that line out of Start and into FixedUpdate so that the ray is repeatedly assigned a new variable based on the current transform, but that has still not fixed the collision issue. \$\endgroup\$
    – ZTheo
    Jun 29 at 18:30
0
\$\begingroup\$
Distance param

I think you're confusing the parameters for Physics2D.Raycast with Physics2D.LineCast. The "distance" parameter your passing into Physics2D.LineCast is actually a "minDepth" value. Which according to Unity Docs:

Only include objects with a Z coordinate (depth) greater than or equal to this value.

Which means it actually has nothing to do with distance in 2D space, but rather rather operates on the z-axis.

Solution

I would employ Physics2D.Raycast instead. The tricky "gotcha" with this method (at least in 3D), is that the distance param is actually just used by the Unity engine to optimize the raycasting algorithm so unity doesn't do more intersection tests than it has to. It isn't a guarantee for the precise max distance that the raycast hits will return.

You'll have to perform these checks yourself to be sure:

var hit = Physics2D.Raycast(transform.position, Vector2.up);

//if there was a hit, and distance was less than maxdist...
if ((hit.collider != null && (hit.distance < maxDistance))
{
   //do....
}


"The name 'mask' does not exist in the current context."

This is happening because your mask variable goes out of scope at the end of the your Start() method. You have to declare your mask variable as a member variable, so it's lifetime matches the lifetime of your script.

Try this instead:

LayerMask mask;

void Start()
{
    mask = LayerMask.GetMask("BlockingLayer");
}
```
\$\endgroup\$
7
  • \$\begingroup\$ That makes sense for my mask issue, thanks for that. As for using Raycast instead of Linecast, what would you suggest? I've messed with it previously, but not managed to devise anything that functions. Sorry if that's a question with an obvious answer, but I haven't managed to solve it despite searching this site and others. \$\endgroup\$
    – ZTheo
    Jun 29 at 0:40
  • \$\begingroup\$ The two methods are equivalent. Use whichever one is more convenient for the parameters you have handy: raycast if you have a direction, linecast if you have an endpoint. \$\endgroup\$
    – DMGregory
    Jun 29 at 1:56
  • \$\begingroup\$ I edited my code to provide a code snippet solution. \$\endgroup\$
    – Charly
    Jun 29 at 2:02
  • \$\begingroup\$ Do you know if the 'distance' param guarantees distance, I'm almost certain this is the case for Physics.Raycast but i'm not sure about Physics2D.Raycast.... \$\endgroup\$
    – Charly
    Jun 29 at 2:03
  • \$\begingroup\$ So, I've messed with your snippet of code, which looks quite promising, but I've run into what I believe is the same issue I was having earlier with LayerMask. I can't declare my variable in Start without an error "The contextual keyword 'var' may only appear within a local variable declaration or in script code" and I also can't declare it outside of a function because of the same error. Obviously, I shouldn't be running it in FixedUpdate with my movement checks, so I'm at a loss. Should I employ the same concept as the mask solution? I don't know what data type to declare. \$\endgroup\$
    – ZTheo
    Jun 29 at 4:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.