状态机C#
我正在与C#联合进行一个项目,我希望有两架无人机在房间里游荡,然后用状态机互相攻击。 我有三个类AttackState、ChaseState和WonderState 例如,这是我的WanderState类:状态机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
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);
}
}