Files
TaiWan/Assets/Roaming/Scripts/Controller/Camera/NavController.cs
2025-10-31 15:20:38 +08:00

165 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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