Im making a grappling gun, that pulls an object towards the player if the layer is LightWeight
, and pull the player towards the object if the layer is Ground
int groundLayer_mask = LayerMask.GetMask("Ground");
int lightWeightLayer_mask = LayerMask.GetMask("LightWeight");
//Shoots a raycast, and only works if layer is Ground
if (Physics.Raycast(Shoulder.transform.position, cam.transform.forward, out raycastHit, float.PositiveInfinity, groundLayer_mask))
{
//Hit Something
debugHitpointTransform.position = raycastHit.point;
hookshotPosition = raycastHit.point;
hookShotSize = 0f;
HookShotTransform.gameObject.SetActive(true);
HookShotTransform.localScale = Vector3.zero;
layerHit = 0;
state = State.HookShotThrown;
}
//Shoots a raycast, and only works if layer is LightWeight
else if (Physics.Raycast(Shoulder.transform.position, cam.transform.forward, out raycastHit, float.PositiveInfinity, lightWeightLayer_mask))
{
//Hit Something
debugHitpointTransform.position = raycastHit.point;
hookshotPosition = raycastHit.point;
hookShotSize = 0f;
HookShotTransform.gameObject.SetActive(true);
HookShotTransform.localScale = Vector3.zero;
layerHit = 1;
state = State.HookShotThrown;
}
But if im looking in the direction of an object with Ground
layer, even if there is one with the layer LightWeight
closer than the one with Ground
, it goes for the one with Ground
cuz i have it's if statement first. Any way to make it either not go through the object infront just cuz the first if is looking for one behind, or to make it prioritize the one infront?
CodePudding user response:
Both your raycast cases basically do the exact same thing, except for the value of layerHit
. So either way this is a waste of resources ;)
So in order to be more efficient and also achieve what you want simply include both layers in your layer mask and make only one single raycast against both layers -> it will use whatever it hits first from the given layers.
You can then still check what layer you actually have hit inside the if
block.
So I would expose the field to be configurable in the Inspector
// Configure this via the Inspector
// it will be a drop-down from which you can select multiple entries
public LayerMask layers;
private void Awake ()
{
// if you really want to keep getting these by code
layers = LayerMask.GetMask("Ground", "LightWeight");
}
And also in general I would also use an enum
in order to have some meaningful names like e.g.
public enum HitType
{
None = -1,
Ground,
Lightweight
}
and then use a single ray cast like
int groundLayer_mask = LayerMask.NameToLayer("Ground");
int lightWeightLayer_mask = LayerMask.NameToLayer("LightWeight");
var hitType = HitType.None;
if (Physics.Raycast(Shoulder.transform.position, cam.transform.forward, out raycastHit, float.PositiveInfinity, layers))
{
//Hit Something
debugHitpointTransform.position = raycastHit.point;
hookshotPosition = raycastHit.point;
hookShotSize = 0f;
HookShotTransform.gameObject.SetActive(true);
HookShotTransform.localScale = Vector3.zero;
if(raycastHit.collider.gameObject.layer == groundLayer_mask) hitType = HitType.Ground;
else if(raycastHit.collider.gameObject.layer == lightWeightLayer_mask) hitType = HitType.Lightweight;
state = State.HookShotThrown;
}