
知识点
-
向量减法及其应用
-
向量归一化原理
-
向量点乘的几何意义
-
向量叉乘的特性
-
向量距离计算






using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class MonsterAI : MonoBehaviour
{
// 复习一下向量的减法,实现怪物朝向人移动
//【触发】人物距离怪物50米内 【执行】怪物朝向人的方向移动
public Transform PlayerTran; // 存储游戏主角的Transform组件
public Transform MosnsterTran; // 存储单个怪物的Transform组件(可能是用于测试或特定怪物)
GameObject[] MonsterTran; // 存储所有带有"Monster"标签的怪物对象数组
public float MoveDirSeed = 10f; // 怪物的移动速度
private void Start()
{
// 在游戏开始时,查找场景中所有带有"Monster"标签的游戏对象
MonsterTran = GameObject.FindGameObjectsWithTag("Monster");
}
// Update is called once per frame
void Update()
{
// 每帧更新怪物移动逻辑
MonsterMove();
// 计算并显示怪物与玩家之间的距离
VectorDistance();
// 计算法线向量并绘制调试射线
// 法线向量垂直于怪物到玩家的向量和玩家前方向量的平面
Vector3 Normal = NormalLine(MosnsterTran.position - PlayerTran.position, PlayerTran.forward);
// 绘制红色射线表示法线方向
Debug.DrawRay(PlayerTran.position, Normal * 100, Color.red);
// 绘制玩家前方方向的射线
Debug.DrawRay(PlayerTran.position, PlayerTran.forward * 100);
}
/// <summary>
/// 这个函数实现怪物追踪人去移动,且判断怪物在人的方位,用到了向量的减法和点乘
/// 功能:控制所有怪物向玩家移动,并判断怪物相对于玩家的方位
/// </summary>
void MonsterMove()
{
#region 怪物移动和方位判断区域
// 遍历所有怪物对象
for (int i = 0; i < MonsterTran.Length; i++)
{
// 检查怪物对象是否存在
if (MonsterTran[i] != null)
{
// 计算从怪物指向玩家的方向向量(向量减法:终点-起点)
Vector3 MoveDir = PlayerTran.position - MonsterTran[i].transform.position;
// 计算从玩家指向怪物的方向向量
Vector3 ForwordDir = MonsterTran[i].transform.position - PlayerTran.position;
// 检查怪物与玩家之间的距离是否在50单位内
if (MoveDir.magnitude <= 50)
{
// 如果距离在范围内,让怪物向玩家方向移动
// Vector3.Normalize将方向向量转换为单位向量,保持方向但长度为1
// Time.deltaTime使移动与帧率无关
MonsterTran[i].transform.Translate(Vector3.Normalize(MoveDir) * MoveDirSeed * Time.deltaTime);
}
// ============= 下面是判断怪物是否在人物前后方 =============
// 使用点乘判断两个向量的方向关系:
// 点乘 > 0: 两个向量方向基本相同(夹角小于90度)
// 点乘 = 0: 两个向量垂直(夹角等于90度)
// 点乘 < 0: 两个向量方向基本相反(夹角大于90度)
// 计算玩家前方方向与指向怪物方向的点乘值
if (Vector3.Dot(PlayerTran.forward, ForwordDir.normalized) > 0)
{
// 点乘大于0,说明怪物在玩家前方
Debug.Log("怪物在你的前方,他叫+" + MonsterTran[i]);
}
else if (Vector3.Dot(PlayerTran.forward, ForwordDir.normalized) == 0)
{
// 点乘等于0,说明怪物在玩家正侧面
Debug.Log("怪物在你的正侧面,他叫+" + MonsterTran[i]);
}
else
{
// 点乘小于0,说明怪物在玩家后方
Debug.Log("怪物在你的后方,他叫+" + MonsterTran[i]);
}
}
}
#endregion
}
/// <summary>
/// 计算并显示单个怪物与玩家之间的距离
/// 功能:计算MosnsterTran指向的怪物与玩家之间的距离,并绘制连线
/// </summary>
void VectorDistance()
{
// 计算两个点之间的直线距离
float distan = Vector3.Distance(MosnsterTran.position, PlayerTran.position);
// 在场景中绘制从怪物位置到玩家位置的连线(在Scene视图中可见)
Debug.DrawLine(MosnsterTran.position, PlayerTran.position);
// 在控制台输出距离信息
Debug.Log("距离是" + distan);
}
/// <summary>
/// 计算两个向量的叉积,得到垂直于这两个向量的法线向量
/// 功能:计算向量A和向量B的叉积,返回法线向量
/// </summary>
/// <param name="A">第一个输入向量</param>
/// <param name="B">第二个输入向量</param>
/// <returns>返回垂直于A和B的法线向量</returns>
public Vector3 NormalLine(Vector3 A, Vector3 B)
{
// Vector3.Cross计算两个向量的叉积
// 结果向量同时垂直于输入的两个向量
return Vector3.Cross(A, B);
}
}
245

被折叠的 条评论
为什么被折叠?



