165 lines
4.6 KiB
C#
165 lines
4.6 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.AI;
|
||
using UnityEngine.EventSystems;
|
||
|
||
[RequireComponent(typeof(NavMeshAgent))]
|
||
public class NavController : BaseController
|
||
{
|
||
/// <summary>
|
||
/// 单击时显示的光圈对象
|
||
/// </summary>
|
||
[Tooltip("单击时显示的光圈对象")]
|
||
public GameObject preClick;
|
||
|
||
/// <summary>
|
||
/// 可点击的地面层
|
||
/// </summary>
|
||
[Tooltip("地面所在的层,需要将地面对象的层设为此")]
|
||
public LayerMask layer;
|
||
|
||
/// <summary>
|
||
/// 角色寻路旋转速度
|
||
/// </summary>
|
||
[Tooltip("角色寻路旋转速度")]
|
||
public float rotateSpeed = 50f;
|
||
|
||
/// <summary>
|
||
/// 角色寻路移动速度
|
||
/// </summary>
|
||
[Tooltip("角色寻路移动速度")]
|
||
public float moveSpeed = 2f;
|
||
|
||
/// <summary>
|
||
/// 角色寻路最远距离
|
||
/// </summary>
|
||
[Tooltip("角色寻路最远距离")]
|
||
public float MaxNavDistance = 10f;
|
||
|
||
/// <summary>
|
||
/// 导航代理对象
|
||
/// </summary>
|
||
NavMeshAgent agent;
|
||
|
||
GameObject objClick;
|
||
|
||
void Start()
|
||
{
|
||
agent = GetComponent<NavMeshAgent>();
|
||
|
||
if (agent != null)
|
||
{
|
||
// 初始化移动和旋转速度
|
||
agent.speed = moveSpeed;
|
||
agent.angularSpeed = rotateSpeed;
|
||
}
|
||
if(transform.parent != null)
|
||
objClick = Instantiate(preClick, transform.parent.transform);
|
||
else
|
||
objClick = Instantiate(preClick);
|
||
objClick.SetActive(false);
|
||
|
||
layerMask = (1 << 0) | (1 << 6); // 地面跟默认层(墙)
|
||
}
|
||
// 射线检测
|
||
RaycastHit hit;
|
||
Ray ray;
|
||
int layerMask;
|
||
NavMeshHit meshHit;
|
||
|
||
Vector3 mouseDownPos;
|
||
|
||
void LateUpdate()
|
||
{
|
||
if (CanControl
|
||
&& agent.enabled
|
||
&& !IsTouchOnControl
|
||
&& !IsJoyStickOnControl
|
||
&& !IsUIClicked)
|
||
{
|
||
if (Input.GetMouseButtonUp(1) || Input.touchCount == 1)
|
||
{
|
||
if (!EventSystem.current.IsPointerOverGameObject())
|
||
{
|
||
if (!IsMouseOnControl && Input.touchCount == 1)
|
||
{
|
||
ray = CommonData.MainCamera.ScreenPointToRay(Input.touches[0].position);
|
||
}
|
||
else
|
||
{
|
||
ray = CommonData.MainCamera.ScreenPointToRay(Input.mousePosition);
|
||
}
|
||
|
||
if (Physics.Raycast(ray, out hit, MaxNavDistance, layerMask))
|
||
{
|
||
// Debug.Log(hit.collider.name);
|
||
// 判断点击的对象所在层与所设置的层是否一致
|
||
if (Mathf.Pow(2, hit.collider.gameObject.layer) == layer.value)
|
||
{
|
||
if (NavMesh.SamplePosition(hit.point, out meshHit, 1.0f, NavMesh.AllAreas))
|
||
{
|
||
// agent.enabled = true;
|
||
|
||
// 设置提示对象位置并显示
|
||
objClick.transform.position = hit.point;
|
||
objClick.SetActive(true);
|
||
|
||
// 自动寻路到目标位置
|
||
agent.isStopped = false;
|
||
agent.SetDestination(hit.point);
|
||
|
||
// 标识自动寻路控制中
|
||
IsNavOnControl = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果控下键盘或鼠标则停止寻路
|
||
// if (IsMouseOnControl || IsKeyOnControl || IsJoyStickOnControl)
|
||
if (IsKeyOnControl || IsJoyStickOnControl)
|
||
{
|
||
StopNav();
|
||
}
|
||
|
||
if (IsNavOnControl && !IsMoving())
|
||
{
|
||
IsNavOnControl = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止寻路
|
||
/// </summary>
|
||
public void StopNav()
|
||
{
|
||
if (agent.enabled)
|
||
{
|
||
agent.isStopped = true; // 停止自动寻路
|
||
}
|
||
|
||
objClick.SetActive(false); // 隐藏点击图标对象
|
||
IsNavOnControl = false;
|
||
|
||
// agent.enabled = false;
|
||
}
|
||
|
||
// Unity导航是否到达目的地的方法,(包括有些不可能到达的目的地)
|
||
public bool IsMoving()
|
||
{
|
||
if (!agent.enabled)
|
||
return false;
|
||
//bool r = agent.pathPending || agent.remainingDistance > agent.stoppingDistance || agent.velocity != Vector3.zero;
|
||
//r = agent.enabled ? r : false;
|
||
//return r;
|
||
|
||
return agent.enabled ?
|
||
agent.pathPending || agent.remainingDistance > agent.stoppingDistance || agent.velocity != Vector3.zero
|
||
:
|
||
false;
|
||
}
|
||
}
|