I just came across a bug where the currently selected unit is shot by the enemy units and the game fails to transfer the unit selection over to the next one available, which essentially leaves the currently active unit to be a ghost.
When doing the next action (unless the player first clicks on the other on to select it instead), consequently I get an error:
MissingReferenceException: The object of type 'Unit' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
Unit.GetWorldPosition () (at Assets/Scripts/Unit.cs:94)
CameraManager.BaseAction_OnAnyActionStarted (System.Object sender, System.EventArgs e) (at Assets/Scripts/CameraManager.cs:39)
BaseAction.ActionStart (System.Action onActionComplete) (at Assets/Scripts/Actions/BaseAction.cs:49)
ShootAction.TakeAction (GridPosition gridPosition, System.Action onCompleteAction) (at Assets/Scripts/Actions/ShootAction.cs:112)
UnitActionSystem.HandleSelectedAction () (at Assets/Scripts/UnitActionSystem.cs:92)
UnitActionSystem.Update () (at Assets/Scripts/UnitActionSystem.cs:77)
It seems it was already discussed here: Unit that dies while selected still has move action
I would think it shouldn’t be the UnitActionSystem
trying to re-assign the selected unit from within its Update()
(safeguarding against “no unit selected” should be added to it, of course), but rather that the OnDead
event from the healthsystem should trigger a re-selection in some way, which would avoid the possibility of trying to find another unit in every update…
So these are my changes in the UnitActionSystem
:
// In Start()
Unit.OnAnyUnitDead += Unit_OnAnyUnitDead;
// null protection within Update()
{
//...
// Currently active unit has died on the previous enemy turn, or all player units are dead
if (null == selectedUnit)
{
return;
}
HandleSelectedAction();
}
// And implement handling the event
private void Unit_OnAnyUnitDead(object sender, EventArgs e)
{
if (TurnSystem.Instance.IsPlayerTurn)
{
if (UnitManager.Instance.GetFriendlyUnityList().Count > 0)
{
SetSelectedUnit(UnitManager.Instance.GetFriendlyUnityList()[0]);
}
else
{
Debug.Log("Game Over, all player units died");
selectedUnit = null;
}
}
}
Since we already have the UnitManager
keeping track of units, we can simply ask it to give us the first in the list.
Updating the UI would also need some null
safeguard:
private void CreateUnitActionButtons()
{
ClearUnitActionButtons();
Unit selectedUnit = UnitActionSystem.Instance.GetSelectedUnit();
if(null == selectedUnit)
{
return;
}
//...
}