private bool GetAllEntitySelectedByVirtualCamera(ref List <SpacecraftEntity> targetList) { MainCameraComponent mainCam = CameraManager.GetInstance().GetMainCamereComponent(); SkillSystemGrow skillGrow = m_PlayerSkillProxy.GetCurrentWeaponSkill().GetSkillGrow(); float range = skillGrow.Range * SceneController.SPACE_ACCURACY_TO_CLIENT; // 粗略的拾取. // 拾取锥体视为一个相机, 把技能射程视为远裁剪面. 根据FOV取远裁剪面的大小, 投射这个大小的Box, 获取所有拾取到的Entity { // 所有粗略裁剪的物体 = Physics.BoxCastAll(投射开始点, 盒子边长, 相机方向, SkillLayer) float halfBoxVerticalSideLength = range * Mathf.Tan(m_ReticleHorizontalFOVParam / m_ReticleAspect * 0.5f * Mathf.Deg2Rad); float halfBoxHorizontalSideLength = halfBoxVerticalSideLength * m_ReticleAspect; // 投射开始的点 = 相机近裁剪面的中心点 + 相机方向 * 盒子边长的一半 Vector3 startPoint = mainCam.transform.position + (mainCam.GetCamera().nearClipPlane + halfBoxVerticalSideLength) * mainCam.GetForward(); RaycastHit[] hitInfos = Physics.BoxCastAll(startPoint, new Vector3(halfBoxHorizontalSideLength, halfBoxVerticalSideLength, halfBoxVerticalSideLength), mainCam.GetForward(), Quaternion.identity, range, LayerUtil.GetLayersIntersectWithSkillProjectile(true)); for (int iHit = 0; iHit < hitInfos.Length; iHit++) { Rigidbody rigidBody = hitInfos[iHit].rigidbody; if (rigidBody == null) { continue; } SpacecraftEntity entity = rigidBody.GetComponent <SpacecraftEntity>(); if (entity != null) { targetList.Add(entity); } } } if (m_VirtualCameraForReticleSelection != null) { // 更新虚拟相机的方向和位置 m_VirtualCameraForReticleSelection.transform.position = mainCam.transform.position; m_VirtualCameraForReticleSelection.transform.rotation = mainCam.transform.rotation; // 更精细的判断. 当前版本仅计算目标中心点是不是在 虚拟相机 里面 for (int iTarget = 0; iTarget < targetList.Count; iTarget++) { Vector3 viewportPos = m_VirtualCameraForReticleSelection.WorldToViewportPoint(targetList[iTarget].transform.position); if (viewportPos.x < 0 || viewportPos.y < 0 || viewportPos.x > 1 || viewportPos.y > 1) { targetList.RemoveAt(iTarget); iTarget--; } } } return(targetList.Count > 0); }
/// <summary> /// 正前方中心点射线选中的目标 /// </summary> /// <returns></returns> private BaseEntity GetForwardEntity() { MainCameraComponent mainCam = CameraManager.GetInstance().GetMainCamereComponent(); Ray ray = new Ray(mainCam.GetPosition(), mainCam.GetForward()); RaycastHit hitInfo = new RaycastHit(); if (Physics.Raycast(ray, out hitInfo, m_SkillMaxDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { return(hitInfo.collider.attachedRigidbody?.GetComponent <BaseEntity>()); } else { return(null); } }
/// <summary> /// 打出一条射线, 检测碰到得一个可攻击的目标 /// </summary> /// <param name="targetPoint"></param> /// <param name="maxDistance"></param> /// <param name="hitInfo"></param> /// <returns>是否拾取到了技能目标</returns> public static bool PickSkillTargetEntityByRaycast(Vector3 targetPoint, float maxDistance, out RaycastHit hitInfo) { Vector3 mainCamPos = CameraManager.GetInstance().GetMainCamereComponent().GetPosition(); Vector3 dir = CameraManager.GetInstance().GetMainCamereComponent().GetForward(); Ray ray = new Ray(mainCamPos, dir); if (Physics.Raycast(ray, out hitInfo, maxDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { return(true); } else { return(false); } }
/// <summary> /// 中心点射线选中的目标 /// </summary> /// <returns></returns> private SpacecraftEntity GetTargetSelectedByCenterRay() { PlayerSkillVO skillVO = m_PlayerSkillProxy.GetCurrentWeaponSkill(); SkillSystemGrow skillGrow = skillVO.GetSkillGrow(); float maxDistance = skillGrow.Range * SceneController.SPACE_ACCURACY_TO_CLIENT; MainCameraComponent mainCam = CameraManager.GetInstance().GetMainCamereComponent(); Ray ray = new Ray(mainCam.GetPosition(), mainCam.GetForward()); RaycastHit hitInfo = new RaycastHit(); if (Physics.Raycast(ray, out hitInfo, maxDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { return(hitInfo.collider.attachedRigidbody?.GetComponent <SpacecraftEntity>()); } else { return(null); } }
/// <summary> /// 根据这次射击的弹道方向, 计算命中的目标Entity和目标点 /// </summary> /// <param name="camDirAffectedByRecoil"></param> /// <returns></returns> protected SkillTarget CalulateTargetDataByShootingDirection(Vector3 camDirAffectedByRecoil) { // 计算射线碰到的目标点, 并重新计算从Launcher到目标点的方向 PlayerSkillVO skillVO = m_PlayerSkillProxy.GetCurrentWeaponSkill(); SkillSystemGrow skillGrow = skillVO.GetSkillGrow(); float maxDistance = skillGrow.Range * SceneController.SPACE_ACCURACY_TO_CLIENT; Ray ray = new Ray(CameraManager.GetInstance().GetMainCamereComponent().GetPosition(), camDirAffectedByRecoil); RaycastHit hitInfo = new RaycastHit(); if (Physics.Raycast(ray, out hitInfo, maxDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { return(new SkillTarget(hitInfo.collider.attachedRigidbody?.GetComponent <SpacecraftEntity>(), hitInfo.point)); } else { Vector3 skillReleasingDir = (ray.GetPoint(maxDistance) - m_MainPlayer.GetRootTransform().position).normalized; return(new SkillTarget(null, m_MainPlayer.GetRootTransform().position + skillReleasingDir * maxDistance)); } }
/// <summary> /// 改善的,获取目标列表 /// </summary> /// <returns></returns> protected override List <Target> ImproveGetTarget() { List <Target> targets = base.ImproveGetTarget(); Vector3 pos = CameraManager.GetInstance().GetMainCamereComponent().GetPosition(); Vector3 direction = IsChangCheckDirection ? m_CheckDirection : CameraManager.GetInstance().GetMainCamereComponent().GetForward(); Collider[] colliders = Physics.OverlapSphere(pos, m_crosssightinfo.m_MaxRayDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true) /*LayerMask.GetMask("Enemy")*/); for (int i = 0; i < colliders.Length; i++) { Vector3 colliderPos = colliders[i].transform.position; //检测单位位置 if (Vector3.Angle(direction, colliderPos - pos) <= m_crosssightinfo.m_ConeInfo.angle * 0.5f) //单位跟摄像机正方向夹角是否在 1/2角度内 { RaycastHit hit = new RaycastHit(); int layermask = LayerUtil.GetLayersIntersectWithSkillProjectile(true); // LayerMask.GetMask("Enemy"/*, "Obstacles"*/); //指定射线碰撞的对象 Physics.Raycast(pos, colliderPos - pos, out hit, m_crosssightinfo.m_MaxRayDistance, layermask); //检测障碍 if (hit.collider == colliders[i]) //如果途中无其他障碍物,那么射线就会碰撞到敌人 { if (hit.rigidbody != null) { BaseEntity entity = hit.rigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = hit.point; targets.Add(target); GizmosHelper.GetInstance().DrawLine(pos, hit.point, Color.red); } } } } } return(targets); }
/// <summary> /// 选中一个新的目标 /// 1. 与上一帧选中的目标不同 /// 2. 上一帧选中的目标已经锁定完成, 进行下一轮锁定 /// </summary> /// <returns>是否有新的目标</returns> private bool PickNewTarget(out SpacecraftEntity newTarget) { PlayerSkillVO skillVO = m_PlayerSkillProxy.GetCurrentWeaponSkill(); SkillSystemGrow skillGrow = skillVO.GetSkillGrow(); float maxDistance = skillGrow.Range * SceneController.SPACE_ACCURACY_TO_CLIENT; MainCameraComponent mainCam = CameraManager.GetInstance().GetMainCamereComponent(); Ray ray = new Ray(mainCam.GetPosition(), mainCam.GetForward()); RaycastHit hitInfo = new RaycastHit(); // UNDONE // 第一版: 使用屏幕中心射线作为目标选取射线. NOW // 第二版: 使用 Physics.BoxCast if (Physics.Raycast(ray, out hitInfo, maxDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { SpacecraftEntity pickedTarget = hitInfo.collider.attachedRigidbody?.GetComponent <SpacecraftEntity>(); newTarget = pickedTarget; return(true); } else { newTarget = null; return(false); } }
/// <summary> /// 改善的,获取目标列表 /// </summary> /// <returns></returns> protected override List <Target> ImproveGetTarget() { List <Target> targets = base.ImproveGetTarget(); Vector3 pos = CameraManager.GetInstance().GetMainCamereComponent().GetPosition(); Vector3 direction = IsChangCheckDirection ? m_CheckDirection : CameraManager.GetInstance().GetMainCamereComponent().GetForward(); if (m_crosssightinfo.m_RoundInfo.detectionMode == DetectionMode.One) { RaycastHit hitInfo = new RaycastHit(); if (Physics.SphereCast(pos, //起始点 m_crosssightinfo.m_RoundInfo.radius, //半径 direction, //方向 out hitInfo, m_crosssightinfo.m_MaxRayDistance, //最大距离 //LayerMask.GetMask("Enemy"))) //层 LayerUtil.GetLayersIntersectWithSkillProjectile(true))) { if (hitInfo.rigidbody != null) { BaseEntity entity = hitInfo.rigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = hitInfo.point; targets.Add(target); GizmosHelper.GetInstance().DrawLine(pos, hitInfo.point, Color.red); GizmosHelper.GetInstance().DrawSphere(hitInfo.point, m_crosssightinfo.m_RoundInfo.radius, Color.red); } } } } else if (m_crosssightinfo.m_RoundInfo.detectionMode == DetectionMode.All) { RaycastHit[] hits = Physics.SphereCastAll(pos, //起始点 m_crosssightinfo.m_RoundInfo.radius, //半径 direction, //方向 m_crosssightinfo.m_MaxRayDistance, //最大距离 // LayerMask.GetMask("Enemy")); //层 LayerUtil.GetLayersIntersectWithSkillProjectile(true)); for (int i = 0; i < hits.Length; i++) { RaycastHit hit = hits[i]; if (hit.rigidbody != null) { BaseEntity entity = hit.rigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = hit.point; targets.Add(target); GizmosHelper.GetInstance().DrawLine(pos, hit.point, Color.red); } } } } return(targets); }
/// <summary> /// 改善的,获取目标列表 /// </summary> /// <returns></returns> protected override List <Target> ImproveGetTarget() { List <Target> targets = base.ImproveGetTarget(); Vector3 pos = CameraManager.GetInstance().GetMainCamereComponent().GetPosition(); Vector3 direction = IsChangCheckDirection ? m_CheckDirection : CameraManager.GetInstance().GetMainCamereComponent().GetForward(); Collider[] colliders = Physics.OverlapSphere(pos, m_crosssightinfo.m_MaxRayDistance, LayerUtil.GetLayersIntersectWithSkillProjectile(true) /*LayerMask.GetMask("Enemy")*/); Plane[] planes = null; // 更新虚拟相机的方向和位置 if (m_virtualCamera != null) { m_virtualCamera.transform.position = pos; m_virtualCamera.transform.rotation = CameraManager.GetInstance().GetMainCamereComponent().GetRotation(); planes = GeometryUtility.CalculateFrustumPlanes(m_virtualCamera); } for (int i = 0; i < colliders.Length; i++) { if (planes == null) { break; } if (GeometryUtility.TestPlanesAABB(planes, colliders[i].bounds)) { BaseEntity entity = colliders[i].attachedRigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = entity.transform.position; targets.Add(target); GizmosHelper.GetInstance().DrawLine(pos, target.target_pos, Color.red); } } } return(targets); }
/// <summary> /// 获取弹道上的目标,并返回弹道方向 /// </summary> public override void GetBallisticTargetAndOutDirection(out List <Target> targets, out Vector3 direction, params object[] args) { Vector3 CamerPos = CameraManager.GetInstance().GetMainCamereComponent().GetPosition();// Camera.main.transform.position; base.GetBallisticTargetAndOutDirection(out targets, out direction, args); if (m_virtualCamera != null) { float offx = 0.0f; //范围 0--0.5 float offy = 0.0f; m_ballisticOffsetFunc?.Invoke(out offx, out offy, m_ballisticOffsetFunc_args); float offz = 500; //到摄像机近视窗平面距离 Vector3 viewPos = new Vector3(offx, offy, offz); //(0.5f + offx, 0.5f + offy, offz); Vector3 worldPos = m_virtualCamera.ViewportToWorldPoint(viewPos); direction = (worldPos - CamerPos).normalized; //验证 // GameObject ga = new GameObject("ddddd"); // ga.transform.position = worldPos; // ga.AddComponent<BoxCollider>().size = Vector3.one; if (m_crosssightinfo.m_ConeSquareInfo.detectionMode == DetectionMode.One) { //射线检测目标 RaycastHit hit = new RaycastHit(); int layermask = LayerUtil.GetLayersIntersectWithSkillProjectile(true); // LayerMask.GetMask("Enemy"/*, "Obstacles"*/); //指定射线碰撞的对象 Physics.Raycast(CamerPos, worldPos - CamerPos, out hit, offz, layermask); //检测障碍 if (hit.rigidbody != null) { BaseEntity entity = hit.rigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = hit.point; targets.Add(target); } } } else if (m_crosssightinfo.m_ConeSquareInfo.detectionMode == DetectionMode.All) { int layermask = LayerUtil.GetLayersIntersectWithSkillProjectile(true); // LayerMask.GetMask("Enemy"/*, "Obstacles"*/); //指定射线碰撞的对象 RaycastHit[] hits = Physics.RaycastAll(CamerPos, //起始点 worldPos - CamerPos, //方向 m_crosssightinfo.m_MaxRayDistance, //最大距离 layermask); for (int tt = 0; tt < hits.Length; tt++) { RaycastHit hitt = hits[tt]; if (hitt.rigidbody != null) { BaseEntity entity = hitt.rigidbody?.GetComponent <BaseEntity>(); if (entity != null && CCrossSightLoic.IsAdd(targets, entity.EntityId())) { Target target = new Target(); target.target_entityId = entity.EntityId(); target.target_pos = hitt.point; targets.Add(target); GizmosHelper.GetInstance().DrawLine(CamerPos, hitt.point, Color.red); } } } } } }