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