I’m making a Portal clone, and I have a code that is supposed to shoot only onto objects with certain layers. I start by defining the variable:
public LayerMask canShootAt;
Later in the script when I incorporate raycasting:
RaycastHit hit;
if(Physics.Raycast(ray, out hit, canShootAt))
//The code that shoots the Portal
I created two layers: “Shootable” and “Nonshootable.” I put the layer “Shootable” on the objects I want to be able to shoot onto, and you can figure out the rest.
The problem is that when I change “canShootAt” to “Shootable” in the inspector, you can still shoot at every object in the level. How do I fix this?
Add a float value as the third parameter, so your layermask will be the fourth (fourth is an interger defining the layermask, so you can use ‘canShootAt.value’) . Then you match the overload of the method which @OboShape has posted.
What you’re currently trying is to use the parameter list with the types:
Ray ray = mainCamera.GetComponent<Camera>().ScreenPointToRay(new Vector3(x,y));
RaycastHit hit;
if(Physics.Raycast(ray, out hit, float distance, canShootAt))
//Do the Portal thing
The error says it’s expecting a “,” or “)” at the if statement line.
You cannot pass ‘float distance’, you have to declare the variable and pass only the name afterwards. Note that you have to assign it when doing so or you could also just pass a constant value as an argument for the float.
It works for the most part now (thanks ) though I still have some issues. If you try shooting onto a non shootable object, the portal will not appear there, which is supposed to happen. Though, if there is a shootable object behind the non shootable object, the gun will shoot the portal through the non shootable object onto the shootable one. The code basically does the same thing as an “Ignore Raycast” layer. Is there a way to make it so that the portal will not shoot through non shootable objects?
The idea of layermasks is to ignore certain layers. I guess you’re rather looking for tag (or layer) comparison in order to determine whether your portal can be spawned on top of the object or not.
i dont think so, but im not that up on raycasting to be honest.
but its doing what it says on the tin, by returning the first collider that isnt on a layer to be ignored.
you might have to consider other mechanics for distinguishing where to put portals.
if you were to set your raycast to not ignore that layer, you could find what layer the object you hit is on, then base your logic on that.
so the first thing you hit, you can check what layer its on. if its on the ‘dontputaportalhere’ layer then do nothing, otherwise carry on.
when your ray hits, get that gameobject and use the gameObject.layer, and that will give you an int based on what layer it has hit so you can make a comparison.
least that way your ray will fire, hit the first thing, and check what layer that objects on, and then create/dontcreate a portal.
i cant mind the right code to use as i dont have an example in front of me right now.
I know what you are talking about. I had something like that in mind but I didn’t know how I would go about coding it. I sort of have an idea now. Is there a function in Unity that is basically “End Script” or “Do Nothing” so that nothing below the line will happen?
That’s not how layermarks work with raycasting. Any object that’s on a layermask that is being ignored will be effectively invisible to the raycast, so it will go straight through it. Any object that isn’t included in the layermask will behave exactly the same as the Ignore Raycast layer.
If you want the ray to hit all the walls, but only actually interact with certain walls the you need to use tags.
My understanding of layermasks is that they’re used for performance reasons (in raycasting,at least) - if your scene is full of objects that are irrelevant to your raycast then you don’t want the engine to be checking against all these objects if you’re never going to do anything with that information. The ray will only “see” the objects the objects on the layers you want it to see, so it filters the useless objects out.
Create another layermask with only the layers you want to interact with.
First do the raycast with the layermask which includes everything , then inside the if statement, query the gameobjects layer which it collides with and test it’s layer against your “interactive” layermask.
not exactly sure what your after.
if its within a loop then you can use ‘break’ to exit the loop.
or try conditional statements to see if something needs done or not.
I assume “below the line” means after the raycast hits something? If so, that’s the default behaviour of a raycast. The RaycastHit variable will provide information on the first object the ray interacts with.
If an object is on a layer that isn’t in the raycasts layermask, the raycast won’t see it.
You’ll need something like this:
void Update()
{
if (Physics.Raycast(yourRay, out hit, yourLayermask))
{
if ( hit.collider.tag == "Shootable" )
{
// Do portal stuff
}
}
}
The tag check isn’t strictly necessary if the only objects that use the layer you’re masking against are the shootable walls, though. In that case, this should work:
void Update()
{
if (Physics.Raycast(yourRay, out hit, yourLayermask))
{
// Do portal stuff
}
}