因此,对于我正在开发的游戏,我为敌人和老板人工智能使用基于继承的有限状态系统。然而,我在实施过程中遇到了一些问题。
基本状态类由每个状态继承,即AirPatrol状态继承自“EnemyState”。但是,AirPatrol 类具有我想从类外部访问的变量,例如“moveSpeed”、“aggroDistance”等(EnemyState 没有),因此我将它们公开。在敌人的状态机类(管理切换状态等)中,我有一个公共“currentState”变量,它保持当前状态。
但是,如果我尝试引用 currentState.moveSpeed 我会收到“不包含定义”错误。我理解为什么这不起作用,因为并非每个 EnemyState 都会有“moveSpeed”变量,但是有没有一种简单/可靠的方法可以进行此类变量修改,而无需将速度变量添加到基本 EnemyState 类中?
以下是脚本:
安全无人机人工智能课程(这是我的问题)
public class SecurityDroneAI : EnemyController
{
[Header("Movement")]
public float patrolSpeed = 3.0f;
public float aggroSpeed = 5.0f;
[SerializeField] float aggroDistance = 20f;
public float acceleration = 2f;
[Header("Pathfinding")]
public float pathUpdateDelay = 1.0f;
public List<Vector2> patrolPositions = new List<Vector2>();
public float nextWaypointDistance = 2;
Animator anim;
Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
SetNextState(new AirPatrol());
nextState.speed = 1; // HERE IS MY PROBLEM >:(
}
private void Update()
{
anim.SetBool("seeking", currentState.GetType() == typeof(AirPatrol));
float rot = -rb.velocity.x * 3;
}
}
敌国级
public class EnemyState
{
public Rigidbody2D rb;
public Animator anim;
public Transform transform;
public EnemyController controller;
public virtual void OnEnter(EnemyController parentController)
{
controller = parentController;
rb = controller.GetComponent<Rigidbody2D>();
anim = controller.GetComponentInChildren<Animator>();
transform = controller.transform;
}
public virtual void OnUpdate()
{
}
public virtual void OnFixedUpdate()
{
}
public virtual void OnLateUpdate()
{
}
public virtual void OnExit()
{
}
}
空中巡逻班
public class AirPatrol : EnemyState
{
public List<Vector2> patrolPositions = new List<Vector2>(); // List of positions to patrol between
public float speed = 3.0f; // Movement speed
public float acceleration = 2f; // Acceleration
public float pathUpdateDelay = 1.0f; // How often to update the path
public float nextWaypointDistance = 1.5f; // How far the patroller should check for the next waypoint
int positionIndex; // Index of the target position in patrolPositions
int currentWaypoint = 0; // Index of the current target waypoint on the current path
float timeSinceUpdatedPath; // Time since last generated path
Path path; // Current path
public Seeker seeker; // Seeker component for A* pathfinding
public override void OnEnter(EnemyController parentController)
{
base.OnEnter(parentController);
positionIndex = 0;
timeSinceUpdatedPath = 0;
}
public override void OnUpdate()
{
base.OnUpdate();
if (timeSinceUpdatedPath <= 0) // Update path if delayed enough
{
UpdatePath();
timeSinceUpdatedPath = pathUpdateDelay;
}
timeSinceUpdatedPath += Time.deltaTime;
if (path == null) { return; }
if (currentWaypoint >= path.vectorPath.Count) // At end of the path
{
positionIndex = positionIndex + 1 >= patrolPositions.Count ? 0 : positionIndex + 1; // Iterate to next patrol point
UpdatePath();
return;
}
MoveAlongPath();
}
private void MoveAlongPath()
{
Vector2 direction = (path.vectorPath[currentWaypoint] - transform.position).normalized;
rb.velocity = Vector3.Lerp(rb.velocity, direction * speed, acceleration * Time.deltaTime);
float distance = Vector2.Distance(rb.position, path.vectorPath[currentWaypoint]);
if (distance < nextWaypointDistance)
{
currentWaypoint++;
}
}
private void UpdatePath()
{
if (!seeker.IsDone()) { return; }
seeker.StartPath(transform.position, patrolPositions[positionIndex], SetPath);
}
private void SetPath(Path p)
{
if (p.error) { return; }
path = p;
currentWaypoint = 0;
}
}
敌人控制者等级
public class EnemyController : MonoBehaviour
{
public EnemyState mainStateType;
public EnemyState currentState;
public EnemyState nextState;
private void Update()
{
if (nextState != null)
{
SetState(nextState);
}
if (currentState != null) { currentState.OnUpdate(); }
}
private void LateUpdate()
{
if (currentState != null) { currentState.OnLateUpdate(); }
}
private void FixedUpdate()
{
if (currentState != null) { currentState.OnFixedUpdate(); }
}
private void SetState(EnemyState newState)
{
nextState = null;
if (currentState != null)
{
currentState.OnExit();
}
currentState = newState;
currentState.OnEnter(this);
}
public void SetNextState(EnemyState newState)
{
if (newState != null)
{
nextState = newState;
}
}
}
任何形式的帮助将不胜感激! :)
哈哈,对于其他需要答案的人,我在提出这个问题后几乎立即想到了一个答案,有趣的是世界是如何运作的!
解决方案是将新状态转换为特定的 AirPatrol 变量,然后对其进行修改。如果有人可以教我,更好的方法将不胜感激!
更改的脚本:
private void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
AirPatrol patrolState = new AirPatrol();
patrolState.speed = 1;
SetNextState(patrolState);
}