版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gohuge/article/details/80244723
网格自动寻路:
① 把场景中不动的物体勾选static
② 烘焙寻路网格
③ 给需要寻路的物体添加脚本添加NavMeshAgent组件和控制脚本
实现:
① 制作一个场景Terrain对象的地图,上面可以铺上一些Cube
把场景设为静态
路径烘焙只烘焙静有静态导航属性的对象,也可以通过在Inspector中设置要烘焙的对象,没有改属性的变没有路径
烘焙过寻路网格后会显示蓝色的网格,表示可行走区域
选择window→navigation,调出navigation面板,选择bake,形成一个蓝色路面,enemy将在这个蓝色路面上进行寻路
注意,寻路对象的NavMeshAgent组件在没有网格的情况下不可使用。
using
System.Collections;
using
System.Collections.Generic;
using
UnityEngine;
using
UnityEngine.AI;
public
class
RayTest : MonoBehaviour {
private
Ray ray;
private
RaycastHit hit;
//射线碰到的碰撞信息
public
GameObject navPlayer;
//寻路的人
private
NavMeshAgent agent;
private
void
Start()
{
agent = navPlayer.GetComponent<NavMeshAgent>();
}
private
void
Update ()
{
//射线起始位置
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if
(Physics.Raycast(ray,
out
hit, 100) && Input.GetMouseButtonDown(0))
{
agent.SetDestination(hit.point);
Debug.DrawLine(ray.origin, hit.point, Color.red);
}
}
}
碰撞检测:
发生触发的条件:
1、发生碰撞的物体两者其中之一有Rigidbody即可,发生碰撞的两个游戏对象必须有Collider,其中一方勾选IsTrigger表示被动方
2、确认地形上是可达的,像下图盒子放置的位置,恰好玩家卡在缝里上不去就一直没发生碰撞事件
角色控制
角色控制大概有4种途径,鼠标点击,键盘控制(下面代码附这两种逻辑),另外还有手机的重力感应和手势键盘
public class PlayerMove : MonoBehaviour
{
[Header("是否点击移动")]
public bool isClickMove = false;
[Header("是否采用网格导航")]
public bool IsNavAgent;
[Header("移动速度")]
public float m_speed = 5f;
[Header("跑动动作")]
public string RUN = "is_run";
[Header("待机动作")]
public string IDLE = "is_idle";
float ogrY = 0;
// 动作 0 待机,1 跑动
int currentState = 0;
// 寻路者
NavMeshAgent agent;
// 玩家
GameObject player;
// 目标位置
Vector3 targetPos;
void Start()
{
agent = this.GetComponent<NavMeshAgent>();
targetPos = this.transform.position;
ogrY = targetPos.y;
}
void LateUpdate()
{
if (isClickMove)
{
MoveControlByMouse();
}
else
{
MoveControlByTranslate();
}
}
//Translate移动控制函数
void MoveControlByTranslate()
{
if (Input.GetKey(KeyCode.W) | Input.GetKey(KeyCode.UpArrow)) //前
{
this.transform.Translate(Vector3.forward * m_speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.S) | Input.GetKey(KeyCode.DownArrow)) //后
{
this.transform.Translate(Vector3.forward * -m_speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.A) | Input.GetKey(KeyCode.LeftArrow)) //左
{
this.transform.Translate(Vector3.right * -m_speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D) | Input.GetKey(KeyCode.RightArrow)) //右
{
this.transform.Translate(Vector3.right * m_speed * Time.deltaTime);
}
}
// 鼠标点击移动
void MoveControlByMouse()
{
if (Input.GetMouseButton(0))
{
//获得鼠标屏幕位置
Vector3 mousePos = Input.mousePosition;
//将屏幕位置转为射线
Ray ray = Camera.main.ScreenPointToRay(mousePos);
//用来记录射线碰撞记录
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
// 点中地板砖
//if (!hit.collider.name.Equals("Terrain"))
//{
// return;
//}
targetPos = new Vector3(hit.point.x, ogrY, hit.point.z);
if (!player) {
player = this.transform.GetChild(0).gameObject;
}
// 差值
transform.rotation = Quaternion.LookRotation(targetPos - transform.position);
if (IsNavAgent)
{
agent.SetDestination(targetPos);
}
}
}
if (IsNavAgent)
{
if (agent.remainingDistance == 0)
{
AnimatorChange(0);
}
else
{
AnimatorChange(1);
}
}
else {
if (Mathf.Abs(transform.position.x - targetPos.x) > 0.1 || Mathf.Abs(transform.position.z - targetPos.z) > 0.1)
{
AnimatorChange(1);
transform.position = Vector3.MoveTowards(transform.position, targetPos, m_speed * Time.deltaTime);
}
else
{
AnimatorChange(0);
}
}
}
// 动作切换
void AnimatorChange(int state)
{
if (!player) return;
if (currentState == state) return;
currentState = state;
switch (state)
{
case 0:
Animator ani = player.GetComponent<Animator>();
ani.SetTrigger(IDLE);
break;
case 1:
ani = player.GetComponent<Animator>();
ani.SetTrigger(RUN);
break;
default:
break;
}
}
}
角色设置