第2章 Unity游戏人工智能系统架构解析与构建
本章节解析了Unity游戏AI系统的层次化架构,重点探讨了运动控制层的设计与实现。运动控制层作为AI系统基础,负责角色移动、物理行为和环境交互。文章详细介绍了实现要点,包括物理系统集成、动画同步、性能优化和障碍规避等,并提供了完整的C#代码示例,展示了一个可扩展的运动系统实现方案,涵盖速度控制、重力应用、地面检测和路径规划等核心功能。
第二章 Unity游戏人工智能系统架构解析与构建
2.1 游戏AI系统的层次化架构模型
2.1.1 运动控制层的设计与实现
运动控制层是游戏人工智能系统的基础,负责处理AI角色的基本移动和物理行为。这一层的主要目标是让AI角色能够在游戏世界中自然、流畅地移动,同时响应环境的变化和约束。
在Unity商业项目中,运动控制层的实现通常需要考虑以下关键因素:
- 物理系统的集成
- 动画状态的同步
- 移动性能的优化
- 环境障碍的规避
- 移动行为的多样性
下面是一个基础的运动控制层实现示例,展示了如何在Unity中构建可扩展的运动系统:
using UnityEngine;
public class AIMovementController : MonoBehaviour
{
[System.Serializable]
public class MovementSettings
{
public float maxSpeed = 5.0f;
public float acceleration = 10.0f;
public float deceleration = 15.0f;
public float rotationSpeed = 540.0f;
public float stoppingDistance = 0.5f;
public float gravityMultiplier = 2.0f;
}
[Header("运动设置")]
[SerializeField]
private MovementSettings movementSettings = new MovementSettings();
[Header("组件引用")]
[SerializeField]
private CharacterController characterController;
[SerializeField]
private Animator animator;
[Header("状态追踪")]
[SerializeField]
private Vector3 currentVelocity;
[SerializeField]
private Vector3 targetVelocity;
[SerializeField]
private Vector3 moveDirection;
[SerializeField]
private bool isGrounded;
[SerializeField]
private float verticalVelocity;
private Transform cachedTransform;
private Vector3 lastPosition;
private float currentSpeed;
private const float groundCheckDistance = 0.3f;
private const float groundCheckRadius = 0.2f;
private const float gravity = -9.81f;
public Vector3 CurrentVelocity
{
get { return currentVelocity; }
}
public float CurrentSpeed
{
get { return currentSpeed; }
}
public bool IsGrounded
{
get { return isGrounded; }
}
private void Awake()
{
InitializeComponents();
}
private void InitializeComponents()
{
cachedTransform = transform;
if (characterController == null)
{
characterController = GetComponent<CharacterController>();
}
if (animator == null)
{
animator = GetComponent<Animator>();
}
currentVelocity = Vector3.zero;
targetVelocity = Vector3.zero;
moveDirection = Vector3.zero;
verticalVelocity = 0f;
}
private void Update()
{
UpdateGroundStatus();
ApplyGravity();
UpdateMovement();
UpdateAnimator();
}
private void UpdateGroundStatus()
{
bool wasGrounded = isGrounded;
// 使用射线检测地面
RaycastHit hit;
Vector3 rayStart = cachedTransform.position + Vector3.up * 0.1f;
if (Physics.SphereCast(
rayStart,
groundCheckRadius,
Vector3.down,
out hit,
groundCheckDistance,
Physics.AllLayers,
QueryTriggerInteraction.Ignore
))
{
isGrounded = true;
verticalVelocity = 0f;
}
else
{
isGrounded = false;
}
// 地面状态变化事件
if (wasGrounded != isGrounded)
{
if (isGrounded)
{
OnLanded();
}
else
{
OnAirborne();
}
}
}
private void ApplyGravity()
{
if (!isGrounded)
{
verticalVelocity += gravity * movementSettings.gravityMultiplier * Time.deltaTime;
}
else
{
// 保持在地面上
verticalVelocity = gravity * 0.1f;
}
}
public void MoveToPosition(Vector3 targetPosition, bool usePathfinding = true)
{
if (!IsPositionReachable(targetPosition))
{
Debug.LogWarning($"目标位置不可达: {targetPosition}");
return;
}
Vector3 directionToTarget;
if (usePathfinding)
{
// 使用路径规划
directionToTarget = CalculatePathDirection(targetPosition);
}
else
{
// 直线移动
directionToTarget = (targetPosition - cachedTransform.position).normalized;
}
MoveInDirection(directionToTarget);
}
public void MoveInDirection(Vector3 direction)
{
if (direction.magnitude < 0.01f)
{
// 停止移动
targetVelocity = Vector3.zero;
return;
}
// 标准化方向向量
direction.Normalize();
// 计算目标速度
targetVelocity = direction * movementSettings.maxSpeed;
// 更新移动方向
moveDirection = direction;
}
public void StopMovement()
{
targetVelocity = Vector3.zero;
moveDirection = Vector3.zero;
}
private void UpdateMovement()
{
// 计算速度差值
Vector3 velocityDifference = targetVelocity - currentVelocity;
// 根据加速度或减速度调整当前速度
float accelerationRate = velocityDifference.magnitude > 0.01f
? movementSettings.acceleration
: movementSettings.deceleration;
// 插值当前速度到目标速度
currentVelocity = Vector3.MoveTowards(
currentVelocity,
targetVelocity,
accelerationRate * Time.deltaTime
);
// 创建最终移动向量(包括垂直速度)
Vector3 finalMoveVector = currentVelocity;
finalMoveVector.y = verticalVelocity;
// 应用移动
if (characterController != null && characterController.enabled)
{
characterController.Move(finalMoveVector * Time.deltaTime);
}
else
{
cachedTransform.position += finalMoveVector * Time.deltaTime;
}
// 更新实际速度(用于动画和状态判断)
currentSpeed = currentVelocity.magnitude;
// 如果正在移动,旋转到移动方向
if (currentSpeed > 0.1f && moveDirection.magnitude > 0.01f)
{
RotateTowardsDirection(moveDirection);
}
}
private void RotateTowardsDirection(Vector3 direction)
{
if (direction.magnitude < 0.01f)
{
return;
}
// 计算目标旋转
Quaternion targetRotation = Quaternion.LookRotation(direction);
// 平滑旋转
cachedTransform.rotation = Quaternion.RotateTowards(
cachedTransform.rotation,
targetRotation,
movementSettings.rotationSpeed * Time.deltaTime
);
}
private Vector3 CalculatePathDirection(Vector3 targetPosition)
{
// 简化版路径计算
// 在实际项目中,这里会集成A*或NavMesh系统
Vector3 direction = (targetPosition - cachedTransform.position).normalized;
// 简单的障碍物回避
RaycastHit hit;
if (Physics.Raycast(
cachedTransform.position,
direction,
out hit,
2.0f,
LayerMask.GetMask("Obstacle"),
QueryTriggerInteraction.Ignore
))
{
// 计算回避方向
Vector3 avoidanceDirection = Vector3.Cross(hit.normal, Vector3.up).normalized;
// 选择与当前方向更接近的回避方向
float dotProduct = Vector3.Dot(avoidanceDirection, direction);
if (dotProduct < 0)
{
avoidanceDirection = -avoidanceDirection;
}
// 混合原始方向和回避方向
direction = Vector3.Lerp(direction, avoidanceDirection, 0.7f).normalized;
}
return direction;
}
private bool IsPositionReachable(Vector3 position)
{
// 简化可达性检查
// 在实际项目中,这里会进行更复杂的检查
float distance = Vector3.Distance(cachedTransform.position, position);
if (distance > 100f) // 最大移动距离限制
{
return false;
}
// 检查是否有直接路径(无遮挡)
RaycastHit hit;
if (Physics.Linecast(
cachedTransform.position,
position,
out hit,
LayerMask.GetMask("Impassable"),
QueryTriggerInteraction.Ignore
))
{
return false;
}
return true;
}
private void UpdateAnimator()
{
if (animator == null)
{
return;
}
// 更新动画参数
animator.SetFloat("Speed", currentSpeed);
animator.SetFloat("MotionSpeed", currentSpeed / movementSettings.maxSpeed);
animator.SetBool("IsGrounded", isGrounded);
// 设置移动方向参数(用于8向移动混合)
if (currentSpeed > 0.1f)
{
Vector3 localMoveDirection = cachedTransform.InverseTransformDirection(moveDirection);
animator.SetFloat("MoveX", localMoveDirection.x);
animator.SetFloat("MoveZ", localMoveDirection.z);
}
}
private void OnLanded()
{
// 着陆时的处理
if (animator != null)
{
animator.SetTrigger("Land");
}
// 重置移动参数
currentVelocity.y = 0f;
}
private void OnAirborne()
{
// 离地时的处理
if (animator != null)
{
animator.SetTrigger("Jump");
}
}
public void Jump(float jumpForce)
{
if (!isGrounded)
{
return;
}
verticalVelocity = jumpForce;
isGrounded = false;
}
public void SetMovementEnabled(bool enabled)
{
if (characterController != null)
{
characterController.enabled = enabled;
}
enabled = enabled;
}
private void OnDrawGizmosSelected()
{
if (!Application.isPlaying)
{
return;
}
// 绘制移动方向
Gizmos.color = Color.green;
Gizmos.DrawRay(cachedTransform.position, moveDirection * 2f);
// 绘制当前速度
Gizmos.color = Color.blue;
Gizmos.DrawRay(cachedTransform.position, currentVelocity);
// 绘制地面检测范围
Gizmos.color = isGrounded ? Color.green : Color.red;
Vector3 groundCheckStart = cachedTransform.position + Vector3.up * 0.1f;
Vector3 groundCheckEnd = groundCheckStart + Vector3.down * groundCheckDistance;
Gizmos.DrawLine(groundCheckStart, groundCheckEnd);
Gizmos.DrawWireSphere(groundCheckEnd, groundCheckRadius);
}
}
2.1.2 决策逻辑层的架构设计
决策逻辑层是AI系统的"大脑",负责根据当前游戏状态、环境信息和角色目标来做出智能决策。这一层处理从简单的状态转换到复杂的计划制定等各种认知任务。
在商业游戏项目中,决策逻辑层的设计需要考虑:
- 决策的响应速度和准确性
- 决策的可预测性和可调试性
- 决策的多样性和适应性
- 决策系统的可扩展性和维护性
下面是决策逻辑层的核心架构实现:
using UnityEngine;
using System;
using System.Collections.Generic;
public class AIDecisionController : MonoBehaviour
{
[System.Serializable]
public class DecisionConfig
{
public float decisionUpdateInterval = 0.2f;
public float maxDecisionTime = 1.0f;
public bool enableDebugLogging = false;
public bool enableGizmos = true;
}
[System.Serializable]
public class BehaviorWeight
{
public string behaviorName;
public float baseWeight = 1.0f;
public AnimationCurve weightCurve = AnimationCurve.Linear(0, 1, 1, 1);
public List<ConditionModifier> conditionModifiers = new List<ConditionModifier>();
}
[System.Serializable]
public class ConditionModifier
{
public string conditionName;
public float modifierValue = 1.0f;
public ComparisonOperator comparison = ComparisonOperator.GreaterThan;
public float threshold = 0.5f;
}
public enum ComparisonOperator
{
GreaterThan,
LessThan,
EqualTo,
NotEqualTo
}
[Header("配置")]
[SerializeField]
private DecisionConfig config = new DecisionConfig();
[Header("行为权重")]
[SerializeField]
private List<BehaviorWeight> behaviorWeights = new List<BehaviorWeight>();
[Header("组件引用")]
[SerializeField]
private AIMovementController movementController;
[SerializeField]
private AIPerceptionController perceptionController;
[SerializeField]
private AIStateController stateController;
[Header("运行时状态")]
[SerializeField]
private string currentDecision;
[SerializeField]
private float decisionConfidence;
[SerializeField]
private float timeSinceLastDecision;
[SerializeField]
private List<DecisionHistory> decisionHistory = new List<DecisionHistory>();
private Dictionary<string, float> conditionValues = new Dictionary<string, float>();
private Dictionary<string, Func<float>> conditionEvaluators = new Dictionary<string, Func<float>>();
private Dictionary<string, Action> behaviorExecutors = new Dictionary<string, Action>();
private float decisionTimer;
private bool isDecisionMaking;
[System.Serializable]
public class DecisionHistory
{
public string decision;
public float confidence;
public float timestamp;
public Dictionary<string, float> conditions;
public DecisionHistory(string decision, float confidence, Dictionary<string, float> conditions)
{
this.decision = decision;
this.confidence = confidence;
this.timestamp = Time.time;
this.conditions = new Dictionary<string, float>(conditions);
}
}
private void Awake()
{
InitializeComponents();
InitializeConditions();
InitializeBehaviors();
}
private void InitializeComponents()
{
if (movementController == null)
{
movementController = GetComponent<AIMovementController>();
}
if (perceptionController == null)
{
perceptionController = GetComponent<AIPerceptionController>();
}
if (stateController == null)
{
stateController = GetComponent<AIStateController>();
}
}
private void InitializeConditions()
{
// 注册条件评估器
RegisterCondition("HealthRatio", EvaluateHealthRatio);
RegisterCondition("ThreatLevel", EvaluateThreatLevel);
RegisterCondition("DistanceToTarget", EvaluateDistanceToTarget);
RegisterCondition("AmmoRatio", EvaluateAmmoRatio);
RegisterCondition("HasLineOfSight", EvaluateHasLineOfSight);
RegisterCondition("IsUnderAttack", EvaluateIsUnderAttack);
RegisterCondition("TargetVisible", EvaluateTargetVisible);
RegisterCondition("GroupSize", EvaluateGroupSize);
RegisterCondition("CoverAvailable", EvaluateCoverAvailable);
RegisterCondition("ObjectivePriority", EvaluateObjectivePriority);
}
private void InitializeBehaviors()
{
// 注册行为执行器
RegisterBehavior("Attack", ExecuteAttackBehavior);
RegisterBehavior("TakeCover", ExecuteTakeCoverBehavior);
RegisterBehavior("Retreat", ExecuteRetreatBehavior);
RegisterBehavior("Patrol", ExecutePatrolBehavior);
RegisterBehavior("Investigate", ExecuteInvestigateBehavior);
RegisterBehavior("Search", ExecuteSearchBehavior);
RegisterBehavior("Heal", ExecuteHealBehavior);
RegisterBehavior("Reload", ExecuteReloadBehavior);
RegisterBehavior("CallForHelp", ExecuteCallForHelpBehavior);
RegisterBehavior("Flank", ExecuteFlankBehavior);
}
private void Update()
{
UpdateDecisionMaking();
}
private void UpdateDecisionMaking()
{
timeSinceLastDecision += Time.deltaTime;
decisionTimer += Time.deltaTime;
// 定期更新决策
if (decisionTimer >= config.decisionUpdateInterval)
{
UpdateConditionValues();
MakeDecision();
decisionTimer = 0f;
}
// 执行当前决策
ExecuteCurrentDecision();
}
private void UpdateConditionValues()
{
// 更新所有条件值
foreach (var evaluator in conditionEvaluators)
{
try
{
conditionValues[evaluator.Key] = evaluator.Value();
}
catch (Exception e)
{
Debug.LogError($"条件评估失败: {evaluator.Key}, 错误: {e.Message}");
conditionValues[evaluator.Key] = 0f;
}
}
}
private void MakeDecision()
{
if (isDecisionMaking)
{
// 防止重复决策
return;
}
isDecisionMaking = true;
// 记录决策开始时间
float startTime = Time.time;
// 计算每个行为的权重
Dictionary<string, float> behaviorScores = new Dictionary<string, float>();
float totalScore = 0f;
foreach (BehaviorWeight behaviorWeight in behaviorWeights)
{
float score = CalculateBehaviorScore(behaviorWeight);
behaviorScores[behaviorWeight.behaviorName] = score;
totalScore += score;
}
// 选择得分最高的行为
string bestBehavior = null;
float bestScore = -1f;
foreach (var score in behaviorScores)
{
if (score.Value > bestScore)
{
bestScore = score.Value;
bestBehavior = score.Key;
}
}
// 计算决策置信度
float confidence = totalScore > 0 ? bestScore / totalScore : 0f;
// 应用决策
if (bestBehavior != null && bestScore > 0)
{
ApplyDecision(bestBehavior, confidence);
}
// 检查决策时间
float decisionTime = Time.time - startTime;
if (decisionTime > config.maxDecisionTime)
{
Debug.LogWarning($"决策时间过长: {decisionTime:F2}秒");
}
isDecisionMaking = false;
}
private float CalculateBehaviorScore(BehaviorWeight behaviorWeight)
{
float score = behaviorWeight.baseWeight;
// 应用曲线调整
float timeFactor = Mathf.Clamp01(timeSinceLastDecision / 10f);
score *= behaviorWeight.weightCurve.Evaluate(timeFactor);
// 应用条件修饰符
foreach (ConditionModifier modifier in behaviorWeight.conditionModifiers)
{
if (conditionValues.ContainsKey(modifier.conditionName))
{
float conditionValue = conditionValues[modifier.conditionName];
bool conditionMet = EvaluateCondition(conditionValue, modifier);
if (conditionMet)
{
score *= modifier.modifierValue;
}
}
}
return Mathf.Max(0, score);
}
private bool EvaluateCondition(float value, ConditionModifier modifier)
{
switch (modifier.comparison)
{
case ComparisonOperator.GreaterThan:
return value > modifier.threshold;
case ComparisonOperator.LessThan:
return value < modifier.threshold;
case ComparisonOperator.EqualTo:
return Mathf.Approximately(value, modifier.threshold);
case ComparisonOperator.NotEqualTo:
return !Mathf.Approximately(value, modifier.threshold);
default:
return false;
}
}
private void ApplyDecision(string behavior, float confidence)
{
// 避免频繁切换相同决策
if (currentDecision == behavior && confidence < decisionConfidence * 1.1f)
{
return;
}
// 记录决策历史
decisionHistory.Add(new DecisionHistory(
behavior,
confidence,
new Dictionary<string, float>(conditionValues)
));
// 限制历史记录数量
if (decisionHistory.Count > 50)
{
decisionHistory.RemoveAt(0);
}
// 更新当前决策
string previousDecision = currentDecision;
currentDecision = behavior;
decisionConfidence = confidence;
timeSinceLastDecision = 0f;
// 触发决策变化事件
OnDecisionChanged(previousDecision, behavior, confidence);
if (config.enableDebugLogging)
{
Debug.Log($"决策改变: {previousDecision} -> {behavior} (置信度: {confidence:F2})");
}
}
private void ExecuteCurrentDecision()
{
if (string.IsNullOrEmpty(currentDecision))
{
return;
}
if (behaviorExecutors.ContainsKey(currentDecision))
{
try
{
behaviorExecutors[currentDecision]();
}
catch (Exception e)
{
Debug.LogError($"行为执行失败: {currentDecision}, 错误: {e.Message}");
}
}
}
#region 条件评估方法
private float EvaluateHealthRatio()
{
// 获取健康值比例 (0-1)
// 这里需要根据实际游戏系统实现
HealthComponent health = GetComponent<HealthComponent>();
if (health != null)
{
return health.CurrentHealth / health.MaxHealth;
}
return 1.0f;
}
private float EvaluateThreatLevel()
{
// 评估威胁等级 (0-1)
if (perceptionController == null)
{
return 0f;
}
GameObject primaryThreat = perceptionController.GetPrimaryThreat();
if (primaryThreat == null)
{
return 0f;
}
// 基于距离和威胁类型的简单评估
float distance = Vector3.Distance(transform.position, primaryThreat.transform.position);
float distanceFactor = Mathf.Clamp01(1 - (distance / 50f));
// 这里可以添加更复杂的威胁评估逻辑
return distanceFactor;
}
private float EvaluateDistanceToTarget()
{
// 评估到目标的距离 (0-1, 1表示非常近)
if (stateController == null || stateController.CurrentTarget == null)
{
return 0f;
}
float distance = Vector3.Distance(transform.position, stateController.CurrentTarget.transform.position);
float maxDistance = 100f;
return Mathf.Clamp01(1 - (distance / maxDistance));
}
private float EvaluateAmmoRatio()
{
// 评估弹药比例 (0-1)
// 这里需要根据实际武器系统实现
WeaponController weapon = GetComponent<WeaponController>();
if (weapon != null)
{
return weapon.GetAmmoRatio();
}
return 1.0f;
}
private float EvaluateHasLineOfSight()
{
// 是否有视线 (0或1)
if (stateController == null || stateController.CurrentTarget == null)
{
return 0f;
}
Vector3 direction = stateController.CurrentTarget.transform.position - transform.position;
RaycastHit hit;
if (Physics.Raycast(
transform.position,
direction.normalized,
out hit,
direction.magnitude,
LayerMask.GetMask("Obstacle", "Default"),
QueryTriggerInteraction.Ignore
))
{
return hit.collider.gameObject == stateController.CurrentTarget ? 1f : 0f;
}
return 1f;
}
private float EvaluateIsUnderAttack()
{
// 是否正在被攻击 (0或1)
DamageReceiver damageReceiver = GetComponent<DamageReceiver>();
if (damageReceiver != null)
{
return damageReceiver.IsUnderAttack() ? 1f : 0f;
}
return 0f;
}
private float EvaluateTargetVisible()
{
// 目标是否可见 (0或1)
if (perceptionController == null)
{
return 0f;
}
return perceptionController.IsTargetVisible() ? 1f : 0f;
}
private float EvaluateGroupSize()
{
// 评估群体大小 (0-1)
// 这里需要根据实际群体系统实现
AIGroupManager groupManager = AIGroupManager.Instance;
if (groupManager != null)
{
AIGroup group = groupManager.GetGroupForMember(gameObject);
if (group != null)
{
int memberCount = group.GetMemberCount();
return Mathf.Clamp01(memberCount / 10f); // 假设最大10人小组
}
}
return 0f;
}
private float EvaluateCoverAvailable()
{
// 评估是否有掩护可用 (0或1)
CoverSystem coverSystem = GetComponent<CoverSystem>();
if (coverSystem != null)
{
return coverSystem.HasAvailableCover() ? 1f : 0f;
}
return 0f;
}
private float EvaluateObjectivePriority()
{
// 评估目标优先级 (0-1)
if (stateController == null)
{
return 0f;
}
return stateController.GetCurrentObjectivePriority();
}
#endregion
#region 行为执行方法
private void ExecuteAttackBehavior()
{
if (stateController == null || stateController.CurrentTarget == null)
{
return;
}
// 移动到攻击位置
Vector3 attackPosition = CalculateAttackPosition();
movementController.MoveToPosition(attackPosition);
// 面向目标
Vector3 directionToTarget = stateController.CurrentTarget.transform.position - transform.position;
movementController.RotateTowardsDirection(directionToTarget);
// 尝试攻击
WeaponController weapon = GetComponent<WeaponController>();
if (weapon != null && weapon.CanFire())
{
weapon.FireAtTarget(stateController.CurrentTarget);
}
}
private void ExecuteTakeCoverBehavior()
{
CoverSystem coverSystem = GetComponent<CoverSystem>();
if (coverSystem == null)
{
return;
}
GameObject bestCover = coverSystem.FindBestCover();
if (bestCover != null)
{
movementController.MoveToPosition(bestCover.transform.position);
coverSystem.TakeCover(bestCover);
}
}
private void ExecuteRetreatBehavior()
{
if (stateController == null || stateController.CurrentTarget == null)
{
return;
}
// 计算撤退方向(远离目标)
Vector3 retreatDirection = transform.position - stateController.CurrentTarget.transform.position;
retreatDirection.y = 0;
retreatDirection.Normalize();
// 计算撤退位置
Vector3 retreatPosition = transform.position + retreatDirection * 20f;
movementController.MoveToPosition(retreatPosition);
}
private void ExecutePatrolBehavior()
{
PatrolSystem patrolSystem = GetComponent<PatrolSystem>();
if (patrolSystem != null)
{
patrolSystem.Patrol();
}
else
{
// 简单的巡逻行为
ExecuteDefaultPatrol();
}
}
private void ExecuteDefaultPatrol()
{
// 实现简单的巡逻逻辑
if (movementController.CurrentSpeed < 0.1f)
{
// 随机选择新的巡逻点
Vector3 randomDirection = new Vector3(
Random.Range(-1f, 1f),
0,
Random.Range(-1f, 1f)
).normalized;
Vector3 patrolPoint = transform.position + randomDirection * 10f;
movementController.MoveToPosition(patrolPoint, false);
}
}
private void ExecuteInvestigateBehavior()
{
if (stateController == null)
{
return;
}
Vector3 investigationPoint = stateController.GetInvestigationPoint();
if (investigationPoint != Vector3.zero)
{
movementController.MoveToPosition(investigationPoint);
}
}
private void ExecuteSearchBehavior()
{
SearchSystem searchSystem = GetComponent<SearchSystem>();
if (searchSystem != null)
{
searchSystem.SearchArea();
}
}
private void ExecuteHealBehavior()
{
// 寻找治疗物品或安全区域
GameObject healingItem = FindClosestHealingItem();
if (healingItem != null)
{
movementController.MoveToPosition(healingItem.transform.position);
}
else
{
// 撤退到安全区域
ExecuteRetreatBehavior();
}
}
private void ExecuteReloadBehavior()
{
WeaponController weapon = GetComponent<WeaponController>();
if (weapon != null && weapon.NeedsReload())
{
weapon.Reload();
// 寻找掩护
ExecuteTakeCoverBehavior();
}
}
private void ExecuteCallForHelpBehavior()
{
AIGroupManager groupManager = AIGroupManager.Instance;
if (groupManager != null)
{
groupManager.RequestBackup(gameObject, transform.position);
}
}
private void ExecuteFlankBehavior()
{
if (stateController == null || stateController.CurrentTarget == null)
{
return;
}
// 计算侧翼位置
Vector3 flankPosition = CalculateFlankPosition();
movementController.MoveToPosition(flankPosition);
}
#endregion
#region 辅助方法
private Vector3 CalculateAttackPosition()
{
if (stateController == null || stateController.CurrentTarget == null)
{
return transform.position;
}
Vector3 targetPosition = stateController.CurrentTarget.transform.position;
Vector3 directionToTarget = targetPosition - transform.position;
float idealDistance = 15f; // 理想攻击距离
// 计算理想攻击位置
if (directionToTarget.magnitude > idealDistance * 1.5f)
{
// 太远,靠近目标
return targetPosition - directionToTarget.normalized * idealDistance;
}
else if (directionToTarget.magnitude < idealDistance * 0.5f)
{
// 太近,后退
return transform.position - directionToTarget.normalized * idealDistance;
}
else
{
// 寻找更好的攻击角度
Vector3 rightFlank = Vector3.Cross(directionToTarget, Vector3.up).normalized;
return targetPosition + rightFlank * 5f;
}
}
private Vector3 CalculateFlankPosition()
{
if (stateController == null || stateController.CurrentTarget == null)
{
return transform.position;
}
Vector3 targetPosition = stateController.CurrentTarget.transform.position;
Vector3 directionToTarget = (targetPosition - transform.position).normalized;
// 计算侧翼方向(垂直于视线方向)
Vector3 flankDirection = Vector3.Cross(directionToTarget, Vector3.up).normalized;
// 随机选择左侧或右侧
if (Random.value > 0.5f)
{
flankDirection = -flankDirection;
}
// 计算侧翼位置
return targetPosition + flankDirection * 20f;
}
private GameObject FindClosestHealingItem()
{
// 在实际项目中,这里会查询游戏世界的物品系统
GameObject[] healthPacks = GameObject.FindGameObjectsWithTag("HealthPack");
GameObject closest = null;
float closestDistance = float.MaxValue;
foreach (GameObject healthPack in healthPacks)
{
float distance = Vector3.Distance(transform.position, healthPack.transform.position);
if (distance < closestDistance && distance < 50f) // 最大搜索距离
{
closestDistance = distance;
closest = healthPack;
}
}
return closest;
}
#endregion
#region 公共接口
public void RegisterCondition(string conditionName, Func<float> evaluator)
{
conditionEvaluators[conditionName] = evaluator;
conditionValues[conditionName] = 0f;
}
public void RegisterBehavior(string behaviorName, Action executor)
{
behaviorExecutors[behaviorName] = executor;
}
public void ForceDecision(string behavior, float confidence = 1.0f)
{
ApplyDecision(behavior, confidence);
}
public string GetCurrentDecision()
{
return currentDecision;
}
public float GetDecisionConfidence()
{
return decisionConfidence;
}
public Dictionary<string, float> GetConditionValues()
{
return new Dictionary<string, float>(conditionValues);
}
public List<DecisionHistory> GetDecisionHistory(int count = 10)
{
if (decisionHistory.Count <= count)
{
return new List<DecisionHistory>(decisionHistory);
}
return decisionHistory.GetRange(decisionHistory.Count - count, count);
}
public void ClearDecisionHistory()
{
decisionHistory.Clear();
}
#endregion
#region 事件
public event Action<string, string, float> OnDecisionChanged = delegate { };
#endregion
private void OnDrawGizmos()
{
if (!config.enableGizmos || !Application.isPlaying)
{
return;
}
// 绘制当前决策
#if UNITY_EDITOR
UnityEditor.Handles.Label(
transform.position + Vector3.up * 3f,
$"决策: {currentDecision}\n置信度: {decisionConfidence:F2}"
);
#endif
// 绘制攻击位置(如果当前决策是攻击)
if (currentDecision == "Attack" && stateController != null && stateController.CurrentTarget != null)
{
Vector3 attackPosition = CalculateAttackPosition();
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(attackPosition, 1f);
Gizmos.DrawLine(transform.position, attackPosition);
}
}
}
2.1.3 战略规划层的实现机制
战略规划层处理更高层次的AI行为,包括长期目标设定、资源管理、团队协调和战术制定。这一层使AI能够表现出更复杂、更智能的行为,特别适用于策略游戏、团队射击游戏和大型多人在线游戏。
在商业项目中,战略规划层的实现需要考虑:
- 长期目标的优先级管理
- 资源分配和经济效益分析
- 团队角色分配和协作
- 动态战术调整
- 风险评估和管理
下面是战略规划层的基础实现:
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
public class AIStrategicController : MonoBehaviour
{
[System.Serializable]
public class StrategicObjective
{
public string objectiveId;
public string objectiveName;
public ObjectiveType objectiveType;
public float priority;
public float basePriority;
public Vector3 targetPosition;
public GameObject targetObject;
public bool isActive;
public float timeAssigned;
public float timeCompleted;
public List<string> requiredResources;
public Dictionary<string, float> successFactors = new Dictionary<string, float>();
public StrategicObjective(
string id,
string name,
ObjectiveType type,
float basePriority
)
{
objectiveId = id;
objectiveName = name;
objectiveType = type;
this.basePriority = basePriority;
priority = basePriority;
isActive = false;
timeAssigned = 0f;
timeCompleted = 0f;
requiredResources = new List<string>();
}
public float GetAge()
{
if (!isActive)
{
return 0f;
}
return Time.time - timeAssigned;
}
public void UpdatePriority(float modifier)
{
priority = basePriority * modifier;
priority = Mathf.Max(0, priority);
}
}
[System.Serializable]
public class ResourceAllocation
{
public string resourceType;
public float currentAmount;
public float maxAmount;
public float regenerationRate;
public float lastUpdateTime;
public ResourceAllocation(string type, float max, float regeneration)
{
resourceType = type;
maxAmount = max;
currentAmount = max;
regenerationRate = regeneration;
lastUpdateTime = Time.time;
}
public void UpdateResource()
{
float timePassed = Time.time - lastUpdateTime;
currentAmount = Mathf.Min(
maxAmount,
currentAmount + regenerationRate * timePassed
);
lastUpdateTime = Time.time;
}
public bool Consume(float amount)
{
if (currentAmount >= amount)
{
currentAmount -= amount;
return true;
}
return false;
}
}
public enum ObjectiveType
{
Offensive,
Defensive,
Support,
Resource,
Reconnaissance,
Survival,
Strategic
}
[Header("战略配置")]
[SerializeField]
private float strategyUpdateInterval = 1.0f;
[SerializeField]
private int maxActiveObjectives = 3;
[SerializeField]
private float objectiveReevaluationTime = 5.0f;
[Header("资源管理")]
[SerializeField]
private List<ResourceAllocation> resources = new List<ResourceAllocation>();
[Header("目标管理")]
[SerializeField]
private List<StrategicObjective> allObjectives = new List<StrategicObjective>();
[SerializeField]
private List<StrategicObjective> activeObjectives = new List<StrategicObjective>();
[SerializeField]
private List<StrategicObjective> completedObjectives = new List<StrategicObjective>();
[Header("团队协调")]
[SerializeField]
private AIGroup assignedGroup;
[SerializeField]
private TeamRole assignedRole = TeamRole.Soldier;
private Dictionary<ObjectiveType, float> typeWeights = new Dictionary<ObjectiveType, float>();
private float strategyTimer;
private float reevaluationTimer;
public enum TeamRole
{
Leader,
Soldier,
Sniper,
Support,
Medic,
Engineer,
Scout
}
private void Awake()
{
InitializeTypeWeights();
InitializeResources();
InitializeDefaultObjectives();
}
private void InitializeTypeWeights()
{
// 设置目标类型权重
typeWeights[ObjectiveType.Offensive] = 1.2f;
typeWeights[ObjectiveType.Defensive] = 1.0f;
typeWeights[ObjectiveType.Support] = 0.8f;
typeWeights[ObjectiveType.Resource] = 0.7f;
typeWeights[ObjectiveType.Reconnaissance] = 0.6f;
typeWeights[ObjectiveType.Survival] = 1.5f;
typeWeights[ObjectiveType.Strategic] = 1.3f;
}
private void InitializeResources()
{
// 初始化资源
resources.Add(new ResourceAllocation("Health", 100f, 0.1f));
resources.Add(new ResourceAllocation("Ammo", 100f, 0f));
resources.Add(new ResourceAllocation("Energy", 100f, 1.0f));
resources.Add(new ResourceAllocation("Morale", 100f, 0.2f));
}
private void InitializeDefaultObjectives()
{
// 创建默认战略目标
AddObjective(new StrategicObjective(
"survive_01",
"生存",
ObjectiveType.Survival,
0.8f
));
AddObjective(new StrategicObjective(
"defend_base_01",
"保卫基地",
ObjectiveType.Defensive,
0.7f
));
AddObjective(new StrategicObjective(
"attack_enemy_01",
"攻击敌人",
ObjectiveType.Offensive,
0.6f
));
AddObjective(new StrategicObjective(
"gather_intel_01",
"收集情报",
ObjectiveType.Reconnaissance,
0.5f
));
}
private void Update()
{
UpdateResources();
UpdateStrategy();
UpdateActiveObjectives();
}
private void UpdateResources()
{
// 更新所有资源
foreach (ResourceAllocation resource in resources)
{
resource.UpdateResource();
}
}
private void UpdateStrategy()
{
strategyTimer += Time.deltaTime;
reevaluationTimer += Time.deltaTime;
// 定期更新战略
if (strategyTimer >= strategyUpdateInterval)
{
ReevaluateObjectives();
strategyTimer = 0f;
}
// 定期重新评估目标优先级
if (reevaluationTimer >= objectiveReevaluationTime)
{
UpdateObjectivePriorities();
reevaluationTimer = 0f;
}
}
private void ReevaluateObjectives()
{
// 更新当前环境评估
UpdateEnvironmentalAssessment();
// 计算每个目标的当前优先级
foreach (StrategicObjective objective in allObjectives)
{
CalculateObjectivePriority(objective);
}
// 选择要激活的目标
SelectActiveObjectives();
}
private void UpdateEnvironmentalAssessment()
{
// 评估当前环境状况
// 在实际项目中,这里会集成感知系统和游戏状态信息
float threatLevel = AssessThreatLevel();
float resourceStatus = AssessResourceStatus();
float teamStatus = AssessTeamStatus();
float gameProgress = AssessGameProgress();
// 更新类型权重(根据环境动态调整)
UpdateDynamicTypeWeights(threatLevel, resourceStatus, teamStatus, gameProgress);
}
private float AssessThreatLevel()
{
// 评估威胁等级 (0-1)
AIPerceptionController perception = GetComponent<AIPerceptionController>();
if (perception != null)
{
return perception.GetThreatLevel();
}
return 0.5f;
}
private float AssessResourceStatus()
{
// 评估资源状态 (0-1, 1表示资源充足)
float totalResourceRatio = 0f;
foreach (ResourceAllocation resource in resources)
{
totalResourceRatio += resource.currentAmount / resource.maxAmount;
}
return totalResourceRatio / resources.Count;
}
private float AssessTeamStatus()
{
// 评估团队状态 (0-1)
if (assignedGroup == null)
{
return 1.0f; // 没有团队,自主行动
}
return assignedGroup.GetGroupEffectiveness();
}
private float AssessGameProgress()
{
// 评估游戏进度 (0-1)
// 这里需要根据实际游戏系统实现
return 0.5f;
}
private void UpdateDynamicTypeWeights(float threatLevel, float resourceStatus, float teamStatus, float gameProgress)
{
// 根据环境动态调整目标类型权重
// 威胁高时增加防御和生存权重
if (threatLevel > 0.7f)
{
typeWeights[ObjectiveType.Defensive] = 1.5f;
typeWeights[ObjectiveType.Survival] = 2.0f;
}
else
{
typeWeights[ObjectiveType.Defensive] = 1.0f;
typeWeights[ObjectiveType.Survival] = 1.5f;
}
// 资源不足时增加资源收集权重
if (resourceStatus < 0.3f)
{
typeWeights[ObjectiveType.Resource] = 1.2f;
}
else
{
typeWeights[ObjectiveType.Resource] = 0.7f;
}
// 游戏后期增加战略目标权重
if (gameProgress > 0.7f)
{
typeWeights[ObjectiveType.Strategic] = 1.8f;
}
}
private void CalculateObjectivePriority(StrategicObjective objective)
{
float basePriority = objective.basePriority;
float typeWeight = typeWeights.ContainsKey(objective.objectiveType)
? typeWeights[objective.objectiveType]
: 1.0f;
// 计算时间衰减
float ageFactor = CalculateAgeFactor(objective);
// 计算资源可用性
float resourceFactor = CalculateResourceFactor(objective);
// 计算角色适配度
float roleFactor = CalculateRoleFactor(objective);
// 计算团队需求
float teamFactor = CalculateTeamFactor(objective);
// 组合所有因素
float finalPriority = basePriority * typeWeight * ageFactor * resourceFactor * roleFactor * teamFactor;
objective.UpdatePriority(finalPriority / basePriority);
}
private float CalculateAgeFactor(StrategicObjective objective)
{
// 目标年龄影响因子(新鲜目标优先级更高)
float age = objective.GetAge();
float maxAge = 300f; // 5分钟
return Mathf.Clamp01(1.0f - (age / maxAge));
}
private float CalculateResourceFactor(StrategicObjective objective)
{
// 检查是否有足够资源执行目标
if (objective.requiredResources.Count == 0)
{
return 1.0f;
}
int satisfiedRequirements = 0;
foreach (string resourceType in objective.requiredResources)
{
ResourceAllocation resource = resources.Find(r => r.resourceType == resourceType);
if (resource != null && resource.currentAmount > resource.maxAmount * 0.3f)
{
satisfiedRequirements++;
}
}
return (float)satisfiedRequirements / objective.requiredResources.Count;
}
private float CalculateRoleFactor(StrategicObjective objective)
{
// 计算目标与角色适配度
Dictionary<TeamRole, float> roleWeights = new Dictionary<TeamRole, float>();
// 设置不同角色对不同类型目标的适配权重
switch (assignedRole)
{
case TeamRole.Leader:
roleWeights[ObjectiveType.Strategic] = 1.5f;
roleWeights[ObjectiveType.Offensive] = 1.2f;
roleWeights[ObjectiveType.Defensive] = 1.0f;
break;
case TeamRole.Soldier:
roleWeights[ObjectiveType.Offensive] = 1.3f;
roleWeights[ObjectiveType.Defensive] = 1.1f;
break;
case TeamRole.Sniper:
roleWeights[ObjectiveType.Reconnaissance] = 1.4f;
roleWeights[ObjectiveType.Offensive] = 1.2f;
break;
case TeamRole.Support:
roleWeights[ObjectiveType.Support] = 1.5f;
roleWeights[ObjectiveType.Resource] = 1.2f;
break;
case TeamRole.Medic:
roleWeights[ObjectiveType.Support] = 1.6f;
roleWeights[ObjectiveType.Survival] = 1.3f;
break;
case TeamRole.Engineer:
roleWeights[ObjectiveType.Resource] = 1.4f;
roleWeights[ObjectiveType.Defensive] = 1.2f;
break;
case TeamRole.Scout:
roleWeights[ObjectiveType.Reconnaissance] = 1.6f;
break;
default:
return 1.0f;
}
if (roleWeights.ContainsKey(objective.objectiveType))
{
return roleWeights[objective.objectiveType];
}
return 0.8f; // 默认权重
}
private float CalculateTeamFactor(StrategicObjective objective)
{
if (assignedGroup == null)
{
return 1.0f;
}
// 检查团队是否需要执行此目标
float teamNeed = assignedGroup.GetObjectiveNeed(objective.objectiveId);
// 检查是否有其他成员正在执行此目标
bool isBeingExecuted = assignedGroup.IsObjectiveBeingExecuted(objective.objectiveId);
if (isBeingExecuted)
{
return teamNeed * 0.5f; // 减少重复执行
}
return teamNeed;
}
private void SelectActiveObjectives()
{
// 按优先级排序所有目标
List<StrategicObjective> sortedObjectives = allObjectives
.Where(obj => !obj.isActive && !completedObjectives.Contains(obj))
.OrderByDescending(obj => obj.priority)
.ToList();
// 停用低优先级目标
for (int i = activeObjectives.Count - 1; i >= 0; i--)
{
StrategicObjective activeObj = activeObjectives[i];
bool shouldDeactivate = false;
// 检查目标是否已完成
if (IsObjectiveCompleted(activeObj))
{
CompleteObjective(activeObj.objectiveId);
shouldDeactivate = true;
}
// 检查目标是否已过时
else if (activeObj.GetAge() > 600f) // 10分钟
{
shouldDeactivate = true;
}
// 检查是否有更高优先级目标需要激活
else if (sortedObjectives.Count > 0 &&
sortedObjectives[0].priority > activeObj.priority * 1.2f)
{
shouldDeactivate = true;
}
if (shouldDeactivate)
{
DeactivateObjective(activeObj.objectiveId);
}
}
// 激活新目标
while (activeObjectives.Count < maxActiveObjectives && sortedObjectives.Count > 0)
{
StrategicObjective nextObjective = sortedObjectives[0];
ActivateObjective(nextObjective.objectiveId);
sortedObjectives.RemoveAt(0);
}
}
private void UpdateActiveObjectives()
{
// 更新激活目标的执行状态
foreach (StrategicObjective objective in activeObjectives)
{
UpdateObjectiveExecution(objective);
}
}
private void UpdateObjectiveExecution(StrategicObjective objective)
{
// 根据目标类型执行相应的战略行为
switch (objective.objectiveType)
{
case ObjectiveType.Offensive:
ExecuteOffensiveObjective(objective);
break;
case ObjectiveType.Defensive:
ExecuteDefensiveObjective(objective);
break;
case ObjectiveType.Support:
ExecuteSupportObjective(objective);
break;
case ObjectiveType.Resource:
ExecuteResourceObjective(objective);
break;
case ObjectiveType.Reconnaissance:
ExecuteReconnaissanceObjective(objective);
break;
case ObjectiveType.Survival:
ExecuteSurvivalObjective(objective);
break;
case ObjectiveType.Strategic:
ExecuteStrategicObjective(objective);
break;
}
// 更新目标成功因素
UpdateSuccessFactors(objective);
}
#region 目标执行方法
private void ExecuteOffensiveObjective(StrategicObjective objective)
{
// 执行进攻目标
AIDecisionController decisionController = GetComponent<AIDecisionController>();
if (decisionController != null)
{
// 设置攻击行为
decisionController.ForceDecision("Attack", 0.8f);
}
// 更新目标位置(如果需要)
if (objective.targetObject != null)
{
objective.targetPosition = objective.targetObject.transform.position;
}
// 记录进攻进度
RecordObjectiveProgress(objective, "进攻执行中");
}
private void ExecuteDefensiveObjective(StrategicObjective objective)
{
// 执行防御目标
AIDecisionController decisionController = GetComponent<AIDecisionController>();
if (decisionController != null)
{
// 寻找并占据防御位置
decisionController.ForceDecision("TakeCover", 0.7f);
}
// 检查防御区域
if (objective.targetPosition != Vector3.zero)
{
float distanceToDefensePoint = Vector3.Distance(
transform.position,
objective.targetPosition
);
if (distanceToDefensePoint > 10f)
{
// 移动到防御点
AIMovementController movementController = GetComponent<AIMovementController>();
if (movementController != null)
{
movementController.MoveToPosition(objective.targetPosition);
}
}
}
RecordObjectiveProgress(objective, "防御执行中");
}
private void ExecuteSupportObjective(StrategicObjective objective)
{
// 执行支援目标
if (assignedGroup != null)
{
// 寻找需要支援的队友
GameObject allyInNeed = assignedGroup.FindAllyInNeed();
if (allyInNeed != null)
{
// 移动到队友位置
AIMovementController movementController = GetComponent<AIMovementController>();
if (movementController != null)
{
movementController.MoveToPosition(allyInNeed.transform.position);
}
// 提供支援
ProvideSupportToAlly(allyInNeed);
}
}
RecordObjectiveProgress(objective, "支援执行中");
}
private void ExecuteResourceObjective(StrategicObjective objective)
{
// 执行资源收集目标
if (objective.targetObject != null)
{
// 移动到资源位置
AIMovementController movementController = GetComponent<AIMovementController>();
if (movementController != null)
{
movementController.MoveToPosition(objective.targetObject.transform.position);
}
// 收集资源
float distance = Vector3.Distance(
transform.position,
objective.targetObject.transform.position
);
if (distance < 2f)
{
CollectResource(objective.targetObject);
}
}
RecordObjectiveProgress(objective, "资源收集中");
}
private void ExecuteReconnaissanceObjective(StrategicObjective objective)
{
// 执行侦察目标
AIDecisionController decisionController = GetComponent<AIDecisionController>();
if (decisionController != null)
{
decisionController.ForceDecision("Investigate", 0.6f);
}
// 探索未知区域
if (objective.targetPosition != Vector3.zero)
{
AIMovementController movementController = GetComponent<AIMovementController>();
if (movementController != null)
{
movementController.MoveToPosition(objective.targetPosition);
}
}
RecordObjectiveProgress(objective, "侦察执行中");
}
private void ExecuteSurvivalObjective(StrategicObjective objective)
{
// 执行生存目标
AIDecisionController decisionController = GetComponent<AIDecisionController>();
if (decisionController != null)
{
// 生存行为:治疗、躲避、撤退
float healthRatio = GetResourceAmount("Health") / 100f;
if (healthRatio < 0.3f)
{
decisionController.ForceDecision("Heal", 0.9f);
}
else
{
decisionController.ForceDecision("TakeCover", 0.8f);
}
}
RecordObjectiveProgress(objective, "生存模式");
}
private void ExecuteStrategicObjective(StrategicObjective objective)
{
// 执行战略目标
// 这通常是高层次的目标,需要多个步骤
RecordObjectiveProgress(objective, "战略执行中");
}
#endregion
#region 辅助方法
private void ProvideSupportToAlly(GameObject ally)
{
// 提供支援给队友
// 在实际项目中,这里会有具体的支援逻辑
Debug.Log($"正在支援队友: {ally.name}");
// 检查队友状态
HealthComponent allyHealth = ally.GetComponent<HealthComponent>();
if (allyHealth != null && allyHealth.CurrentHealth < allyHealth.MaxHealth * 0.5f)
{
// 队友生命值低,尝试治疗
Debug.Log("队友生命值低,提供医疗支援");
}
// 提供火力支援
WeaponController weapon = GetComponent<WeaponController>();
if (weapon != null)
{
// 瞄准队友附近的敌人
AIPerceptionController perception = ally.GetComponent<AIPerceptionController>();
if (perception != null)
{
GameObject primaryThreat = perception.GetPrimaryThreat();
if (primaryThreat != null)
{
weapon.FireAtTarget(primaryThreat);
}
}
}
}
private void CollectResource(GameObject resourceObject)
{
// 收集资源
ResourcePickup resourcePickup = resourceObject.GetComponent<ResourcePickup>();
if (resourcePickup != null)
{
resourcePickup.Collect(gameObject);
Debug.Log($"收集资源: {resourceObject.name}");
}
}
private void UpdateSuccessFactors(StrategicObjective objective)
{
// 更新目标成功因素
// 这些因素用于评估目标执行的成功程度
if (!objective.successFactors.ContainsKey("time_spent"))
{
objective.successFactors["time_spent"] = 0f;
}
objective.successFactors["time_spent"] += Time.deltaTime;
// 根据目标类型添加特定的成功因素
switch (objective.objectiveType)
{
case ObjectiveType.Offensive:
UpdateOffensiveSuccessFactors(objective);
break;
case ObjectiveType.Defensive:
UpdateDefensiveSuccessFactors(objective);
break;
}
}
private void UpdateOffensiveSuccessFactors(StrategicObjective objective)
{
// 更新进攻目标成功因素
if (objective.targetObject != null)
{
float distance = Vector3.Distance(
transform.position,
objective.targetObject.transform.position
);
if (!objective.successFactors.ContainsKey("distance_to_target"))
{
objective.successFactors["distance_to_target"] = distance;
}
else
{
objective.successFactors["distance_to_target"] = Mathf.Min(
objective.successFactors["distance_to_target"],
distance
);
}
}
}
private void UpdateDefensiveSuccessFactors(StrategicObjective objective)
{
// 更新防御目标成功因素
if (objective.targetPosition != Vector3.zero)
{
float distance = Vector3.Distance(transform.position, objective.targetPosition);
if (!objective.successFactors.ContainsKey("distance_to_defense_point"))
{
objective.successFactors["distance_to_defense_point"] = distance;
}
else
{
objective.successFactors["distance_to_defense_point"] = Mathf.Min(
objective.successFactors["distance_to_defense_point"],
distance
);
}
}
}
private void RecordObjectiveProgress(StrategicObjective objective, string status)
{
// 记录目标进度
// 在实际项目中,这里可能会更新UI或发送事件
objective.successFactors["last_status"] = Time.time;
}
private bool IsObjectiveCompleted(StrategicObjective objective)
{
// 检查目标是否已完成
// 根据目标类型有不同的完成条件
switch (objective.objectiveType)
{
case ObjectiveType.Offensive:
return IsOffensiveObjectiveCompleted(objective);
case ObjectiveType.Defensive:
return IsDefensiveObjectiveCompleted(objective);
case ObjectiveType.Resource:
return IsResourceObjectiveCompleted(objective);
case ObjectiveType.Reconnaissance:
return IsReconnaissanceObjectiveCompleted(objective);
default:
return false;
}
}
private bool IsOffensiveObjectiveCompleted(StrategicObjective objective)
{
// 进攻目标完成条件:目标被消灭或超出时间限制
if (objective.targetObject == null)
{
return true; // 目标已不存在
}
// 检查是否超出时间限制
float timeSpent = objective.successFactors.ContainsKey("time_spent")
? objective.successFactors["time_spent"]
: 0f;
if (timeSpent > 300f) // 5分钟
{
return true; // 超时
}
return false;
}
private bool IsDefensiveObjectiveCompleted(StrategicObjective objective)
{
// 防御目标完成条件:成功防御一定时间或威胁解除
float timeSpent = objective.successFactors.ContainsKey("time_spent")
? objective.successFactors["time_spent"]
: 0f;
if (timeSpent > 180f) // 3分钟
{
return true; // 成功防御足够时间
}
// 检查威胁等级
float threatLevel = AssessThreatLevel();
if (threatLevel < 0.2f)
{
return true; // 威胁解除
}
return false;
}
private bool IsResourceObjectiveCompleted(StrategicObjective objective)
{
// 资源目标完成条件:资源收集完成或资源不存在
if (objective.targetObject == null)
{
return true;
}
ResourcePickup resourcePickup = objective.targetObject.GetComponent<ResourcePickup>();
if (resourcePickup != null && resourcePickup.IsCollected())
{
return true;
}
return false;
}
private bool IsReconnaissanceObjectiveCompleted(StrategicObjective objective)
{
// 侦察目标完成条件:到达侦察点并停留足够时间
if (objective.targetPosition == Vector3.zero)
{
return true;
}
float distance = Vector3.Distance(transform.position, objective.targetPosition);
float timeSpent = objective.successFactors.ContainsKey("time_spent")
? objective.successFactors["time_spent"]
: 0f;
if (distance < 5f && timeSpent > 30f)
{
return true; // 到达侦察点并停留30秒
}
return false;
}
private void UpdateObjectivePriorities()
{
// 更新所有目标的优先级
foreach (StrategicObjective objective in allObjectives)
{
CalculateObjectivePriority(objective);
}
}
#endregion
#region 公共接口
public void AddObjective(StrategicObjective objective)
{
allObjectives.Add(objective);
}
public bool ActivateObjective(string objectiveId)
{
StrategicObjective objective = allObjectives.Find(obj => obj.objectiveId == objectiveId);
if (objective != null && !objective.isActive)
{
objective.isActive = true;
objective.timeAssigned = Time.time;
activeObjectives.Add(objective);
Debug.Log($"激活目标: {objective.objectiveName}");
// 触发目标激活事件
OnObjectiveActivated?.Invoke(objective);
return true;
}
return false;
}
public bool DeactivateObjective(string objectiveId)
{
StrategicObjective objective = activeObjectives.Find(obj => obj.objectiveId == objectiveId);
if (objective != null)
{
objective.isActive = false;
activeObjectives.Remove(objective);
Debug.Log($"停用目标: {objective.objectiveName}");
// 触发目标停用事件
OnObjectiveDeactivated?.Invoke(objective);
return true;
}
return false;
}
public bool CompleteObjective(string objectiveId)
{
StrategicObjective objective = activeObjectives.Find(obj => obj.objectiveId == objectiveId);
if (objective != null)
{
objective.isActive = false;
objective.timeCompleted = Time.time;
activeObjectives.Remove(objective);
completedObjectives.Add(objective);
Debug.Log($"完成目标: {objective.objectiveName}");
// 触发目标完成事件
OnObjectiveCompleted?.Invoke(objective);
return true;
}
return false;
}
public List<StrategicObjective> GetActiveObjectives()
{
return new List<StrategicObjective>(activeObjectives);
}
public StrategicObjective GetHighestPriorityObjective()
{
if (activeObjectives.Count == 0)
{
return null;
}
return activeObjectives.OrderByDescending(obj => obj.priority).First();
}
public float GetResourceAmount(string resourceType)
{
ResourceAllocation resource = resources.Find(r => r.resourceType == resourceType);
return resource != null ? resource.currentAmount : 0f;
}
public bool ConsumeResource(string resourceType, float amount)
{
ResourceAllocation resource = resources.Find(r => r.resourceType == resourceType);
return resource != null && resource.Consume(amount);
}
public void AssignToGroup(AIGroup group, TeamRole role)
{
assignedGroup = group;
assignedRole = role;
if (group != null)
{
group.RegisterMember(gameObject, role);
}
}
public void SetTeamRole(TeamRole role)
{
assignedRole = role;
}
#endregion
#region 事件
public event Action<StrategicObjective> OnObjectiveActivated = delegate { };
public event Action<StrategicObjective> OnObjectiveDeactivated = delegate { };
public event Action<StrategicObjective> OnObjectiveCompleted = delegate { };
#endregion
private void OnDrawGizmosSelected()
{
if (!Application.isPlaying)
{
return;
}
// 绘制激活目标
Gizmos.color = Color.yellow;
foreach (StrategicObjective objective in activeObjectives)
{
if (objective.targetPosition != Vector3.zero)
{
Gizmos.DrawWireSphere(objective.targetPosition, 1f);
Gizmos.DrawLine(transform.position, objective.targetPosition);
}
}
// 绘制最高优先级目标
StrategicObjective highestPriority = GetHighestPriorityObjective();
if (highestPriority != null && highestPriority.targetPosition != Vector3.zero)
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(highestPriority.targetPosition, 1.5f);
Gizmos.DrawLine(transform.position, highestPriority.targetPosition);
}
// 显示当前角色和目标信息
#if UNITY_EDITOR
string info = $"角色: {assignedRole}\n";
info += $"激活目标: {activeObjectives.Count}\n";
if (highestPriority != null)
{
info += $"最高优先级: {highestPriority.objectiveName}\n";
info += $"优先级: {highestPriority.priority:F2}";
}
UnityEditor.Handles.Label(
transform.position + Vector3.up * 2.5f,
info
);
#endif
}
}
2.1.4 AI架构支撑系统的完善
一个完整的AI架构除了核心的三层结构外,还需要支撑系统来确保AI的稳定运行和高效表现。这些支撑系统包括性能管理、调试工具、配置系统和集成接口。
下面是支撑系统的实现示例:
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Text;
public class AISupportSystem : MonoBehaviour
{
[System.Serializable]
public class PerformanceSettings
{
public bool enablePerformanceMonitoring = true;
public float performanceUpdateInterval = 1.0f;
public int maxFrameTimeMs = 16; // 60 FPS
public bool enableAdaptiveUpdate = true;
public float minUpdateInterval = 0.05f;
public float maxUpdateInterval = 0.5f;
}
[System.Serializable]
public class DebugSettings
{
public bool enableDebugOverlay = false;
public bool logAIEvents = false;
public bool logPerformanceWarnings = true;
public bool enableVisualDebugging = true;
public Color debugTextColor = Color.white;
public int maxLogEntries = 100;
}
[System.Serializable]
public class AIConfig
{
public string aiName = "DefaultAI";
public int aiVersion = 1;
public string behaviorProfile = "Aggressive";
public Dictionary<string, string> customParameters = new Dictionary<string, string>();
}
[Header("性能设置")]
[SerializeField]
private PerformanceSettings performanceSettings = new PerformanceSettings();
[Header("调试设置")]
[SerializeField]
private DebugSettings debugSettings = new DebugSettings();
[Header("AI配置")]
[SerializeField]
private AIConfig aiConfig = new AIConfig();
[Header("组件引用")]
[SerializeField]
private AIMovementController movementController;
[SerializeField]
private AIDecisionController decisionController;
[SerializeField]
private AIStrategicController strategicController;
[Header("性能统计")]
[SerializeField]
private float averageFrameTime;
[SerializeField]
private float maxFrameTime;
[SerializeField]
private float minFrameTime;
[SerializeField]
private int frameCount;
[SerializeField]
private float performanceTimer;
[Header("调试信息")]
[SerializeField]
private List<DebugLogEntry> debugLog = new List<DebugLogEntry>();
[SerializeField]
private StringBuilder debugOverlayText = new StringBuilder();
private Dictionary<string, float> componentUpdateTimes = new Dictionary<string, float>();
private Dictionary<string, int> componentCallCounts = new Dictionary<string, int>();
private float adaptiveUpdateInterval;
private bool isInitialized;
[System.Serializable]
public class DebugLogEntry
{
public string message;
public LogType logType;
public float timestamp;
public string source;
public DebugLogEntry(string message, LogType logType, string source)
{
this.message = message;
this.logType = logType;
this.timestamp = Time.time;
this.source = source;
}
}
public enum LogType
{
Info,
Warning,
Error,
Performance
}
private void Awake()
{
InitializeSupportSystem();
}
private void InitializeSupportSystem()
{
// 获取组件引用
if (movementController == null)
{
movementController = GetComponent<AIMovementController>();
}
if (decisionController == null)
{
decisionController = GetComponent<AIDecisionController>();
}
if (strategicController == null)
{
strategicController = GetComponent<AIStrategicController>();
}
// 初始化自适应更新间隔
adaptiveUpdateInterval = performanceSettings.minUpdateInterval;
// 初始化性能监控
InitializePerformanceMonitoring();
// 初始化调试系统
InitializeDebugSystem();
isInitialized = true;
LogInfo("AI支撑系统初始化完成", "AISupportSystem");
}
private void InitializePerformanceMonitoring()
{
averageFrameTime = 0f;
maxFrameTime = 0f;
minFrameTime = float.MaxValue;
frameCount = 0;
performanceTimer = 0f;
// 初始化组件性能追踪
componentUpdateTimes["Movement"] = 0f;
componentUpdateTimes["Decision"] = 0f;
componentUpdateTimes["Strategic"] = 0f;
componentCallCounts["Movement"] = 0;
componentCallCounts["Decision"] = 0;
componentCallCounts["Strategic"] = 0;
}
private void InitializeDebugSystem()
{
debugLog.Clear();
debugOverlayText.Clear();
// 注册调试命令
RegisterDebugCommands();
}
private void Update()
{
if (!isInitialized)
{
return;
}
UpdatePerformanceMonitoring();
UpdateAdaptiveSystem();
UpdateDebugOverlay();
}
private void UpdatePerformanceMonitoring()
{
if (!performanceSettings.enablePerformanceMonitoring)
{
return;
}
// 测量帧时间
float frameTime = Time.deltaTime * 1000f; // 转换为毫秒
UpdateFrameTimeStatistics(frameTime);
// 更新性能计时器
performanceTimer += Time.deltaTime;
if (performanceTimer >= performanceSettings.performanceUpdateInterval)
{
AnalyzePerformance();
performanceTimer = 0f;
}
}
private void UpdateFrameTimeStatistics(float frameTime)
{
// 更新帧时间统计
frameCount++;
// 移动平均
averageFrameTime = (averageFrameTime * (frameCount - 1) + frameTime) / frameCount;
// 更新最大/最小帧时间
if (frameTime > maxFrameTime)
{
maxFrameTime = frameTime;
}
if (frameTime < minFrameTime)
{
minFrameTime = frameTime;
}
// 检查性能警告
if (frameTime > performanceSettings.maxFrameTimeMs && debugSettings.logPerformanceWarnings)
{
LogWarning($"帧时间超标: {frameTime:F1}ms (限制: {performanceSettings.maxFrameTimeMs}ms)",
"Performance");
}
}
private void AnalyzePerformance()
{
// 分析性能数据并调整系统
if (performanceSettings.enableAdaptiveUpdate)
{
AdjustUpdateIntervals();
}
// 记录性能日志
if (debugSettings.logPerformanceWarnings && averageFrameTime > performanceSettings.maxFrameTimeMs * 0.8f)
{
LogPerformance($"性能警告: 平均帧时间 {averageFrameTime:F1}ms");
}
// 重置统计
frameCount = 0;
averageFrameTime = 0f;
maxFrameTime = 0f;
minFrameTime = float.MaxValue;
}
private void AdjustUpdateIntervals()
{
// 根据性能调整更新间隔
if (averageFrameTime > performanceSettings.maxFrameTimeMs * 0.9f)
{
// 性能紧张,增加更新间隔
adaptiveUpdateInterval = Mathf.Min(
adaptiveUpdateInterval * 1.2f,
performanceSettings.maxUpdateInterval
);
ApplyAdaptiveUpdates();
}
else if (averageFrameTime < performanceSettings.maxFrameTimeMs * 0.5f)
{
// 性能充足,减少更新间隔
adaptiveUpdateInterval = Mathf.Max(
adaptiveUpdateInterval * 0.9f,
performanceSettings.minUpdateInterval
);
ApplyAdaptiveUpdates();
}
}
private void ApplyAdaptiveUpdates()
{
// 应用自适应更新间隔到各个组件
if (decisionController != null)
{
// 这里需要决策控制器支持更新间隔调整
// decisionController.SetUpdateInterval(adaptiveUpdateInterval);
}
if (strategicController != null)
{
// strategicController.SetUpdateInterval(adaptiveUpdateInterval * 2f);
}
}
private void UpdateAdaptiveSystem()
{
// 更新自适应系统(LOD、剔除等)
UpdateLevelOfDetail();
UpdateCullingSystem();
}
private void UpdateLevelOfDetail()
{
// 根据距离调整AI细节层次
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player == null)
{
return;
}
float distanceToPlayer = Vector3.Distance(transform.position, player.transform.position);
float lodLevel = CalculateLODLevel(distanceToPlayer);
ApplyLODSettings(lodLevel);
}
private float CalculateLODLevel(float distance)
{
// 计算LOD级别 (0-1, 0表示最低细节)
if (distance < 10f)
{
return 1.0f; // 高细节
}
else if (distance < 30f)
{
return 0.7f; // 中等细节
}
else if (distance < 50f)
{
return 0.4f; // 低细节
}
else
{
return 0.1f; // 最低细节
}
}
private void ApplyLODSettings(float lodLevel)
{
// 应用LOD设置到各个组件
if (decisionController != null)
{
// 调整决策精度
// decisionController.SetDecisionPrecision(lodLevel);
}
if (movementController != null)
{
// 调整移动精度
// movementController.SetMovementPrecision(lodLevel);
}
}
private void UpdateCullingSystem()
{
// 更新剔除系统(远离玩家或不可见时禁用AI)
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player == null)
{
return;
}
Camera mainCamera = Camera.main;
if (mainCamera == null)
{
return;
}
// 计算视锥剔除
Vector3 viewportPoint = mainCamera.WorldToViewportPoint(transform.position);
bool isInView = viewportPoint.x >= 0 && viewportPoint.x <= 1 &&
viewportPoint.y >= 0 && viewportPoint.y <= 1 &&
viewportPoint.z > 0;
// 计算距离剔除
float distanceToPlayer = Vector3.Distance(transform.position, player.transform.position);
bool isInRange = distanceToPlayer < 100f; // 最大AI激活距离
// 应用剔除
bool shouldBeActive = isInView && isInRange;
SetAIActive(shouldBeActive);
}
private void UpdateDebugOverlay()
{
if (!debugSettings.enableDebugOverlay)
{
return;
}
// 更新调试叠加文本
debugOverlayText.Clear();
// 添加性能信息
debugOverlayText.AppendLine($"=== AI 调试信息 ===");
debugOverlayText.AppendLine($"名称: {aiConfig.aiName}");
debugOverlayText.AppendLine($"配置: {aiConfig.behaviorProfile}");
debugOverlayText.AppendLine($"帧时间: {averageFrameTime:F1}ms");
debugOverlayText.AppendLine($"更新间隔: {adaptiveUpdateInterval:F2}s");
// 添加组件状态
if (movementController != null)
{
debugOverlayText.AppendLine($"移动速度: {movementController.CurrentSpeed:F1}");
debugOverlayText.AppendLine($"是否接地: {movementController.IsGrounded}");
}
if (decisionController != null)
{
debugOverlayText.AppendLine($"当前决策: {decisionController.GetCurrentDecision()}");
debugOverlayText.AppendLine($"决策置信度: {decisionController.GetDecisionConfidence():F2}");
}
if (strategicController != null)
{
var activeObjectives = strategicController.GetActiveObjectives();
debugOverlayText.AppendLine($"激活目标: {activeObjectives.Count}");
foreach (var objective in activeObjectives)
{
debugOverlayText.AppendLine($" - {objective.objectiveName}: {objective.priority:F2}");
}
}
// 添加最近的日志
debugOverlayText.AppendLine($"=== 最近日志 ===");
int logCount = Mathf.Min(debugLog.Count, 5);
for (int i = debugLog.Count - logCount; i < debugLog.Count; i++)
{
if (i >= 0)
{
var logEntry = debugLog[i];
debugOverlayText.AppendLine($"[{logEntry.timestamp:F1}] {logEntry.message}");
}
}
}
private void RegisterDebugCommands()
{
// 注册调试命令
// 在实际项目中,这里会集成到游戏的控制台系统
DebugCommandSystem commandSystem = DebugCommandSystem.Instance;
if (commandSystem != null)
{
commandSystem.RegisterCommand("ai_status", "显示AI状态", ShowAIStatus);
commandSystem.RegisterCommand("ai_log", "显示AI日志", ShowAILog);
commandSystem.RegisterCommand("ai_performance", "显示AI性能", ShowAIPerformance);
commandSystem.RegisterCommand("ai_setprofile", "设置AI配置", SetAIProfile);
}
}
#region 调试命令处理
private string ShowAIStatus(string[] args)
{
StringBuilder status = new StringBuilder();
status.AppendLine($"AI状态报告 - {aiConfig.aiName}");
status.AppendLine($"位置: {transform.position}");
status.AppendLine($"旋转: {transform.rotation.eulerAngles}");
status.AppendLine($"激活: {gameObject.activeSelf}");
if (movementController != null)
{
status.AppendLine($"移动状态: {movementController.CurrentSpeed:F1} 单位/秒");
}
if (decisionController != null)
{
status.AppendLine($"决策: {decisionController.GetCurrentDecision()}");
}
return status.ToString();
}
private string ShowAILog(string[] args)
{
StringBuilder logOutput = new StringBuilder();
logOutput.AppendLine($"AI日志 - 最近 {debugLog.Count} 条");
foreach (var logEntry in debugLog)
{
string logTypeStr = logEntry.logType.ToString().PadRight(10);
logOutput.AppendLine($"[{logEntry.timestamp:F2}] [{logTypeStr}] {logEntry.message}");
}
return logOutput.ToString();
}
private string ShowAIPerformance(string[] args)
{
StringBuilder performance = new StringBuilder();
performance.AppendLine($"AI性能统计");
performance.AppendLine($"平均帧时间: {averageFrameTime:F1}ms");
performance.AppendLine($"最大帧时间: {maxFrameTime:F1}ms");
performance.AppendLine($"最小帧时间: {minFrameTime:F1}ms");
performance.AppendLine($"自适应更新间隔: {adaptiveUpdateInterval:F2}s");
performance.AppendLine($"组件调用次数:");
foreach (var pair in componentCallCounts)
{
performance.AppendLine($" {pair.Key}: {pair.Value}");
}
performance.AppendLine($"组件更新时间:");
foreach (var pair in componentUpdateTimes)
{
performance.AppendLine($" {pair.Key}: {pair.Value:F2}ms");
}
return performance.ToString();
}
private string SetAIProfile(string[] args)
{
if (args.Length < 2)
{
return "用法: ai_setprofile <配置名称>";
}
string profileName = args[1];
aiConfig.behaviorProfile = profileName;
// 应用新的配置
ApplyBehaviorProfile(profileName);
return $"AI配置已更改为: {profileName}";
}
#endregion
#region 公共接口
public void LogInfo(string message, string source = "AI")
{
AddDebugLog(message, LogType.Info, source);
if (debugSettings.logAIEvents)
{
Debug.Log($"[AI-Info] {source}: {message}");
}
}
public void LogWarning(string message, string source = "AI")
{
AddDebugLog(message, LogType.Warning, source);
if (debugSettings.logAIEvents)
{
Debug.LogWarning($"[AI-Warning] {source}: {message}");
}
}
public void LogError(string message, string source = "AI")
{
AddDebugLog(message, LogType.Error, source);
if (debugSettings.logAIEvents)
{
Debug.LogError($"[AI-Error] {source}: {message}");
}
}
public void LogPerformance(string message, string source = "AI")
{
AddDebugLog(message, LogType.Performance, source);
}
private void AddDebugLog(string message, LogType logType, string source)
{
DebugLogEntry logEntry = new DebugLogEntry(message, logType, source);
debugLog.Add(logEntry);
// 限制日志数量
if (debugLog.Count > debugSettings.maxLogEntries)
{
debugLog.RemoveAt(0);
}
}
public void RecordComponentTime(string componentName, float timeMs)
{
if (!componentUpdateTimes.ContainsKey(componentName))
{
componentUpdateTimes[componentName] = 0f;
componentCallCounts[componentName] = 0;
}
componentUpdateTimes[componentName] = (componentUpdateTimes[componentName] + timeMs) / 2; // 移动平均
componentCallCounts[componentName]++;
}
public void SetAIActive(bool active)
{
if (movementController != null)
{
movementController.SetMovementEnabled(active);
}
if (decisionController != null)
{
decisionController.enabled = active;
}
if (strategicController != null)
{
strategicController.enabled = active;
}
enabled = active;
LogInfo($"AI激活状态: {active}", "AISupportSystem");
}
public void SetBehaviorProfile(string profileName)
{
aiConfig.behaviorProfile = profileName;
ApplyBehaviorProfile(profileName);
}
private void ApplyBehaviorProfile(string profileName)
{
// 根据配置名称应用不同的行为设置
switch (profileName.ToLower())
{
case "aggressive":
ApplyAggressiveProfile();
break;
case "defensive":
ApplyDefensiveProfile();
break;
case "stealth":
ApplyStealthProfile();
break;
case "support":
ApplySupportProfile();
break;
default:
ApplyDefaultProfile();
break;
}
LogInfo($"应用行为配置: {profileName}", "AISupportSystem");
}
private void ApplyAggressiveProfile()
{
// 应用侵略性配置
if (decisionController != null)
{
// 设置更高的攻击权重
// decisionController.SetBehaviorWeight("Attack", 2.0f);
}
if (strategicController != null)
{
// 设置进攻性目标
strategicController.SetTeamRole(AIStrategicController.TeamRole.Soldier);
}
}
private void ApplyDefensiveProfile()
{
// 应用防御性配置
if (decisionController != null)
{
// 设置更高的防御权重
// decisionController.SetBehaviorWeight("TakeCover", 1.5f);
}
}
private void ApplyStealthProfile()
{
// 应用潜行配置
if (movementController != null)
{
// 降低移动速度
// movementController.SetMaxSpeed(3.0f);
}
}
private void ApplySupportProfile()
{
// 应用支援配置
if (strategicController != null)
{
strategicController.SetTeamRole(AIStrategicController.TeamRole.Support);
}
}
private void ApplyDefaultProfile()
{
// 应用默认配置
// 重置所有设置
}
public string GetDebugOverlayText()
{
return debugOverlayText.ToString();
}
public Dictionary<string, string> GetAIConfiguration()
{
Dictionary<string, string> config = new Dictionary<string, string>
{
["Name"] = aiConfig.aiName,
["Version"] = aiConfig.aiVersion.ToString(),
["Profile"] = aiConfig.behaviorProfile,
["Performance"] = $"{averageFrameTime:F1}ms"
};
foreach (var param in aiConfig.customParameters)
{
config[param.Key] = param.Value;
}
return config;
}
public void SetCustomParameter(string key, string value)
{
aiConfig.customParameters[key] = value;
}
public string GetCustomParameter(string key)
{
return aiConfig.customParameters.ContainsKey(key)
? aiConfig.customParameters[key]
: string.Empty;
}
#endregion
#region 调试绘制
private void OnDrawGizmos()
{
if (!debugSettings.enableVisualDebugging || !Application.isPlaying)
{
return;
}
// 绘制调试信息
DrawDebugGizmos();
}
private void DrawDebugGizmos()
{
// 绘制AI活动范围
Gizmos.color = new Color(0, 1, 0, 0.1f);
Gizmos.DrawWireSphere(transform.position, 100f);
// 绘制到目标的线(如果有)
if (decisionController != null)
{
var conditionValues = decisionController.GetConditionValues();
if (conditionValues.ContainsKey("DistanceToTarget") && conditionValues["DistanceToTarget"] > 0)
{
Gizmos.color = Color.red;
// 这里需要获取实际目标位置
// Gizmos.DrawLine(transform.position, targetPosition);
}
}
// 绘制LOD范围
Gizmos.color = new Color(1, 1, 0, 0.2f);
Gizmos.DrawWireSphere(transform.position, 10f); // 高细节
Gizmos.DrawWireSphere(transform.position, 30f); // 中细节
Gizmos.DrawWireSphere(transform.position, 50f); // 低细节
// 绘制调试文本
#if UNITY_EDITOR
if (debugSettings.enableDebugOverlay)
{
UnityEditor.Handles.color = debugSettings.debugTextColor;
UnityEditor.Handles.Label(
transform.position + Vector3.up * 3f,
GetDebugOverlayText()
);
}
#endif
}
#endregion
private void OnDestroy()
{
// 清理资源
CleanupSupportSystem();
}
private void CleanupSupportSystem()
{
// 注销调试命令
DebugCommandSystem commandSystem = DebugCommandSystem.Instance;
if (commandSystem != null)
{
commandSystem.UnregisterCommand("ai_status");
commandSystem.UnregisterCommand("ai_log");
commandSystem.UnregisterCommand("ai_performance");
commandSystem.UnregisterCommand("ai_setprofile");
}
LogInfo("AI支撑系统清理完成", "AISupportSystem");
}
}
2.2 FPS/TPS游戏AI架构的实践解析
2.2.1 FPS/TPS游戏中运动层的特殊需求
第一人称射击游戏(FPS)和第三人称射击游戏(TPS)对AI的运动控制有着特殊的要求。这些游戏中的AI不仅需要基本的移动能力,还需要表现出符合射击游戏特点的行为模式,如寻找掩护、战术移动、精确瞄准等。
在商业FPS/TPS项目中,运动层的实现需要特别关注以下方面:
- 掩护系统集成:AI需要能够识别并使用环境中的掩护物
- 战术移动:包括侧翼移动、跃进、撤退等战术动作
- 瞄准与射击:精确的瞄准系统和射击行为
- 团队协调移动:小队成员的协同移动和阵型保持
下面是针对FPS/TPS游戏的增强运动控制器实现:
using UnityEngine;
public class FPSAIMovementController : AIMovementController
{
[System.Serializable]
public class FPSMovementSettings : MovementSettings
{
public float crouchSpeedMultiplier = 0.6f;
public float sprintSpeedMultiplier = 1.5f;
public float proneSpeedMultiplier = 0.3f;
public float strafeSpeedMultiplier = 0.8f;
public float backwardsSpeedMultiplier = 0.6f;
public float coverMoveSpeed = 2.0f;
public float peekSpeed = 1.0f;
}
[Header("FPS特殊设置")]
[SerializeField]
private FPSMovementSettings fpsSettings = new FPSMovementSettings();
[Header("掩护系统")]
[SerializeField]
private CoverSystem coverSystem;
[SerializeField]
private bool isInCover;
[SerializeField]
private CoverPoint currentCover;
[Header("姿态系统")]
[SerializeField]
private PostureState currentPosture = PostureState.Standing;
[SerializeField]
private float postureTransitionSpeed = 5.0f;
[SerializeField]
private float standingHeight = 2.0f;
[SerializeField]
private float crouchingHeight = 1.2f;
[SerializeField]
private float proneHeight = 0.5f;
private float targetHeight;
private Vector3 coverPeekDirection;
private bool isPeeking;
public enum PostureState
{
Standing,
Crouching,
Prone,
InCover
}
public enum CoverPeekDirection
{
None,
Left,
Right,
Up
}
protected override void Awake()
{
base.Awake();
InitializeFPSSystems();
}
private void InitializeFPSSystems()
{
if (coverSystem == null)
{
coverSystem = GetComponent<CoverSystem>();
}
targetHeight = standingHeight;
currentPosture = PostureState.Standing;
isInCover = false;
isPeeking = false;
}
protected override void Update()
{
base.Update();
UpdatePosture();
UpdateCoverBehavior();
}
private void UpdatePosture()
{
// 平滑过渡到目标高度
if (characterController != null)
{
float currentHeight = characterController.height;
if (Mathf.Abs(currentHeight - targetHeight) > 0.01f)
{
characterController.height = Mathf.Lerp(
currentHeight,
targetHeight,
postureTransitionSpeed * Time.deltaTime
);
// 调整中心点以保持脚部在地面
Vector3 newCenter = characterController.center;
newCenter.y = characterController.height / 2f;
characterController.center = newCenter;
}
}
// 更新动画参数
if (animator != null)
{
animator.SetBool("IsCrouching", currentPosture == PostureState.Crouching);
animator.SetBool("IsProne", currentPosture == PostureState.Prone);
animator.SetBool("IsInCover", isInCover);
}
}
private void UpdateCoverBehavior()
{
if (!isInCover || currentCover == null)
{
return;
}
// 在掩护中的特殊行为
UpdateCoverMovement();
UpdatePeeking();
}
public void EnterCover(CoverPoint cover)
{
if (cover == null)
{
return;
}
currentCover = cover;
isInCover = true;
currentPosture = PostureState.InCover;
// 调整到掩护高度
targetHeight = crouchingHeight;
// 面向掩护方向
Vector3 coverDirection = cover.GetCoverDirection();
RotateTowardsDirection(-coverDirection);
// 移动到掩护位置
Vector3 coverPosition = cover.GetCoverPosition();
cachedTransform.position = coverPosition;
// 更新动画
if (animator != null)
{
animator.SetTrigger("EnterCover");
}
Debug.Log($"进入掩护: {cover.gameObject.name}");
}
public void ExitCover()
{
if (!isInCover)
{
return;
}
isInCover = false;
currentCover = null;
currentPosture = PostureState.Crouching;
// 恢复到站立高度
SetPosture(PostureState.Standing);
// 更新动画
if (animator != null)
{
animator.SetTrigger("ExitCover");
}
Debug.Log("离开掩护");
}
public void SetPosture(PostureState newPosture)
{
if (currentPosture == newPosture)
{
return;
}
// 检查姿势转换是否允许
if (!CanChangePosture(newPosture))
{
return;
}
PostureState previousPosture = currentPosture;
currentPosture = newPosture;
// 设置目标高度
switch (newPosture)
{
case PostureState.Standing:
targetHeight = standingHeight;
movementSettings.maxSpeed = fpsSettings.maxSpeed;
break;
case PostureState.Crouching:
targetHeight = crouchingHeight;
movementSettings.maxSpeed = fpsSettings.maxSpeed * fpsSettings.crouchSpeedMultiplier;
break;
case PostureState.Prone:
targetHeight = proneHeight;
movementSettings.maxSpeed = fpsSettings.maxSpeed * fpsSettings.proneSpeedMultiplier;
break;
case PostureState.InCover:
targetHeight = crouchingHeight;
movementSettings.maxSpeed = fpsSettings.coverMoveSpeed;
break;
}
// 触发姿势变化事件
OnPostureChanged(previousPosture, newPosture);
}
private bool CanChangePosture(PostureState newPosture)
{
// 检查是否有足够的空间改变姿势
if (newPosture == PostureState.Standing && currentPosture == PostureState.Prone)
{
// 检查上方空间
RaycastHit hit;
if (Physics.Raycast(
cachedTransform.position,
Vector3.up,
out hit,
standingHeight - proneHeight,
Physics.AllLayers,
QueryTriggerInteraction.Ignore
))
{
return false; // 没有足够的空间站起来
}
}
return true;
}
public void StartPeeking(CoverPeekDirection direction)
{
if (!isInCover || currentCover == null)
{
return;
}
isPeeking = true;
switch (direction)
{
case CoverPeekDirection.Left:
coverPeekDirection = -currentCover.transform.right;
break;
case CoverPeekDirection.Right:
coverPeekDirection = currentCover.transform.right;
break;
case CoverPeekDirection.Up:
coverPeekDirection = Vector3.up;
break;
default:
isPeeking = false;
return;
}
// 更新动画
if (animator != null)
{
animator.SetBool("IsPeeking", true);
animator.SetFloat("PeekDirection", (float)direction);
}
}
public void StopPeeking()
{
if (!isPeeking)
{
return;
}
isPeeking = false;
coverPeekDirection = Vector3.zero;
// 更新动画
if (animator != null)
{
animator.SetBool("IsPeeking", false);
}
}
private void UpdateCoverMovement()
{
if (!isInCover || currentCover == null)
{
return;
}
// 沿着掩护移动
Vector3 coverDirection = currentCover.GetCoverDirection();
Vector3 moveAlongCover = Vector3.Cross(coverDirection, Vector3.up).normalized;
// 限制移动范围在掩护长度内
float maxMovement = currentCover.GetCoverLength() / 2f;
float currentOffset = GetCoverOffset();
if (Mathf.Abs(currentOffset) >= maxMovement)
{
// 到达掩护边缘
moveDirection = Vector3.zero;
}
else
{
// 允许沿着掩护移动
moveDirection = moveAlongCover;
}
}
private void UpdatePeeking()
{
if (!isPeeking || currentCover == null)
{
return;
}
// 执行窥视移动
Vector3 peekMovement = coverPeekDirection * fpsSettings.peekSpeed * Time.deltaTime;
// 检查窥视是否安全
if (IsPeekSafe(coverPeekDirection))
{
characterController.Move(peekMovement);
}
else
{
StopPeeking();
}
}
private bool IsPeekSafe(Vector3 peekDirection)
{
if (currentCover == null)
{
return false;
}
// 检查窥视方向是否安全(无敌人视线)
Vector3 peekPosition = cachedTransform.position + peekDirection * 0.5f;
// 在实际项目中,这里会检查是否有敌人在这个方向
// 简化实现:总是返回安全
return true;
}
private float GetCoverOffset()
{
if (currentCover == null)
{
return 0f;
}
Vector3 coverToAI = cachedTransform.position - currentCover.transform.position;
Vector3 coverDirection = currentCover.GetCoverDirection();
Vector3 coverRight = Vector3.Cross(coverDirection, Vector3.up).normalized;
return Vector3.Dot(coverToAI, coverRight);
}
public void Sprint(bool startSprinting)
{
if (startSprinting)
{
if (currentPosture == PostureState.Standing)
{
movementSettings.maxSpeed = fpsSettings.maxSpeed * fpsSettings.sprintSpeedMultiplier;
if (animator != null)
{
animator.SetBool("IsSprinting", true);
}
}
}
else
{
movementSettings.maxSpeed = fpsSettings.maxSpeed;
if (animator != null)
{
animator.SetBool("IsSprinting", false);
}
}
}
public void Strafe(Vector3 direction)
{
// 侧向移动
if (direction.magnitude > 0.1f)
{
moveDirection = direction.normalized;
movementSettings.maxSpeed = fpsSettings.maxSpeed * fpsSettings.strafeSpeedMultiplier;
}
}
public void MoveBackwards(Vector3 direction)
{
// 后退移动
if (direction.magnitude > 0.1f)
{
moveDirection = direction.normalized;
movementSettings.maxSpeed = fpsSettings.maxSpeed * fpsSettings.backwardsSpeedMultiplier;
}
}
public bool IsInCover()
{
return isInCover;
}
public CoverPoint GetCurrentCover()
{
return currentCover;
}
public PostureState GetCurrentPosture()
{
return currentPosture;
}
public event Action<PostureState, PostureState> OnPostureChanged = delegate { };
protected override void OnDrawGizmosSelected()
{
base.OnDrawGizmosSelected();
if (!Application.isPlaying)
{
return;
}
// 绘制掩护信息
if (isInCover && currentCover != null)
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(currentCover.transform.position, 0.5f);
Gizmos.DrawLine(cachedTransform.position, currentCover.transform.position);
// 绘制掩护方向
Vector3 coverDirection = currentCover.GetCoverDirection();
Gizmos.DrawRay(currentCover.transform.position, coverDirection * 2f);
// 绘制掩护范围
float coverLength = currentCover.GetCoverLength();
Vector3 coverRight = Vector3.Cross(coverDirection, Vector3.up).normalized;
Vector3 coverStart = currentCover.transform.position - coverRight * coverLength / 2f;
Vector3 coverEnd = currentCover.transform.position + coverRight * coverLength / 2f;
Gizmos.DrawLine(coverStart, coverEnd);
}
// 绘制姿势信息
Gizmos.color = Color.green;
string postureText = $"姿势: {currentPosture}";
#if UNITY_EDITOR
UnityEditor.Handles.Label(
cachedTransform.position + Vector3.up * 2.2f,
postureText
);
#endif
}
}
[System.Serializable]
public class CoverPoint : MonoBehaviour
{
[SerializeField]
private float coverLength = 5.0f;
[SerializeField]
private float coverHeight = 1.5f;
[SerializeField]
private CoverType coverType = CoverType.Full;
[SerializeField]
private Vector3 coverDirection = Vector3.forward;
public enum CoverType
{
Full,
Half,
Low,
Destructible
}
public Vector3 GetCoverPosition()
{
return transform.position;
}
public Vector3 GetCoverDirection()
{
return transform.TransformDirection(coverDirection).normalized;
}
public float GetCoverLength()
{
return coverLength;
}
public float GetCoverHeight()
{
return coverHeight;
}
public CoverType GetCoverType()
{
return coverType;
}
public bool IsOccupied()
{
// 检查是否已被占用
Collider[] colliders = Physics.OverlapBox(
transform.position,
new Vector3(coverLength / 2f, 1f, 1f),
transform.rotation
);
foreach (Collider collider in colliders)
{
if (collider.CompareTag("AI") && collider.gameObject != gameObject)
{
return true;
}
}
return false;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(
transform.position,
new Vector3(coverLength, coverHeight, 0.5f)
);
// 绘制掩护方向
Gizmos.color = Color.red;
Vector3 direction = transform.TransformDirection(coverDirection).normalized;
Gizmos.DrawRay(transform.position, direction * 2f);
}
}
这个增强的运动控制器为FPS/TPS游戏提供了专门的移动能力,包括掩护系统、多种姿态(站立、蹲下、匍匐)、战术移动(冲刺、侧移、后退)以及精确的瞄准支持。在实际商业项目中,这些功能可以根据具体游戏需求进一步扩展和优化。
通过本章介绍的完整AI架构系统,开发者可以在Unity中构建出强大、灵活且高性能的游戏人工智能。这些系统不仅提供了基础的AI功能,还考虑了商业项目中的实际需求,如性能优化、调试支持、配置管理和团队协作等。无论是独立游戏还是大型商业项目,这套架构都能为AI开发提供坚实的基础。
更多推荐


所有评论(0)