Since this lesson introduced a number of new concepts for someone whose sole experience with Unity and C# is the Complete Unity Developer course, I just wanted to go back through the explanation (without referencing the video) to make sure I’m understanding. All of the comments will be my explanations of the code.
using UnityEngine;
public class CameraRaycaster : MonoBehaviour
{
// Delcare an array from the Layer enum in Utiliy.cs. Each layer is set to
// the integer value from Edit > Project Settings > Tags and Layers >
// Layers for the layers that we want to detect with raycasting. These
// are going to be the layers we want to try and detect.
public Layer[] layerPriorities = {
Layer.Enemy,
Layer.Walkable
};
// The max distance from the camera to look for objects before giving up.
float distanceToBackground = 100f;
// This will be set to the Main Camera object in Start().
Camera viewCamera;
/*
m_hit is a private member RaycastHit variable and is not accessible outside
of CameraRaycaster.
When another external method calls hit, the get property simply returns the
value of m_hit, which is set in the Update() method. This lets me make a
variable publicly readable, but protects it from being changed outside the
method.
If I wanted to set m_hit from outside of CameraRaycaster, I could define a
set { m_hit = value } and access it later the way I would with a normal
variable declaration.
*/
RaycastHit m_hit;
public RaycastHit hit
{
get { return m_hit; }
}
/*
This does the same thing as hit, but returns the Layer enum property set
in the Update() method.
*/
Layer m_layerHit;
public Layer layerHit
{
get { return m_layerHit; }
}
void Start() // TODO Awake?
{
// Set viewCamera to Main Camera
viewCamera = Camera.main;
}
void Update()
{
// Loop through each layer in layerPriorities array
foreach (Layer layer in layerPriorities)
{
// Cast a ray and return the RaycastHit values if it hits an object that is part of
// the given layer. (This is why object that aren't in the Walkable
// or Enemy layers appear to are "invisible" to the ray. We just
// don't filter for them. in RaycastForLayer())
var hit = RaycastForLayer(layer);
// if hit is not null...
if (hit.HasValue)
{
// ... set m_hit to the value (all the infor for) hit...
m_hit = hit.Value;
//... and set m_layerHit to the Layer property we tested for...
m_layerHit = layer;
//... and get out of Dodge 'cause you're done.
return;
}
}
// If the hit didn't hit any layer we tested for, set the distance
// propery to distanceToBackground...
m_hit.distance = distanceToBackground;
// ..and the layer to the property indicating that we didn't find
// anything.
m_layerHit = Layer.RaycastEndStop;
}
// Usually we must return a valid RaycastHit value, but the ? let's us
// return null.
RaycastHit? RaycastForLayer(Layer layer)
{
// Set up a LayerMask using a bitwise operation set equal to our passed
// in layer enum value.
int layerMask = 1 << (int)layer;
// Shoot a ray that originates from the main camera, passes through the
// position of the mouse cursor (see illustration) and tries to impact
// against something.
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
// Declare the variable we're going to be setting to the value of the
// object the raycast hit. Out variable 'cause "Unity".
RaycastHit hit;
// If ray hits layerMask before going distanceToBackground, assign it to
// hit
bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
// If hit has a value, return it.
if (hasHit)
{
return hit;
}
// If hit does not have a value, return null. Because we can. The
// all-knowing question mark says so.
return null;
}
}
The following illustration shows how viewCamera.ScreenPointToRay(Input.mousePosition) casts a ray from the camera through the cursor position (shows two rays (red) casting through two mouse positions (green) from the camera (blue))
Does that look correct?
Some feedback: I’m all for dropping in code when it’s stuff we’ve already covered, but it’s very much helpful to write code for new concepts. I understand it better because each block is being explained as we write. It helps me relate one section back to the whole.