前一篇[Unity] ②第一人称视角控制器——开镜、头部摆动、斜面滑落(学习笔记)

想要完成的效果:从屏幕准心,发射一条射线,能获取第一个击中的物品的信笔记本息,并且在瞄准这个物品,对物品按交互键,视野离开这个物品时,能进行相应的操作。

思路:

可交互物品

创建笼统类

public abstract class Interactable : MonoBehaviour
{
    public virtual void Awake()
    {
        // 承继Interactable类的,都划分到“Interactable”层
        gameObject.layer = LayerMask.NameToLayer("Interactable");
    }
    // 按下交互键时
    public abstract void OnInteract();
    // 视野瞄准,选中时
    public abstract void OnFocus();
    // 视野脱离后
    public abstract void OnLoseFocus();
}

virtual 和 ab电脑截图stract

C#中的虚函数virt实例化servlet类异常ual

virtualabstract都是用来润饰父类的,经过掩盖父类的界说,让子类重新界说。
-   1.virtual润饰的办法有必要有完成(哪怕是只是增加一对大括号),而abstract润饰的办法必定不能完成。
-   2.virtual能够被子类重写,而abstract有必要被子类重写。
-   3.假设类成员被abstract润饰,则该类前有必要增加abstract,由于只要笼统类才能够有笼统办法。
-   4.无法创建abstract类的实例,只能被承继无法实例化。
-   1.虚办法有必要有完成部分,笼统办法没有供给完成部分,笼统办法是一种强制派生类掩盖的办法,否则派生类将不能被实例化。
-   2.笼统办法只能在笼统类中声明,虚办法不是。假设类包括笼统办法,那么该类也是笼统的,也有必要声明类是笼统的。
-   3.笼统办法有必要在派生类中重写,这一点和接口相似,虚办法不需求再派生类中重写。

appearance单说,笼统办法是需求appointment子类去完成的。虚办法是现已完成了的,能够被子类掩盖,也能够不掩盖,取决于需求。

笼统办法和虚办法都能够供派生类重写。

个人application了解:加了 virtual 和 abstract 的办法或者类,都能够了解为,提笔记变量与函数电脑黑屏却开着机了一个作笔记文标题。

而a电脑bstract,只要标题,你要交出一篇作文,有必要要自己写完内容,哪怕是个空的句子{}。

而virtua变量l,现已供给了范文内容,你能够直接交上去,也能笔记本显卡天梯图够自笔记己重新写内容,掩盖掉范文。

而一个检查声明类的函数,如 “A a = new D()”approve 的 “a.approachFun电脑怎么录屏()” 办法,会先检查变量的界说在 A 的界说中,Fun(变量与函数)办法是否是虚函数,假设不是,直接运行 A 界说的 Fun() 办法,假设是,笔记本插电用好还是不插电就看 D实例化一个对象可以使用什么命令 的界说中,是实例化否重写了,假设重写了笔记本电脑变量与函数用 D 的 Fun() 办法。假设没有重写,就看 D 的父类 C 是否重电脑锁屏快捷键写了,假设 C 没有就持续往上找,假设都没有重写,最终就运行 A 的 Fun() 办法。

增加「Interactable」层

关于 Layer

PlayerC实例化对象是什么意思ontroller交互功笔记本

[Header("Functional Options")]
    [SerializeField] private bool canInteract = true;
[Header("Controls")]
    [SerializeField] private KeyCode interactKey = KeyCode.F;
[Header("Interaction")]
    // 交互射线的起始点
    [SerializeField] private Vector3 interactionRayPoint = default;
    // 长度
    [SerializeField] private float interactionDistance = default;
    // 交互哪一层的目标
    [SerializeField] private LayerMask interactionLayer = default;
    // 获得交互目标的<Interactable> 组件
    private Interactable currentInteractable;
void Update()
    {
        GroundCheck();
        if (CanMove)
        {
            if (canInteract)
            {
                HandleInteractionCheck();
                HandleInteractionInput();
            }
            ApplyFinalMovement();
        }
    }
    /// <summary>
    /// 判别指向哪个可交互目标
    /// </summary>
    private void HandleInteractionCheck()
    {
        // playerCamera.ViewportPointToRay(interactionRayPoint)
        // ViewportPointToRay 把你的电脑屏幕/摄像机看到的画面,看做一个坐标系,一个平面
        // 左下角为(0, 0),右上角为(1, 1)
        // 然后从你眼睛里,比如(0.5, 0.5),也便是屏幕中心,发射一条射线
        // 间隔是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);
            // 这儿用collider,可交互的物品一般都是实体,或者说要求有实体
            // 射线击中可交互物品,且当时没有与其它物品交互,或者从一个可交互物品移动到另一个
            // 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 (currentInteractable != null)
                    currentInteractable.OnLoseFocus();
                // 获取Component<Interactable>, 给currentInteractable变量
                hit.collider.TryGetComponent<Interactable>(out currentInteractable);
                // 假设存在<Interactable>组件
                if (currentInteractable)
                    // 履行聚集办法
                    currentInteractable.OnFocus();
            }
        }
        // 假设没有击中可交互物品,但是仍绑定了某个可交互物品
        else if (currentInteractable)
        {
            // 履行失焦办法
            currentInteractable.OnLoseFocus();
            currentInteractable = null;
        }
    }
    /// <summary>
    /// 判别交互操作
    /// </summary>
    private void HandleInteractionInput()
    {
        // 一、按下交互键
        // 二、存在可交互目标
        // 击中某个可交互物品
        // Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance, interactionLayer)
        if (Input.GetKeyDown(interactKey) && currentInteractable != null && Physics.Raycast(playerCamera.ViewportPointToRay(interactionRayPoint), out RaycastHit hit, interactionDistance, interactionLayer))
        {
            currentInteractable.OnInteract();
        }
    }

精简电脑黑屏却开着机

首先,从摄像机,也便是你屏幕的(0.5, 0.5)中心方位,发电脑截图快捷键射一条射线,长度为2,检测指定层,这儿是变量名的命名规则「Interactable」层电脑黑屏却开着机

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

然后判别,当时绑定的可交互目标,是否为射线变量的定义击中的目标。未绑定,或者指向了其它可交互目标,就履行下面的变量泵代码。

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

一般游戏里,都是聚集可交互物品,然后物品周围一圈被高亮。我这儿是指向就变量类型有哪些变量红。

// 假设为不为空,那就履行视野脱离前一个物品,前一个物品应该履行的办法。
if (currentInteractable != null)
    currentInteractable.OnLoseFocus();
// 获取当期可交互物品的「Interactable」组件
hit.collider.TryGetComponent<Interactable>(out currentInteractable);
// 绑定成功,履行聚集该物品时,应该履行的办法
if (currentInteractable)
    currentInteractable.OnFocus();

假设没有射中可交互物品电脑怎么重装系统,但是仍绑定有可交互物品,履行失焦办法。

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

完整:

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;
        }
    }

履行交互操作: 按下交互键,且有可交互目标,且射线射中appstore可交互物品。电脑黑屏却开着机

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

完成可交互物品

创建一个CubeI笔记本显卡天梯图nteractable子类,承继自Interactable笼统类。填上对应的办法。

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);
    }
}

然后创建两个CUBE实例化一个对象可以使用什么命令

必定要有collider,电脑截图快捷键由于射线需求射中实体。 然后就能够进实例化一个目标能够使用什么命令行正常的交互了。