一、Aimable Object
为场景中需要进行交互的物体挂载AimableObject组件:
Description属性表示该物体的描述信息,AimableDistance属性表示该物体可被瞄准检测到的距离,通过OnEnter、OnExit、OnStay分别为该交互物体设置瞄准进入事件、瞄准退出事件、瞄准停留事件,也可以通过继承AimableObject类,来重写这些事件,如下所示:
代码语言:javascript复制using UnityEngine;
using SK.Framework;
public class Example : AimableObject
{
protected override void OnEnter()
{
//TODO
}
protected override void OnStay()
{
//TODO
}
protected override void OnExit()
{
//TODO
}
}
二、Aim System
瞄准交互系统的核心,需要在场景中挂载该组件:
Toggle表示整个系统的开关,将其设为false后,系统将不再进行瞄准检测,MainCamera是用于瞄准检测的相机,AimLayer表示检测的层级,AimMaxDistance表示检测的最大距离,AimMode表示瞄准的方式,包含两种,一种是Mouse,使用鼠标的位置发出射线进行瞄准检测,当我们的相机是自由视角、上帝视角时,通常使用这种方式;另一种则是View Centre,通过屏幕的中心点发出射线进行瞄准检测,当我们的相机是第一人称或第三人称视角时,通常使用这种方式。需要注意,当AimMode为ViewCentre模式时,AimMaxDistance属性才起作用。
除此之外,AimSystem中的核心属性还包括CurrentAimableObject,它记录了当前所瞄准的物体:
代码语言:javascript复制/// <summary>
/// 当前瞄准的物体
/// </summary>
public IAimableObject CurrentAimableObject { get; private set; }
三、示例
上例中,我们在物体的瞄准进入事件里添加了一个物体高亮的效果,并且通过一个Text文本来显示该物体的描述信息,在瞄准退出事件里隐藏物体的高亮效果,并将Text文本清空。实现过程如下:
代码语言:javascript复制using UnityEngine;
using SK.Framework;
public class Example : AimableObject
{
[SerializeField] AimView view;
protected override void OnEnter()
{
//显示物体高亮效果
GetComponent<HighlightOutline>().enabled = true;
//显示描述信息
view.OnEnter(description, transform.position);
}
protected override void OnExit()
{
//隐藏物体高亮效果
GetComponent<HighlightOutline>().enabled = false;
//清空描述信息
view.OnExit();
}
}
将Example挂载于各个可交互物体,并填写各自的Description描述信息
代码语言:javascript复制using UnityEngine;
using UnityEngine.UI;
public class AimView : MonoBehaviour
{
//用于显示描述信息的文本
[SerializeField] Text descriptionText;
public void OnEnter(string description, Vector3 worldPos)
{
//描述信息
descriptionText.text = description;
//世界坐标转屏幕坐标 更新文本位置
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
descriptionText.rectTransform.anchoredPosition3D = screenPos;
}
public void OnExit()
{
descriptionText.text = null;
}
}
注意Text文本的锚点和轴心点的设置:
AimMode使用的是Mouse模式: