Answer the question
In order to leave comments, you need to log in
I can't find a bug in the implementation of the State pattern (StateMachine)?
Good evening. How it should work: characters spawn on my stage (Character.cs), I click one at a time, it goes into the selected state, then I click on the place and it goes there. BUT. They all go to the same place! That is, I click on one, then on the place, and they all go there.
I studied all the code, double-checked everything I could, but I could not figure it out. Perhaps some knowledge is not enough.
Scripts:
1. StateMachine - stores the current state
2. State - an abstract class, states are inherited from it
3. SelectState - the state of the selected character
4. UnselectState the state of the NOT selected character
5. Character - the
StateMachine object itself (1)
public class StateMachine
{
public State CurrentState { get; private set; }
public void Initialize(State startingState)
{
CurrentState = startingState;
startingState.Enter();
}
public void ChangeState(State newState)
{
CurrentState.Exit();
CurrentState = newState;
newState.Enter();
}
}
public abstract class State
{
protected Character character;
protected StateMachine stateMachine;
protected State(Character _character, StateMachine _stateMachine)
{
character = _character;
stateMachine = _stateMachine;
}
public virtual void Enter(){}
public virtual void HandleInput(){}
public virtual void Exit() {}
public void ForEveryone(){}
}
public class SelectState : State
{
public SelectState(Character character, StateMachine stateMachine) : base(character, stateMachine) { }
public override void HandleInput()
{
base.HandleInput();
if (Input.GetMouseButtonDown(0))
{
var hit = character.Ray();
character.agent.SetDestination(hit.point);
character.stateMachine.ChangeState(character.unselect);
}
}
}
public class UnselectedState : State
{
public UnselectedState(Character character, StateMachine stateMachine) : base(character, stateMachine) { }
public override void HandleInput()
{
base.HandleInput();
if (Input.GetMouseButtonDown(0))
{
var hit = character.Ray();
if (hit.collider.gameObject.tag == "Agent") character.stateMachine.ChangeState(character.select);
else return;
}
}
}
public class Character : MonoBehaviour, IPooledObject //интерфейс для пулинга персонажей
{
[NonSerialized] public StateMachine stateMachine;
[NonSerialized] public SelectState select;
[NonSerialized] public UnselectedState unselect;
[NonSerialized] public NavMeshAgent agent;
public void OnObjectSpawn() //персонажи спавнятся из пула. В этот момент они создаются
{
stateMachine = new StateMachine();
select = new SelectState(this, stateMachine);
unselect = new UnselectedState(this, stateMachine);
stateMachine.Initialize(unselect); //выбираем изначальное состояние
agent = GetComponent<NavMeshAgent>();
}
public void Update()
{
stateMachine.CurrentState.HandleInput();
}
public RaycastHit Ray()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, Mathf.Infinity)) return hit;
return hit;
}
}
Answer the question
In order to leave comments, you need to log in
public GameObject[] goArray;
public void Awake(){
foreach (var go in goArray)
go.GetComponent<Character>().isSelected = false;
}
public GameObject selected{//Вернет выделенного персонажа, если нет такого то null
get{
foreach (var go in goArray)
if (go.GetComponent<Character>().isSelected)
return go;
return null;
}
}
public void Update(){
if (Input.GetMouseButtonDown(0)){
var hit = Ray();
if (hit.collider.gameObject.tag == "Agent"){
var _ch = hit.collider.gameObject.GetComponent<Character>();
if(selected != null)
selected.isSelected = false;
_ch.isSelected = true;
} else if (hit.collider.gameObject.tag == "Ground"){
if(selected != null)
selected.GetComponent<Character>().agent.SetDestination(hit.point);
}
else if (selected != null)
selected.isSelected = false;
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question