I’ve managed to get some automatic goal/target markers working, though it could do with a bit more polish. Read the issues at the bottom of this post before deciding to implement this. Also: you MUST have my ‘multiple goals’ script, posted above, to use this code.
You need to add some code to the GUIManager script and create a couple of new prefabs.
NOTE: I’m not posting the complete script because it contains a lot of custom stuff that is specific to my modifications to the engine, and the script would break your game, so follow the steps below carefully, and post here if you get stuck
1) Add the following variables to the top of the GUIManager script
// these will hold our marker prefab items, which will be instantiated as needed
public GameObject targetMarkerPrefab;
public GameObject goalMarkerPrefab;
// this will hold the goalslist, which will be extracted from the Overlord object, in the GoalManager script
// this assumes you have implemented my GoalManager script, where the targets/goals are stored in an array of GoalAndTarget class
GoalManager.GoalAndTarget[ ] GoalsList;
// arrays to store the markers, which will be instantiated when required
// the original ‘markers’ array will not be used for the target/goals, but will still be used to show the ‘tick’ when a level is won
List targetMarkers;
List goalMarkers;
2) In the GUIManager script’s Start() method, add the following lines BEFORE the ‘StartCoroutine(ShowMarkers(2)));’ command
// get the level target(s) and goal(s)
// this is coded to work with arrays (to allow for multiple targets and goals), and this will only work correctly in conjunction with a modified GoalManager script
GoalsList = GameObject.Find (“Overlord”).GetComponent().GoalsList;
// initialize our lists
targetMarkers = new List();
goalMarkers = new List();
// create all the markers required and set their scale to 0,0,0 (so they are not visible until needed)
foreach (GoalManager.GoalAndTarget targetAndGoal in GoalsList)
{
// create a new target marker for each target at the target’s position and set the marker’s scale to 0
GameObject newTarget = Instantiate(targetMarkerPrefab, targetAndGoal.target.rigidbody2D.transform.position, targetAndGoal.target.rigidbody2D.transform.rotation) as GameObject;
newTarget.rigidbody2D.transform.localScale = new Vector3(0,0,1);
targetMarkers.Add(newTarget);
// do the same for the goal marker(s)
// note: this will create duplicates if the same goal object is used for multiple targets, but they will simply overlap and appear as one, so it shouldn’t be a problem
// there may be room for optimisation here
// check for null goals, which are required for the balloon popping target
if (targetAndGoal.goal)
{
GameObject newGoal = Instantiate(goalMarkerPrefab, targetAndGoal.goal.rigidbody2D.transform.position, targetAndGoal.goal.rigidbody2D.transform.rotation) as GameObject;
newGoal.rigidbody2D.transform.localScale=new Vector3(0,0,1);
goalMarkers.Add(newGoal);
}
3) Replace the HideMarkers method with the following code (I recommend commenting out the original to keep it handy)
void HideMarkers()
{
markersVisible = false;
StopCoroutine(“ShowMarkers”);
// replacement code for the new method of showing markers
foreach (GameObject targetMarker in targetMarkers)
targetMarker.rigidbody2D.transform.localScale = new Vector3(0,0,1);
foreach (GameObject goalMarker in goalMarkers)
goalMarker.rigidbody2D.transform.localScale = new Vector3(0,0,1);
}
4) Replace the ShowMarkers method with the following (comment out the original again)
IEnumerator ShowMarkers(float showTime)
{
markersVisible = true;
yield return new WaitForSeconds(1);
//Scale up the markers
foreach (GameObject targetMarker in targetMarkers)
StartCoroutine(ScaleObject(targetMarker.transform, Vector2.one, 0.25f, 0));
foreach (GameObject goalMarker in goalMarkers)
StartCoroutine(ScaleObject(goalMarker.transform, Vector2.one, 0.25f, 0));
yield return new WaitForSeconds(showTime);
//Scale down the markers to zero
foreach (GameObject targetMarker in targetMarkers)
targetMarker.transform.localScale= Vector2.zero;
foreach (GameObject goalMarker in goalMarkers)
goalMarker.transform.localScale= Vector2.zero;
markersVisible = false;
}
- Create 2 new prefabs from the markers in GUIManager > Markers by dragging goalMarker and targetMarker into your Prefabs folder.
- Add a Rigidbody2D to the 2 new prefabs, and make them kinematic, 0 mass, and 0 gravity scale (so they don’t interact with the scene)
- Select the GUIManager and you will have two empty variables in the editor called ‘Target Marker Prefab’ and ‘Goal Marker Prefab’. Drag your new prefabs into the appropriate slots.
Now your levels will automatically display markers for all goals/targets, and you don’t even have to place them yourself!
ISSUES
This is a quick and dirty implementation. The default marker for the goal is an arrow, and this will display in the centre of the goal item, so you should change this (shouldn’t be too hard). I am thinking of maybe implementing a few different types of marker to use depending on the items and their location (e.g. an arrow pointing to the right placed to the left of the goal so it points AT the goal).
With multiple goals or targets there is no indication which goal goes with which target (only a problem if you use different goals for the targets). I will try to implement a way to get around this, such as different coloured markers for each goal/target pair.
EDIT: New issue: If you use the ‘empty target’ prefab in your game you will need to add a rigidbody2D to it due to the way my code accesses the item’s position (so it knows where to place the marker). Add it in the same way you add it to the other prefabs (kinematic, not mass, no gravity).
EDIT2: Added check for a null goal in case the target is popping a balloon (which has no associated goal). Null goals are simply ignored