Week 5 Tuesday
Smarter collisions (review)
Layers
Raycasting
Visualizing raycasts
Here are three ways to decide what the other object is, in a collision:
Note that there are many others.
if (collision.gameObject.name == "Goomba") { Die(); }
Pros:
Cons:
Pros:
Cons:
if (collision.gameObject.tag == "Goomba") { Die(); }
Another way to know whether some GO is the kind of GO you care about: ask for its script components.
collision.gameObject.GetComponent<Goomba>()
If the other GO has a Goomba script attached, you can assume it's a Goomba.
collision.gameObject.GetComponent<Goomba>()
If the other GO has a Goomba component, this will get you a reference to it.
If the other GO does not have a Goomba component, this will return the special value null, which is nothingness.
So to determine whether the other GO has the script, you ask if the result is not null.
Not-nothing is something. So it must be a Goomba.
Goomba potentialGoomba =
collision.gameObject.GetComponent<Goomba>();
if (potentialGoomba != null) { Die(); }
Pros:
Cons:
if (potentialGoomba != null) { Die(); }
is useful
Raycasting is drawing an invisible line (the "ray") out into the game world to see what game objects are in that direction.
?
You can use raycasting to answer questions like:
Where will the grappling hook hit the ceiling?
Can that guard see the player character?
Can that guard see the player character?
Sometimes it's not enough to know whether two objects are colliding.
For example, Mario can only jump when he is standing on something.
Is Mario standing on solid ground?
You could use collisions to
answer this. But...
Is Mario standing on solid ground?
You could draw a ray
down from his center and
see whether it hits
something.
But...
In old 2D platformers like Mario, having even a small part of the character over solid ground is enough.
So you'd do something like this, with two raycasts.
If either of the raycasts
hits solid ground, then
Mario doesn't fall.
The mouse doesn't exist in the game world. It's just a position on a 2D screen.
Image source: Sha Qian via Noteworthy
So you convert the mouse's screen position into a world position. Then you send a ray forward into the game world to see what it hits.
The syntax (what you have to type) is annoying.
And you can't see a raycast so it can be hard to know if you're doing it right.
But it's a key tool.
RaycastHit2D hit2D = Physics2D.Raycast( startOfRay, direction, distance );
This is the basic form of the 2D raycast function:
The 2D raycast function needs at least three pieces of information:
Vector3
Vector3
float
This is how you can get to the GameObject that the ray hit:
hit2D.collider.gameObject
Then you can ask that other GO for its components, tag, and so on:
GameObject otherGO = hit2D.collider.gameObject;
otherGO.GetComponent<SpriteRenderer>()
otherGO.gameObject.tag
otherGO.SetActive(false)
The RaycastHit2D itself will never be null. So you might think you can do something like this:
if (hit2D != null) { print (hit2D.collider.name); }
But this code will always run, whether or not the raycast actually hit something.
!
!
To find out if the ray hit something:
if (hit2D.collider != null) {
print (hit2D.collider.name);
}
By default, the raycast will hit the same GameObject that is casting the ray. You can fix this:
[SerializeField] LayerMask layerMask;
This will show a dropdown in the Inspector. The raycast will hit the layers with checks.
RaycastHit2D hit2D = Physics2D.Raycast( startPosition, direction, distance, layerMask );
[SerializeField] LayerMask layerMask;
RaycastHit2D hit2D = Physics2D.Raycast( startOfRay, direction, distance );
RaycastHit2D hit2D = Physics2D.Raycast( transform.position, directionToPlayer, playerCheckDistance );
RaycastHit2D hit2D = Physics2D.Raycast( transform.position, Vector2.down, groundCheckDistance );
RaycastHit raycastHit;
Physics.Raycast(
startOfRay,
direction,
out raycastHit
);
This is the basic form of the 3D raycast function:
This function needs at least three pieces of information:
Vector3
Vector3
RaycastHit
???
Unity wrote this raycast function to use something called an out parameter. You don't need to understand anything about the why or how.
To use it:
This is how you can get to the GameObject that the ray hit, just like with the 2D function:
raycastHit.collider.gameObject
It can be hard to set up raycasting correctly because the ray is invisible.
You can't directly make the ray visible, but you can draw a line where the ray is using Debug.DrawRay.
It is almost the same as the raycast function...but slightly different.
Debug.DrawRay( startPosition, directionAndDistance, color );
Vector3 dirToPlayer = player.transform.position - transform.position; Debug.DrawRay( transform.position, dirToPlayer, Color.red );
But dirToPlayer is a vector that points directly to the player. If you want to look in the player's direction, but only a certain distance, you will normalize the vector.