状态机C#

状态机C#,c#,unity3d,C#,Unity3d,我正在与C#联合进行一个项目,我希望有两架无人机在房间里游荡,然后用状态机互相攻击。 我有三个类AttackState、ChaseState和WonderState 例如,这是我的WanderState类: using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; using System.Linq; using System; using UnityEngine

我正在与C#联合进行一个项目,我希望有两架无人机在房间里游荡,然后用状态机互相攻击。 我有三个类AttackState、ChaseState和WonderState

例如,这是我的WanderState类:

using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Linq;
using System;
using UnityEngine;

public class WanderState : BaseState
{
    private Vector3? _destination;
    private float stopDistance = 1.5f;     
    private float turnSpeed = 1f;
    private readonly LayerMask _layerMask = LayerMask.NameToLayer("Walls");
    private float _rayDistance = 5.0f;         
    private Quaternion _desiredRotation;
    private Vector3 _direction;
    private Drone _drone;

    public WanderState(Drone drone) : base(drone.gameObject)
    {
        _drone = drone;
    }

    public override Type Tick()
    {
        var chaseTarget = CheckForAggro();

        if (chaseTarget != null)
        {
            _drone.SetTarget(chaseTarget);
            return typeof(ChaseState);
        }

        if (_destination.HasValue == false || Vector3.Distance(transform.position, _destination.Value) <= stopDistance)
        {
            FindRandomDestination();
        }

        transform.rotation = Quaternion.Slerp(transform.rotation, _desiredRotation, Time.deltaTime * turnSpeed);    //Time.deltaTime * turnSpeed

        if (IsForwardBlocked())     //IsForwardBlocked()
        {
          transform.rotation = Quaternion.Lerp(transform.rotation, _desiredRotation, 0.2f);

       }
       else
       {
         float droneSpeed = 2f;
         transform.Translate(Vector3.forward * Time.deltaTime * droneSpeed);     
        }

        Debug.DrawRay(transform.position, _direction * _rayDistance, Color.red);

        while (IsPathBlocked())
        {
            FindRandomDestination();
            Debug.Log("Wall");
        }

        return null;
    }

    private bool IsForwardBlocked()
    {
        Ray ray = new Ray(transform.position, transform.forward);
        return Physics.SphereCast(ray, 0.5f, _rayDistance, _layerMask);
    }


    private bool IsPathBlocked()
    {
        Rigidbody obj = new Rigidbody();
        Ray ray = new Ray(transform.position, _direction);

        return Physics.SphereCast(ray, 0.5f, _rayDistance, _layerMask);
    }


    private void FindRandomDestination()
    {
        Vector3 testPosition = (transform.position + (transform.forward * 4f)) + new Vector3(UnityEngine.Random.Range(-4.5f, 4.5f), 0f,UnityEngine.Random.Range(-4.5f, 4.5f));

        _destination = new Vector3(testPosition.x, 1f, testPosition.z);

        _direction = Vector3.Normalize(_destination.Value - transform.position);
        _direction = new Vector3(_direction.x, 0f, _direction.z);
        _desiredRotation = Quaternion.LookRotation(_direction);

        Debug.Log("Got direction");
    }

    Quaternion startingAngle = Quaternion.AngleAxis(-60, Vector3.up);
    Quaternion stepAngle = Quaternion.AngleAxis(5, Vector3.up);

    private Transform CheckForAggro()
    {
        float aggroRadius = 5f;

        RaycastHit hit;
        var angle = transform.rotation * startingAngle;
        var direction = angle * Vector3.forward;
        var pos = transform.position;
        for (var i = 0; i < 24; i++)
        {
            if (Physics.Raycast(pos, direction, out hit, aggroRadius))
            {
                var drone = hit.collider.GetComponent<Drone>();
                if (drone != null && drone.Team1 != gameObject.GetComponent<Drone>().Team1)
                {
                    Debug.DrawRay(pos, direction * hit.distance, Color.red);
                    return drone.transform;
                }
                else
                {
                    Debug.DrawRay(pos, direction * hit.distance, Color.yellow);
                }
            }
            else
            {
                Debug.DrawRay(pos, direction * aggroRadius, Color.white);
            }
            direction = stepAngle * direction;
        }

        return null;
    }
}
使用系统集合;
使用System.Collections.Generic;
使用System.Security.Cryptography;
使用System.Linq;
使用制度;
使用UnityEngine;
公共类状态:BaseState
{
专用矢量3?\u目的地;
私人浮动停车距离=1.5f;
专用浮球转速=1f;
私有只读LayerMask _LayerMask=LayerMask.NameToLayer(“墙”);
私人浮动距离=5.0f;
私有四元数的理想旋转;
专用矢量3_方向;
私人无人机;
公共漫游状态(无人机):基地(无人机。游戏对象)
{
_无人机=无人机;
}
公共重写类型Tick()
{
var chaseTarget=CheckForAggro();
if(chaseTarget!=null)
{
_无人机设定目标(追逐目标);
返回类型(状态);
}
如果(_destination.HasValue==false | | Vector3.Distance(transform.position,_destination.Value)_团队;
公共StateMachine StateMachine=>GetComponent();
私人空间
{
初始化EstateMachine();
}
private void InitializeStateMachine()
{
var states=新字典()
{
{typeof(WanderState),新的WanderState(this)},
{typeof(ChaseState),new ChaseState(this)},
{typeof(AttackState),new AttackState(this)}
};
GetComponent().SetStates(状态);
}
公共无效设置目标(转换目标)
{
目标=目标;
}
公共无效防火墙()
{
_laserVisual.transform.position=(Target.position+transform.position)/2f;
浮动距离=矢量3.距离(a:目标位置,b:变换位置);
_laserVisual.transform.localScale=新矢量3(0.1f,0.1f,距离);
_laserVisual.SetActive(真);
启动例行程序(关闭激光器());
}
公共IEnumerator关闭激光器()
{
收益率返回新WaitForSeconds(0.25f);
_laserVisual.SetActive(假);
如果(目标!=null)
{
摧毁(Target.GameObject);
}
}
公共普查小组
{
红色
蓝色
}
公共类状态机:单行为
{
私人字典(可供查阅);;
公共BaseState当前状态{get;private set;}
公共事件行为发生变化;
公共无效集合状态(字典状态)
{
_可用房地产=州;
}
私有void更新()
{
如果(CurrentState==null)
{
CurrentState=_availableEstates.Values.First();
}
var nextState=CurrentState?.Tick();
if(nextState!=null&&nextState!=CurrentState.GetType())
{
切换到新状态(下一状态);
}
}
public void SwitchToNewState(类型nextState)
{
CurrentState=_AvailableEstate[nextState];
OnStateChanged?.Invoke(当前状态);
}
}
我面临的问题是,我的无人机正在穿过房间的墙壁

我尝试为墙壁设置网格碰撞器或长方体碰撞器,但这些选项都不起作用。此外,对于无人机,我有一个球体碰撞器


有人知道为什么会出现这种行为吗?我可以做些什么来修复它?

向无人机添加刚体,并确保未选中IsKinetic。

我尝试了你所说的,但是如果IsKinetic属性未选中,无人机对象将开始飞出房间。如果属性被选中,它们的行为正常,但仍会通过walls。也许我也应该在地板上添加一个属性?我尝试了刚体,但仍然不起作用。你有其他建议吗,因为我卡住了,我真的需要做这个项目。
public class Drone : MonoBehaviour
{

    [SerializeField] private Team _team;
    [SerializeField] private GameObject _laserVisual;

    public Transform Target { get; private set; }

    public Team Team1=> _team;

    public StateMachine StateMachine => GetComponent<StateMachine>();

    private void Awake()
    {
        InitializeStateMachine();
    }

    private void InitializeStateMachine()
    {
        var states = new Dictionary<Type, BaseState>()
        {
            {typeof(WanderState), new WanderState(this) },
            {typeof(ChaseState), new ChaseState(this) },
            {typeof(AttackState), new AttackState(this) }
        };

        GetComponent<StateMachine>().SetStates(states);
    }

    public void SetTarget(Transform target)
    {
        Target = Target;
    }

    public void FireWeapon()
    {
        _laserVisual.transform.position = (Target.position + transform.position) / 2f;

        float distance = Vector3.Distance(a: Target.position, b: transform.position);
        _laserVisual.transform.localScale = new Vector3(0.1f, 0.1f, distance);
        _laserVisual.SetActive(true);

        StartCoroutine(TurnOffLaser());
    }

    public IEnumerator TurnOffLaser()
    {
        yield return new WaitForSeconds(0.25f);
        _laserVisual.SetActive(false);

        if (Target != null)
        {
            GameObject.Destroy(Target.gameObject);
        }
    }


    public enum Team
    {
        Red,
        Blue
    }
public class StateMachine : MonoBehaviour
{
    private Dictionary<Type, BaseState> _availableStates;

    public BaseState CurrentState { get; private set; }

    public event Action<BaseState> OnStateChanged;

    public void SetStates(Dictionary<Type, BaseState> states)
    {
        _availableStates = states;
    }

    private void Update()
    {
        if(CurrentState == null)
        {
            CurrentState = _availableStates.Values.First();
        }

        var nextState = CurrentState?.Tick();

        if (nextState != null && nextState != CurrentState.GetType())
        {
            SwitchToNewState(nextState);
        }
    }

    public void SwitchToNewState(Type nextState)
    {
        CurrentState = _availableStates[nextState];
        OnStateChanged?.Invoke(CurrentState);
    }
}