② First person View controller — Open lens, head swing, incline slide (Study notes)

Want to achieve the effect: from the screen centering, emit a ray, can get the information of the first hit item, and when aiming at the item, press the interactive key on the item, the sight away from the item, can carry out the corresponding operation.

Ideas:

Interoperable item

Creating an Abstract Class

public abstract class Interactable : MonoBehaviour
{
    public virtual void Awake()
    {
        // Those that inherit Interactable are divided into the "Interactable" layer
        gameObject.layer = LayerMask.NameToLayer("Interactable");
    }
    // Press the interaction key
    public abstract void OnInteract();
    // When the line of sight is selected
    public abstract void OnFocus();
    // When the line of sight is out
    public abstract void OnLoseFocus();
}
Copy the code

Virtual and abstract

The virtual function virtual in C#

virtualandabstractAre used to modify the parent class, by overwriting the definition of the parent class, let the subclass redefine. -1.virtualThe decorated method must have an implementation (even if it is just adding a pair of braces), andabstractModifying methods must not be implemented. -2.virtualCan be overridden by subclasses, andabstractMust be overridden by subclasses. -3.If a class member isabstractModifier, must be added before the classabstractBecause only abstract classes can have abstract methods. -4.Unable to create theabstractClass, which can only be inherited but cannot be instantiated.Copy the code
-   1.A virtual method must have an implementation part, an abstract method does not provide an implementation part, and an abstract method is a method that forces a derived class to override, otherwise the derived class cannot be instantiated. -2.Abstract methods can only be declared in abstract classes; virtual methods are not. If a class contains abstract methods, the class is abstract and must be declared abstract. -3.Like interfaces, abstract methods must be overridden in derived classes. Virtual methods do not need to be overridden in derived classes.Copy the code

In short, abstract methods are implemented by subclasses. Virtual methods are already implemented and may or may not be overridden by subclasses, depending on requirements.

Both abstract and virtual methods can be overridden by derived classes.

Methods or classes that add virtual and abstract provide an essay title.

If you hand in an essay, you must write the content yourself, even if it is an empty sentence {}.

And virtual, has provided the model content, you can directly submit, you can also rewrite the content, overwrite the model.

A function that checks the declared class, such as “A A = new D()” for “a.fin ()”, will first check if Fun() is virtual in the definition of A. If not, it will run Fun() directly in the definition of A. If so, it will see if the definition of D is overridden. If you do, use D’s Fun(). If not, see if D’s superclass C is overwritten. If C is not overwritten, keep looking. If not, run A’s Fun() method.

Add the Interactable layer

About the Layer

PlayerController interaction

[Header("Functional Options")]
    [SerializeField] private bool canInteract = true;
[Header("Controls")]
    [SerializeField] private KeyCode interactKey = KeyCode.F;

[Header("Interaction")]
    // The starting point of the interaction ray
    [SerializeField] private Vector3 interactionRayPoint = default;
    / / the length
    [SerializeField] private float interactionDistance = default;
    // Which layer of objects to interact with
    [SerializeField] private LayerMask interactionLayer = default;
    // Get the 
      
        component of the interaction object
      
    private Interactable currentInteractable;
Copy the code
void Update()
    {
        GroundCheck();
        if (CanMove)
        {
            if(canInteract) { HandleInteractionCheck(); HandleInteractionInput(); } ApplyFinalMovement(); }}Copy the code
    /// <summary>
    ///Determine which interactive object to point to
    /// </summary>
    private void HandleInteractionCheck()
    {
        // playerCamera.ViewportPointToRay(interactionRayPoint)
        // ViewportPointToRay view your computer screen/camera view as a coordinate system, a plane
        // Lower left corner is (0, 0), upper right corner is (1, 1)
        // Then shoot a ray from your eye, say (0.5, 0.5), in the center of the screen
        // Distance is interactionDistance
        Debug.DrawRay(playerCamera.ViewportPointToRay(interactionRayPoint).origin, playerCamera.ViewportPointToRay(interactionRayPoint).direction * interactionDistance, Color.blue);
        if (Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance, interactionLayer))
        {
            // Debug.DrawRay(hit.transform.position, Vector3.down * 3f, Color.red);
            // When we use this collider, objects that can be interacted with are usually entities, or need to have entities
            // The ray hits an interactive item and is not currently interacting with other items or moving from one interactive item to another
            // currentInteractable.GetInstanceID() ! = hit.collider.gameObject.GetInstanceID()

            // if ((1 << hit.collider.gameObject.layer) == interactionLayer && (currentInteractable == null || currentInteractable.GetInstanceID() ! = hit.collider.gameObject.GetInstanceID()))
            if (currentInteractable == null|| currentInteractable.GetInstanceID() ! = hit.collider.gameObject.GetInstanceID()) {// If it is not empty, then it is out of focus
                if(currentInteractable ! =null)
                    currentInteractable.OnLoseFocus();

                // Get Component
      
       , give currentInteractable variable
      
                hit.collider.TryGetComponent<Interactable>(out currentInteractable);

                // If the 
      
        component exists
      
                if (currentInteractable)
                    // Execute the focus methodcurrentInteractable.OnFocus(); }}// If you miss an interactive item, but still bind to an interactive item
        else if (currentInteractable)
        {
            // Execute the out-of-focus method
            currentInteractable.OnLoseFocus();
            currentInteractable = null; }}/// <summary>
    ///Judgment interaction
    /// </summary>
    private void HandleInteractionInput()
    {
        // Press the interaction key
        // There are interactive objects
        // Hit an interactive item
        // Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance, interactionLayer)
        if(Input.GetKeyDown(interactKey) && currentInteractable ! =null && Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), outRaycastHit hit, interactionDistance, interactionLayer)) { currentInteractable.OnInteract(); }}Copy the code

Downsizing:

First, fire a ray of length 2 from the center of the camera (0.5, 0.5) of your screen to detect the specified layer, in this case the “Interactable” layer.

Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), 
out RaycastHit hit, interactionDistance, interactionLayer)
Copy the code

Then determine whether the currently bound interactive object is the object hit by the ray. If not bound, or if it points to another interactive object, execute the following code.

if (currentInteractable == null|| currentInteractable.GetInstanceID() ! = hit.collider.gameObject.GetInstanceID())Copy the code

In most games, you focus on interactive objects and then highlight them all around. I’m pointing here and it turns red.

// If it is not empty, perform the same method as the previous item.
if(currentInteractable ! =null)
    currentInteractable.OnLoseFocus();
// Get the "Interactable" component of the current interoperable item
hit.collider.TryGetComponent<Interactable>(out currentInteractable);
// The method that should be executed when the item is focused
if (currentInteractable)
    currentInteractable.OnFocus();
Copy the code

If no interactive item is hit, but an interactive item is still bound, the out-of-focus method is performed.

        else if (currentInteractable)
        {
            currentInteractable.OnLoseFocus();
            currentInteractable = null;
        }
Copy the code

Complete:

private void HandleInteractionCheck()
    {
        if (Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), 
        out RaycastHit hit, interactionDistance, interactionLayer))
        {
            if (currentInteractable == null|| currentInteractable.GetInstanceID() ! = hit.collider.gameObject.GetInstanceID()) {if(currentInteractable ! =null)
                    currentInteractable.OnLoseFocus();

                hit.collider.TryGetComponent<Interactable>(out currentInteractable);
                
                if(currentInteractable) currentInteractable.OnFocus(); }}else if (currentInteractable)
        {
            currentInteractable.OnLoseFocus();
            currentInteractable = null; }}Copy the code

Perform interactive operation: press the interactive key, and there are interactive objects, and the ray hits interactive items.

Input.GetKeyDown(interactKey) && currentInteractable ! =null && Physics.Raycast()
Copy the code
    private void HandleInteractionInput()
    {
        if(Input.GetKeyDown(interactKey) && currentInteractable ! =null &&
        Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), 
        outRaycastHit hit, interactionDistance, interactionLayer)) { currentInteractable.OnInteract(); }}Copy the code

Implement interactive items

Create a CubeInteractable subclass that inherits from the Interactable abstract class. Fill in the corresponding method.

public class CubeInteractable : Interactable
{
    public override void OnFocus()
    {
        // Debug.Log("Looking At: " + gameObject.name);
    }

    public override void OnInteract()
    {
        // Debug.Log("Interacted with: " + gameObject.name);
    }

    public override void OnLoseFocus()
    {
        // Debug.Log("Stopped Looking At: " + gameObject.name);}}Copy the code

Then create two cubes:

There must be a Collider because rays need to hit entities. Normal interactions can then take place.