前一篇[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
virtual和abstract都是用来润饰父类的,经过掩盖父类的界说,让子类重新界说。
- 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,电脑截图快捷键由于射线需求射中实体。 然后就能够进实例化一个目标能够使用什么命令行正常的交互了。