一、先看表现形式
主要形式:
- 1、标签跟随光标移动
- 2、pointer enter时,显示部件信息
- 3、pointer exit时,隐藏标签
二、数据的组织
/// <summary>
/// 房屋组件信息表:组成合院的组件:【照壁】、【走马转角楼】、【大门】、【山墙装饰】、【屋顶】......
/// </summary>
[Serializable]
public class PartsInfo
{
/// <summary>
/// 部件名字
/// </summary>
[Header("部件名字")]
[SerializeField]
public string partsName;
/// <summary>
/// 部件root:用于绑定高亮脚本
/// </summary>
[Header("部件root:用于绑定高亮脚本")]
[SerializeField]
public Transform partsRoot;
/// <summary>
/// 部件的子物体:物体进入该零件,显示所属部件名字
/// </summary>
[Header("部件的子物体:物体进入该零件,显示所属部件名字")]
[SerializeField]
public List<GameObject> parts;
}
/// <summary>
/// 房屋部件信息
/// </summary>
[Serializable]
public class House
{
/// <summary>
/// 房屋名字
/// </summary>
[Header("房屋名字")]
[SerializeField]
public string houseName;
/// <summary>
/// 房屋部件信息
/// </summary>
[Header("房屋部件信息")]
[SerializeField]
public List<PartsInfo> partsInfos;
}
/// <summary>
/// 房屋信息
/// </summary>
[Header("房屋信息")]
[SerializeField]
public List<House> houses;
三、交互时的注意事项
- 基本组件【EventTrigger】、【MeshCollider】(注意不是【BoxCollider】)
//添加组件——EventTrigger
if (obj.GetComponent<EventTrigger>() == null)
{
obj.gameObject.AddComponent<EventTrigger>();
}
//添加Collider组件
if (obj.GetComponent<Collider>() == null)
{
//obj.gameObject.AddComponent<BoxCollider>();
obj.gameObject.AddComponent<MeshCollider>();
}
- 光标进入时,显示信息标签
//得着焦点
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerEnter, (PointerEventData eventData) =>
{
Debug.Log($"进入物体:{partName} {obj.name} {currentPart} {Time.realtimeSinceStartup}");
pi.partsRoot.GetComponent<Highlighter>().tween = true;
ShowTag.ShowNameTag(partName, true);
});
- 光标退出时,隐藏信息标签
//失去焦点
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerExit, (PointerEventData eventData) =>
{
Debug.Log($"退出物体:{partName} {obj.name} {currentPart} {Time.realtimeSinceStartup}");
pi.partsRoot.GetComponent<Highlighter>().tween = false;
ShowTag.ShowNameTag(partName, false);
});
- 标签图片随时跟随光标
/// <summary>
/// 显示建筑物部件的名字标签
/// </summary>
public class ShowTag : MonoBehaviour
{
/// <summary>
/// 标签图片包含Text组件
/// </summary>
[Header("标签图片包含Text组件 ")]
[SerializeField]
public GameObject image;
/// <summary>
/// 图片跟随鼠标——开关
/// true:跟随
/// false:不跟随
/// </summary>
private bool dragOn;
/// <summary>
/// 外部调用的入口,在Start()里面初始化
/// </summary>
public static Action<string, bool> ShowNameTag;
private void Start()
{
ShowNameTag = (name, onOff) =>
{
dragOn = onOff;
image.GetComponentInChildren<Text>().text = name;
image.SetActive(onOff);
};
}
// Update is called once per frame
void Update()
{
if (dragOn)
{
Drag2dObjectViaMouse(image);
}
}
#if UNITY_EDITOR
[ContextMenu("测试")]
#endif
async void Test5()
{
ShowNameTag("赵四", true);
await UniTask.Delay(TimeSpan.FromSeconds(5f));
ShowNameTag("刘能", true);
await UniTask.Delay(TimeSpan.FromSeconds(5f));
ShowNameTag("", false);
}
}
四、总结
- 1、规划好底层的数据:本例中关键数据为【部件:GameObject -> 名字:string】
- 2、交互式的组件配置:
-
- (1)主相机:Physics Raycaster,Highlighting Renderer
-
- (2)物体:EventTrigger + PointerEnter + PointerExit,MeshCollider,Highlighter
-
- (3)跟随光标的图片:切记需要把【RayCast Target】取消勾选,不然会挡住射线
- 3、在Start()中动态绑定:
// Start is called before the first frame update
void Start()
{
#region =============================普通初始化=============================
currentPart = "";
#endregion =============================普通初始化=============================end
#region =============================事件绑定=============================
//事件添加
// 每中合院逐个处理
houses.ForEach(house =>
{
//【照壁、坊、大门、走马转角楼】逐个处理
house.partsInfos.ForEach(pi =>
{
var partName = pi.partsName; //部件名称
//添加高亮组件
if(pi.partsRoot.gameObject.GetComponent<Highlighter>() == null)
{
pi.partsRoot.gameObject.AddComponent<Highlighter>();
}
//每个物体逐个处理——添加事件
pi.parts.ForEach(obj =>
{
//添加组件——EventTrigger
if (obj.GetComponent<EventTrigger>() == null)
{
obj.gameObject.AddComponent<EventTrigger>();
}
//添加Collider组件
if (obj.GetComponent<Collider>() == null)
{
//obj.gameObject.AddComponent<BoxCollider>();
obj.gameObject.AddComponent<MeshCollider>();
}
//得着焦点
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerEnter, (PointerEventData eventData) =>
{
Debug.Log($"进入物体:{partName} {obj.name} {currentPart} {Time.realtimeSinceStartup}");
pi.partsRoot.GetComponent<Highlighter>().tween = true;
ShowTag.ShowNameTag(partName, true);
});
//失去焦点
obj.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerExit, (PointerEventData eventData) =>
{
Debug.Log($"退出物体:{partName} {obj.name} {currentPart} {Time.realtimeSinceStartup}");
pi.partsRoot.GetComponent<Highlighter>().tween = false;
ShowTag.ShowNameTag(partName, false);
});
});
});
});
#endregion =============================事件绑定=============================end
}