描述当AI发现玩家时,不会立马发动攻击,则会在玩家周围进行圆周运动(漫步),等待足够长时间后发动攻击,
效果图
其中用LineRederer来绘制轨迹
话不多说直接上代码
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class AiCM : MonoBehaviour
{
[Header("时间尺")]
[Range(0, 4)]
public float scale;
public int framRate=30;
[Header("显示")]
public Text txt_velocity;
public Text txt_Distance;
public Vector3 direction;
public Vector3 rotaionDirection;
/// <summary>
/// 基础速度
/// </summary>
[Header("漫步")]
public float speed = 3f;
/// <summary>
/// 徘徊半径
/// </summary>
public float wanderRadius = 2f;
/// <summary>
/// 徘徊最大距离
/// </summary>
public float wanderDistance = 4f;
/// <summary>
/// 徘徊的目标
/// </summary>
public Transform Target;
/// <summary>
/// 周期 = 2PI v /v
/// </summary>
public float CycleT;
/// <summary>
/// 角速度 = 2pi / T
/// </summary>
public float angleSpeed;
/// <summary>
/// 反转方向
/// <para>真 逆时针 假 顺时针</para>
/// </summary>
public bool inverse;
public float angle;
public float intervalTime = 3f;
public Vector3 oldDirection;
public Vector3 currentDirection;
private float runIntervalTime;
private float currentTime;
private bool _wanderFlag;
private Transform currentTarget;
NavMeshAgent Agent;
CharacterController cc;
void Start()
{
cc = GetComponent<CharacterController>();
Agent = GetComponent<NavMeshAgent>();
Application.targetFrameRate = framRate;
}
// Update is called once per frame
void Update()
{
if (scale != Time.timeScale)
{
Time.timeScale = scale;
}
if(wanderRadius >= wanderDistance)
{
wanderRadius = wanderDistance - 0.5f;
}
MoveToTarget();
#region 朝向旋转部分
if (!_wanderFlag)
{
rotaionDirection = Agent.desiredVelocity;
}
else
{
rotaionDirection = (currentTarget.position - transform.position);
}
var dir = Vector3.ProjectOnPlane(rotaionDirection, transform.up).normalized;
var roa = Quaternion.LookRotation(dir, transform.up);
transform.rotation = Quaternion.Slerp(transform.rotation, roa, 1 - Mathf.Exp(-10 * Time.deltaTime));
#endregion
cc.Move(new Vector3(direction.x, 0, direction.z) * 2 * speed * Time.deltaTime);
if (txt_velocity) txt_velocity.text = cc.velocity.magnitude.ToString("#0.00");
if (txt_Distance) txt_Distance.text = Vector3.Distance(transform.position, currentTarget.position).ToString("#0.00");
}
void MoveToTarget()
{
currentTarget = Target;
if (Agent.pathPending)
{
Debug.Log($"计算路程中 丢弃这帧{Time.frameCount}");
return;
}
if ((Target.position - transform.position).sqrMagnitude > (wanderDistance + 1) * (wanderDistance + 1))
{
Agent.isStopped = false;
Agent.SetDestination(currentTarget.position);
direction = Agent.desiredVelocity;
_wanderFlag = false;
}
else if (Agent.remainingDistance <= wanderDistance &&!_wanderFlag)
{
Agent.ResetPath();
Agent.isStopped = true;
direction = Vector3.zero;
_wanderFlag = true;
angle = 0;
}
if (_wanderFlag)
{
if (Time.time - currentTime > runIntervalTime)
{
inverse ^= true;
runIntervalTime = Random.Range(intervalTime, intervalTime + 3f);
currentTime = Time.time;
}
float runRadius = wanderRadius;
//计算周期
CycleT = (2 * Mathf.PI * runRadius) / (speed);// Random.Range(wanderRadius, wanderRadius + 1f);
if (CycleT == 0) return;
//计算角速度
angleSpeed = (2 * Mathf.PI / CycleT)*2 ;
angle += (angleSpeed * (inverse ? 1 : -1)) * Time.deltaTime;//累加已经转过的角度
float posX = (runRadius * Mathf.Sin(angle )) + Target.position.x;//计算x位置
float posZ = (runRadius * Mathf.Cos(angle )) + Target.position.z;//计算y位置
Vector3 dir = new Vector3(posX, 0, posZ);
Agent.isStopped = false;
Agent.SetDestination(dir);
direction = Agent.desiredVelocity;
}
direction.Normalize();
}
}
面板信息