Files
Main/Assets/Code/Logic/_Required/Input/Handler/HitHandler.cs
2025-01-25 04:38:09 +08:00

214 lines
7.5 KiB
C#

using Thousandto.Code.Center;
using Thousandto.Code.Global;
using Thousandto.Code.Logic.LocalPlayerBT;
using Thousandto.Core.Asset;
using Thousandto.Plugins.Common.UniScene;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace Thousandto.Code.Logic
{
/// <summary>
/// 点击操作的处理器
/// </summary>
public class HitHandler
{
#region//常量处理
//有效射线距离
private const float PickRaycastDistance = 60;
//有效射线的半径
private const float PickRayRadius = 0.4f;
#endregion
#region//私有变量
//是否点击了地面
private bool _touchGround = false;
//点击了地面的时间
private float _touchTime = 0;
//当前场景的主摄像机
private Camera _curCamera = null;
//点击地面的特效
private FGameObjectVFX _hitGroundVfx = null;
#endregion
#region//公共接口方法
//刷新信息
public void Refresh( Camera camera)
{
_curCamera = camera;
}
public void Reset()
{
_curCamera = null;
if (_hitGroundVfx != null)
{
_hitGroundVfx.Destroy();
_hitGroundVfx = null;
}
}
//点击操作
public void OnHit(Vector2 fingerPos)
{
if (IsValid())
{
Ray ray = _curCamera.ScreenPointToRay(fingerPos);
Vector3 hitStart = ray.origin;
Vector3 hitEnd = hitStart + ray.direction * PickRaycastDistance;
//以点击点为圆心的区域,查找所有的Collider
var hitAllObjs = Physics.SphereCastAll(ray, PickRayRadius, PickRaycastDistance, LayerUtils.SceneObject_Mask);
var isHitChar = false;
if (hitAllObjs != null && hitAllObjs.Length > 0)
{
//当点击了角色目标后的处理
var charList = ConvertToCharacterList(hitAllObjs);
if (charList.Count > 0)
{
LocalPlayer lp = GameCenter.GameSceneSystem.GetLocalPlayer();
Character hitChar = null;
//针对所有目标对象,进行处理,优先检查是否点击了NPC(处理一大堆角色围着NPC的问题)
for (int i = 0; i < charList.Count; i++)
{
if (charList[i] is Npc)
{
hitChar = charList[i];
var npc = charList[i] as Npc;
if (lp != null) lp.SetCurSelectedTargetId(npc.ID, false);
PlayerBT.Talk.Write(npc);
isHitChar = true;
break;
}
else if (charList[i] is Collection)
{
hitChar = charList[i];
if (lp != null) lp.SetCurSelectedTargetId(hitChar.ID, false);
PlayerBT.Collect.Write();
isHitChar = true;
break;
}
}
//如果没有特殊的处理,那么就直接找到可以被选择的角色
if (hitChar == null)
{
for (int i = 0; i < charList.Count; i++)
{
if (charList[i].CanBeSelect)
{
if (lp != null) lp.SetCurSelectedTargetId(charList[i].ID, false);
isHitChar = true;
break;
}
}
}
}
}
#if USE_PC_MODEL
if(!isHitChar)
{
RaycastHit hit;
//如果没有点击到物体,那么就检测是否点击地面
bool rePicked = Physics.Raycast(ray, out hit, PickRaycastDistance, LayerUtils.LayerToMask(LayerUtils.Trigger));
if (rePicked)
{
OnHitGround(hit);
}
}
#endif
}
}
#endregion
#region//私有方法
//临时存储被点击的物体
private List<Character> _tempHitCharacterList = new List<Character>();
//获取可被点击的物体
private List<Character> ConvertToCharacterList(RaycastHit[] hits)
{
_tempHitCharacterList.Clear();
for (int i = 0; i < hits.Length; i++)
{
var go = hits[i].collider.gameObject;
if (go != null)
{
if (go.layer == LayerUtils.RemotePlayer || go.layer == LayerUtils.Monster)
{
var ea = go.GetComponent<FRealObjectScript>();
if (ea != null)
{
var skin = ea.GetSkin();
if (skin != null && skin.LogicObject != null && skin.LogicObject is Character)
{
_tempHitCharacterList.Add(skin.LogicObject as Character);
}
}
}
}
}
return _tempHitCharacterList;
}
//点击了地面
private void OnHitGround(RaycastHit hit)
{
_touchGround = true;
_touchTime = Time.time;
var lp = GameCenter.GameSceneSystem.GetLocalPlayer();
if (lp == null)
{
return;
}
//如果已经关闭了点击地面移动
if (GameCenter.GameSetting.GetSetting(GameSettingKeyCode.CheckGroundMove) == 0)
return;
float h = 0.2f;
PlayerBT.Owner.GetHeightOnTerrain(hit.point.x, hit.point.z, out h);
var pos = hit.point;
var height = 0f;
if(!lp.Scene.GetHeightOnTerrain(pos.x, pos.z, out height))
{
//无法到达的位置
return;
}
pos.y = height;
if (lp.Scene.navigator.IsBlocked(pos))
{
//无法到达的位置
return;
}
//点击地面播放特效
if (_hitGroundVfx == null || _hitGroundVfx.IsFreeze)
{
_hitGroundVfx = new FGameObjectVFX(ModelTypeCode.OtherVFX, 10295, true, false);
_hitGroundVfx.SetLayer(LayerUtils.Default, true);
_hitGroundVfx.SetPosition(pos);
_hitGroundVfx.IsFinishDestroy = false;
_hitGroundVfx.StopIsDeactive = true;
_hitGroundVfx.Play(1);
}
else
{
_hitGroundVfx.SetPosition(pos);
_hitGroundVfx.Stop();
_hitGroundVfx.Play(1);
}
PlayerBT.MapMove.Write(-1, pos, 0.1f, true, false);
}
//是否有效
private bool IsValid()
{
return _curCamera != null && PlayerBT.IsInitPlayerBD;
}
#endregion
}
}