② 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.