Since each location has its own MiniLocation component, each was registering its own instance of the OnMenuElementClick event, causing it to be run multiple times.
Best way around this is to split the script into two: MiniLocation (attached to each location object) and MiniLocationNavigator (just one instance attached to a new empty GameObject):
MiniLocation.cs:
using System;
using UnityEngine;
using UnityEngine.UI;
using AC;
public class MiniLocation : MonoBehaviour
{
public Direction up = new Direction ("up");
public Direction down = new Direction ("down");
public Direction left = new Direction ("left");
public Direction right = new Direction ("right");
public _Camera camera;
public ActionList actionListOnEnter;
public static MiniLocation activeMiniLocation { get; private set; }
private const string menuName = "MoveDirection";
[ContextMenu ("Enter")]
public void Enter ()
{
activeMiniLocation = this;
KickStarter.mainCamera.SetGameCamera (camera);
if (actionListOnEnter) actionListOnEnter.Interact ();
UpdateMenu ();
}
[ContextMenu ("GoUp")]
public void GoUp () { Move (up); }
[ContextMenu ("GoDown")]
public void GoDown () { Move (down); }
[ContextMenu ("GoLeft")]
public void GoLeft () { Move (left); }
[ContextMenu ("GoRight")]
public void GoRight () { Move (right); }
public void EnableUp () { SetDirectionState (up, true); }
public void DisableUp () { SetDirectionState (up, false); }
public void EnableDown () { SetDirectionState (down, true); }
public void DisableDown () { SetDirectionState (down, false); }
public void EnableLeft () { SetDirectionState (left, true); }
public void DisableLeft () { SetDirectionState (left, false); }
public void EnableRight () { SetDirectionState (right, true); }
public void DisableRight () { SetDirectionState (right, false); }
private void SetDirectionState (Direction direction, bool state)
{
direction.isEnabled = state;
if (activeMiniLocation == this) UpdateMenu ();
}
private void Move (Direction direction)
{
if (direction.isEnabled && direction.miniLocation)
{
direction.miniLocation.Enter ();
}
}
private void UpdateMenu ()
{
Menu moveDirectionMenu = PlayerMenus.GetMenuWithName (menuName);
up.UpdateUIButton (moveDirectionMenu);
down.UpdateUIButton (moveDirectionMenu);
left.UpdateUIButton (moveDirectionMenu);
right.UpdateUIButton (moveDirectionMenu);
moveDirectionMenu.ResetVisibleElements ();
moveDirectionMenu.Recalculate ();
}
[Serializable]
public class Direction
{
public bool isEnabled;
public MiniLocation miniLocation;
public string elementName;
public Direction (string _elementName)
{
elementName = _elementName;
}
public void UpdateUIButton (Menu menu)
{
MenuButton button = menu.GetElementWithName (elementName) as MenuButton;
button.IsVisible = isEnabled;
}
private void Move ()
{
if (isEnabled && miniLocation)
{
miniLocation.Enter ();
}
}
}
}
MiniLocationNavigator.cs:
using UnityEngine;
using AC;
public class MiniLocationNavigator : MonoBehaviour
{
private const string menuName = "MoveDirection";
private void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
private void OnDisable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
private void OnMenuElementClick (Menu _menu, MenuElement _element, int _slot, int buttonPressed)
{
if (_menu.title == menuName && MiniLocation.activeMiniLocation)
{
if (MiniLocation.activeMiniLocation.up.elementName == _element.title) MiniLocation.activeMiniLocation.GoUp ();
else if (MiniLocation.activeMiniLocation.down.elementName == _element.title) MiniLocation.activeMiniLocation.GoDown ();
else if (MiniLocation.activeMiniLocation.left.elementName == _element.title) MiniLocation.activeMiniLocation.GoLeft ();
else if (MiniLocation.activeMiniLocation.right.elementName == _element.title) MiniLocation.activeMiniLocation.GoRight ();
}
}
}
Chris! That's it. It works perfectly. I tested it as well with Saving and Loading. It works beautifully. I wanted the Camera to Crossfade, so I added this code (just included the top 30 lines for context):
using System;
using UnityEngine;
using UnityEngine.UI;
using AC;
public class MiniLocation : MonoBehaviour
{
public Direction up = new Direction ("up");
public Direction down = new Direction ("down");
public Direction left = new Direction ("left");
public Direction right = new Direction ("right");
public _Camera camera;
public ActionList actionListOnEnter;
public static MiniLocation activeMiniLocation { get; private set; }
private const string menuName = "MoveDirection";
[SerializeField]
private float crossfadeTime = 0.25f;
[ContextMenu ("Enter")]
public void Enter ()
{
activeMiniLocation = this;
KickStarter.mainCamera.Crossfade (crossfadeTime, camera, _fadeCurve : new AnimationCurve (new Keyframe(0, 0, 1, 1), new Keyframe(1, 1, 1, 1)));
if (actionListOnEnter) actionListOnEnter.Interact ();
UpdateMenu ();
}
It functions great. Does that look OK to you?
If that's alright, I think it's time I go through the game and redo all my navigation. What fun!
Comments
Apologies - I was being stupid.
Since each location has its own MiniLocation component, each was registering its own instance of the OnMenuElementClick event, causing it to be run multiple times.
Best way around this is to split the script into two: MiniLocation (attached to each location object) and MiniLocationNavigator (just one instance attached to a new empty GameObject):
MiniLocation.cs:
MiniLocationNavigator.cs:
Chris! That's it. It works perfectly. I tested it as well with Saving and Loading. It works beautifully. I wanted the Camera to Crossfade, so I added this code (just included the top 30 lines for context):
It functions great. Does that look OK to you?
If that's alright, I think it's time I go through the game and redo all my navigation. What fun!